* [kvm-unit-tests PATCH] x86/emulator: Add testcases for ENTER + emulated MMIO
@ 2026-05-14 21:15 Sean Christopherson
0 siblings, 0 replies; only message in thread
From: Sean Christopherson @ 2026-05-14 21:15 UTC (permalink / raw)
To: Paolo Bonzini; +Cc: kvm, Sean Christopherson
Add testcases for stack pushes to emulated MMIO via the ENTER instruction
to validate a pile of KVM changes needed to fix a use-after-free due to
KVM referencing kernel stack data across a userspace exit. Test that ENTER
is handled correctly if it splits non-MMIO => MMIO, MMIO => non-MMIO, and
MMIO => MMIO pages.
Opportunistically add a comment explaining what the collection of pages
are used for in the emulator test.
Link: https://lore.kernel.org/all/20260225012049.920665-1-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
x86/emulator.c | 66 ++++++++++++++++++++++++++++--------------------
x86/emulator64.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 102 insertions(+), 28 deletions(-)
diff --git a/x86/emulator.c b/x86/emulator.c
index 102e5efc..6d945d8a 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -790,8 +790,7 @@ static void test_mov_pop_ss_code_db(void)
int main(void)
{
- void *mem;
- void *cross_mem;
+ void *base, *mmio, *split;
if (!is_fep_available)
report_skip("Skipping tests that require forced emulation, "
@@ -799,45 +798,56 @@ int main(void)
setup_vm();
- mem = alloc_vpages(2);
- install_page((void *)read_cr3(), IORAM_BASE_PHYS, mem);
- // install the page twice to test cross-page mmio
- install_page((void *)read_cr3(), IORAM_BASE_PHYS, mem + 4096);
- cross_mem = vmap(virt_to_phys(alloc_pages(2)), 2 * PAGE_SIZE);
+ /*
+ * Allocate five pages in the virtual address space, with pages, 0, 3,
+ * and 4 pointing at normal memory, and pages 1 and 2 pointing at an
+ * emulated MMIO range. This combination of pages allows testing basic
+ * emulated MMIO handling, as well as a variety of multi-page and page-
+ * split scenarios.
+ */
+ base = alloc_vpages(5);
+ install_page((void *)read_cr3(), virt_to_phys(alloc_pages(1)), base);
+ install_page((void *)read_cr3(), IORAM_BASE_PHYS, base + PAGE_SIZE);
+ install_page((void *)read_cr3(), IORAM_BASE_PHYS, base + 2 * PAGE_SIZE);
+ install_page((void *)read_cr3(), virt_to_phys(alloc_pages(1)), base + 3 * PAGE_SIZE);
+ install_page((void *)read_cr3(), virt_to_phys(alloc_pages(1)), base + 4 * PAGE_SIZE);
- test_mov(mem);
- test_simplealu(mem);
- test_cmps(mem);
- test_scas(mem);
- test_smsw(mem);
+ mmio = base + PAGE_SIZE;
+ split = base + 3 * PAGE_SIZE;
+
+ test_mov(mmio);
+ test_simplealu(mmio);
+ test_cmps(mmio);
+ test_scas(mmio);
+ test_smsw(mmio);
test_lmsw();
test_stringio();
- test_incdecnotneg(mem);
- test_btc(mem);
- test_bsfbsr(mem);
- test_imul(mem);
- test_sse(mem);
- test_sse_exceptions(cross_mem);
- test_shld_shrd(mem);
- //test_lgdt_lidt(mem);
- //test_lldt(mem);
- test_ltr(mem);
+ test_incdecnotneg(mmio);
+ test_btc(mmio);
+ test_bsfbsr(mmio);
+ test_imul(mmio);
+ test_sse(mmio);
+ test_sse_exceptions(split);
+ test_shld_shrd(mmio);
+ //test_lgdt_lidt(mmio);
+ //test_lldt(mmio);
+ test_ltr(mmio);
if (is_fep_available) {
- test_smsw_reg(mem);
- test_nop(mem);
- test_mov_dr(mem);
+ test_smsw_reg(mmio);
+ test_nop(mmio);
+ test_mov_dr(mmio);
test_illegal_lea();
}
- test_crosspage_mmio(mem);
+ test_crosspage_mmio(mmio);
- test_string_io_mmio(mem);
+ test_string_io_mmio(mmio);
test_illegal_movbe();
test_mov_pop_ss_code_db();
#ifdef __x86_64__
- test_emulator_64(mem);
+ test_emulator_64(mmio);
#endif
return report_summary();
}
diff --git a/x86/emulator64.c b/x86/emulator64.c
index 6a85122f..c4df5178 100644
--- a/x86/emulator64.c
+++ b/x86/emulator64.c
@@ -116,6 +116,70 @@ static void test_pop(void *mem)
&& rbp == (unsigned long)stack_top - 8
&& stack_top[-1] == 0xaa55aa55bb66bb66ULL,
"enter");
+
+ stack_top = mem + 8192 + 4;
+ stack_top[-1] = -1ull;
+ rbp = 0x1122334455667788ULL;
+ rsp = (unsigned long)stack_top;
+ asm volatile("mov %[rsp], %%r8 \n\t"
+ "mov %[rbp], %%r9 \n\t"
+ "xchg %%rsp, %%r8 \n\t"
+ "xchg %%rbp, %%r9 \n\t"
+ "enter $0x1234, $0 \n\t"
+ "xchg %%rsp, %%r8 \n\t"
+ "xchg %%rbp, %%r9 \n\t"
+ "xchg %%r8, %[rsp] \n\t"
+ "xchg %%r9, %[rbp]"
+ : [rsp]"+a"(rsp), [rbp]"+b"(rbp) : : "memory", "r8", "r9");
+
+ report(rsp == (unsigned long)stack_top - 8 - 0x1234 &&
+ rbp == (unsigned long)stack_top - 8 &&
+ stack_top[-1] == 0x1122334455667788ULL,
+ "enter");
+
+ stack_top = mem + 4096 + 4;
+ stack_top[-1] = -1ull;
+ rbp = 0x1122334455667788ULL;
+ rsp = (unsigned long)stack_top;
+ asm volatile("mov %[rsp], %%r8 \n\t"
+ "mov %[rbp], %%r9 \n\t"
+ "xchg %%rsp, %%r8 \n\t"
+ "xchg %%rbp, %%r9 \n\t"
+ "enter $0x1234, $0 \n\t"
+ "xchg %%rsp, %%r8 \n\t"
+ "xchg %%rbp, %%r9 \n\t"
+ "xchg %%r8, %[rsp] \n\t"
+ "xchg %%r9, %[rbp]"
+ : [rsp]"+a"(rsp), [rbp]"+b"(rbp) : : "memory", "r8", "r9");
+
+ report(rsp == (unsigned long)stack_top - 8 - 0x1234,
+ "ENTER RSP = %lx, wanted %lx", rsp, (unsigned long)stack_top - 8 - 0x1234);
+ report(rbp == (unsigned long)stack_top - 8,
+ "ENTER RSP = %lx, wanted %lx", rbp, (unsigned long)stack_top - 8);
+ report(stack_top[-1] == 0x1122334455667788ULL,
+ "ENTER val = %lx, wanted 0x1122334455667788", stack_top[-1]);
+
+ stack_top = mem + 4;
+ stack_top[-1] = -1ull;
+ rbp = 0x8877665544332211ULL;
+ rsp = (unsigned long)stack_top;
+ asm volatile("mov %[rsp], %%r8 \n\t"
+ "mov %[rbp], %%r9 \n\t"
+ "xchg %%rsp, %%r8 \n\t"
+ "xchg %%rbp, %%r9 \n\t"
+ "enter $0x1234, $0 \n\t"
+ "xchg %%rsp, %%r8 \n\t"
+ "xchg %%rbp, %%r9 \n\t"
+ "xchg %%r8, %[rsp] \n\t"
+ "xchg %%r9, %[rbp]"
+ : [rsp]"+a"(rsp), [rbp]"+b"(rbp) : : "memory", "r8", "r9");
+
+ report(rsp == (unsigned long)stack_top - 8 - 0x1234,
+ "ENTER RSP = %lx, wanted %lx", rsp, (unsigned long)stack_top - 8 - 0x1234);
+ report(rbp == (unsigned long)stack_top - 8,
+ "ENTER RSP = %lx, wanted %lx", rbp, (unsigned long)stack_top - 8);
+ report(stack_top[-1] == 0x8877665544332211ULL,
+ "ENTER val = %lx, wanted 0x8877665544332211", stack_top[-1]);
}
static void test_ljmp(void *mem)
base-commit: 9eb6c57313060d34f7e5b2ac6f90bb5873bbe2ff
--
2.54.0.563.g4f69b47b94-goog
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2026-05-14 21:15 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-14 21:15 [kvm-unit-tests PATCH] x86/emulator: Add testcases for ENTER + emulated MMIO Sean Christopherson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox