7

我有一个非常简单的问题,QEMU 是否模拟 TLB?当客户 linux 系统执行“invlpg”指令时会发生什么,因为它是为了使 TLB 条目无效。我知道 QEMU 有 softmmu链接,用于将客户虚拟地址转换为主机虚拟地址,但 QEMU 是否模拟实际的 TLB,以及“invlpg”指令的效果是什么。还是 QEMU 只是忽略了这条指令?

4

2 回答 2

7

答案介于“是”和“否”之间。QEMU 不会尝试模拟实际客户 CPU 的 TLB(这是一种加速从客户虚拟地址到客户物理地址的查找的硬件)。然而,它确实实现了自己的非常相似的数据结构,称为 TLB——这加速了从客户虚拟地址直接到 RAM 的主机虚拟地址的查找,或者从客户虚拟地址到仿真设备的读/写功能的查找。

由于 CPU TLB 和 QEMU 的 TLB 之间有相似之处,我们可以使用 guest 指令使 TLB 无效或以其他方式操作 TLB 作为触发器来执行 QEMU TLB 无效(这就是 helper_invlpg() 中的 tlb_flush_page() 调用正在做的事情) ; 所以这些指令不是简单的无操作。如果它使用查询缓存和 TLB 信息的 cpuid 指令,我们也会对客户撒谎并告诉它有关其 TLB 大小的合理信息。但是我们实际上并没有对客户 TLB 进行建模——因此您不会看到围绕客户 TLB 大小的性能变化,并且您无法记录有关客户 TLB 命中和未命中的信息,并且我们不实施 TLB 锁定在拥有它的 CPU 架构上。

最后,monitor "info tlb" 命令的命名相当错误,因为它实际上显示的是关于客户机页表设置的信息,这与 TLB 状态无关。

于 2015-03-18T00:35:17.393 回答
4

QEMU 模拟 TLB 吗?

是的。


QEMU 监视器控制台提供了一个info tlb命令,该命令将

列出TLB(Translation Lookaside Buffer),即物理内存和虚拟内存之间的映射


CPU 仿真文档有一节说

页面缓存在 QEMU 源代码中称为“TLB”。


在源码中,也就是target-i386/cpu.c我们看到了与TLB相关的如下定义:

/* TLB definitions: */

#define L1_DTLB_2M_ASSOC       1
#define L1_DTLB_2M_ENTRIES   255
#define L1_DTLB_4K_ASSOC       1
#define L1_DTLB_4K_ENTRIES   255

#define L1_ITLB_2M_ASSOC       1
#define L1_ITLB_2M_ENTRIES   255
#define L1_ITLB_4K_ASSOC       1
#define L1_ITLB_4K_ENTRIES   255

#define L2_DTLB_2M_ASSOC       0 /* disabled */
#define L2_DTLB_2M_ENTRIES     0 /* disabled */
#define L2_DTLB_4K_ASSOC       4
#define L2_DTLB_4K_ENTRIES   512

#define L2_ITLB_2M_ASSOC       0 /* disabled */
#define L2_ITLB_2M_ENTRIES     0 /* disabled */
#define L2_ITLB_4K_ASSOC       4
#define L2_ITLB_4K_ENTRIES   512

target-i386/translate.c中,我们看到以下代码处理INVLPG指令:

    case 7:
        if (mod != 3) { /* invlpg */
            if (s->cpl != 0) { 
                gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
            } else {
                gen_update_cc_op(s);
                gen_jmp_im(pc_start - s->cs_base);
                gen_lea_modrm(env, s, modrm);
                gen_helper_invlpg(cpu_env, cpu_A0);
                gen_jmp_im(s->pc - s->cs_base);
                gen_eob(s);
            }
        }

gen_helper_invlpg实施于target-i386/misc_helper.c

void helper_invlpg(CPUX86State *env, target_ulong addr)
{
    X86CPU *cpu = x86_env_get_cpu(env);

    cpu_svm_check_intercept_param(env, SVM_EXIT_INVLPG, 0); 
    tlb_flush_page(CPU(cpu), addr);
}

它调用的地方tlb_flush_page,它在cputlb.c.


所以你可以看到的,该INVLPG指令刷新 TLB 以获取地址。

于 2015-03-16T06:25:32.977 回答