我有一个非常简单的问题,QEMU 是否模拟 TLB?当客户 linux 系统执行“invlpg”指令时会发生什么,因为它是为了使 TLB 条目无效。我知道 QEMU 有 softmmu链接,用于将客户虚拟地址转换为主机虚拟地址,但 QEMU 是否模拟实际的 TLB,以及“invlpg”指令的效果是什么。还是 QEMU 只是忽略了这条指令?
2 回答
答案介于“是”和“否”之间。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 状态无关。
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 以获取地址。