I have a very simple question, does QEMU emulate TLB? What happens when a guest linux system executes an "invlpg" instruction as it is for the invalidation of a TLB entry. I am aware that QEMU has softmmu link which is used for translating the guest virtual address to host virtual address but does QEMU emulate an actual TLB, and what is the effect of "invlpg" instruction. Or does QEMU simply ignores this instruction?
The answer is somewhere between "yes" and "no". QEMU doesn't attempt to emulate the actual guest CPU's TLB (which is a piece of hardware which accelerates lookups from guest virtual addresses to guest physical addresses). However it does implement its own rather similar data structure which it calls a TLB -- this accelerates lookups from guest virtual addresses directly to host virtual addresses for RAM, or from guest virtual addresses to the read/write functions for emulated devices.
Since there are similarities between the CPU TLB and QEMU's TLB, we can use the guest instructions to invalidate or otherwise operate on the TLB as the triggers to perform QEMU TLB invalidations (which is what the tlb_flush_page() call in helper_invlpg() is doing); so these instructions are not simple no-ops. We also lie to the guest and tell it plausible things about the size of its TLB if it uses the cpuid instructions which query cache and TLB information. But we don't actually model the guest TLB -- so you won't see performance changes around the size of the guest TLB, and you can't log information about guest TLB hits and misses, and we don't implement TLB lockdown on CPU architectures that have it.
Finally, the monitor "info tlb" command is rather misnamed, because it's actually displaying information about the guest's page table setup, which is nothing to do with the TLB state.
does QEMU emulate TLB?
Yes.
The QEMU monitor console provides an info tlb
command which will
list the TLB (Translation Lookaside Buffer), i.e. mappings between physical memory and virtual memory
The CPU emulation documentation has a section that says
The page cache is called the "TLB" in the QEMU sources.
In the source code, namely target-i386/cpu.c
we see the following definitions related to the 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
In target-i386/translate.c
, we see the following code handling the INVLPG
instruction:
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
is implemented in 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);
}
where it calls tlb_flush_page
, which is implemented in cputlb.c
.
So you can see that yes, the INVLPG
instruction will flush the TLB for an address.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With