All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH kvm-unit-tests] emulator: test for MMX movq raising #MF if pending x87 exceptions exist
@ 2012-03-25 13:52 Avi Kivity
  2012-03-26 12:33 ` Stefan Hajnoczi
  0 siblings, 1 reply; 2+ messages in thread
From: Avi Kivity @ 2012-03-25 13:52 UTC (permalink / raw)
  To: Marcelo Tosatti, stefanha, kvm

Test that a pending #MF is raised correctly if encountered by the emulator
(and that the host isn't trashed by an unexpected exception).  The approach
here exploits the TLB and so will only work on more modern processors.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 x86/emulator.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 55 insertions(+), 1 deletions(-)

diff --git a/x86/emulator.c b/x86/emulator.c
index 6590618..33820f4 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -2,12 +2,15 @@
 #include "vm.h"
 #include "libcflat.h"
 #include "desc.h"
+#include "types.h"
 
 #define memset __builtin_memset
 #define TESTDEV_IO_PORT 0xe0
 
 int fails, tests;
 
+static int exceptions;
+
 void report(const char *name, int result)
 {
 	++tests;
@@ -645,16 +648,65 @@ static void test_shld_shrd(u32 *mem)
     report("shrd (cl)", *mem == ((0x12345678 >> 3) | (5u << 29)));
 }
 
+static void advance_rip_by_3_and_note_exception(struct ex_regs *regs)
+{
+    ++exceptions;
+    regs->rip += 3;
+}
+
+static void test_mmx_movq_mf(uint64_t *mem, uint8_t *insn_page,
+			     uint8_t *alt_insn_page, void *insn_ram)
+{
+    uint16_t fcw = 0;  // all exceptions unmasked
+    ulong *cr3 = (ulong *)read_cr3();
+
+    write_cr0(read_cr0() & ~6);  // TS, EM
+    // Place a trapping instruction in the page to trigger a VMEXIT
+    insn_page[0] = 0x89; // mov %eax, (%rax)
+    insn_page[1] = 0x00;
+    insn_page[2] = 0x90; // nop
+    insn_page[3] = 0xc3; // ret
+    // Place the instruction we want the hypervisor to see in the alternate page
+    alt_insn_page[0] = 0x0f; // movq %mm0, (%rax)
+    alt_insn_page[1] = 0x7f;
+    alt_insn_page[2] = 0x00;
+    alt_insn_page[3] = 0xc3; // ret
+
+    exceptions = 0;
+    handle_exception(MF_VECTOR, advance_rip_by_3_and_note_exception);
+
+    // Load the code TLB with insn_page, but point the page tables at
+    // alt_insn_page (and keep the data TLB clear, for AMD decode assist).
+    // This will make the CPU trap on the insn_page instruction but the
+    // hypervisor will see alt_insn_page.
+    install_page(cr3, virt_to_phys(insn_page), insn_ram);
+    asm volatile("fninit; fldcw %0" : : "m"(fcw));
+    asm volatile("fldz; fldz; fdivp"); // generate exception
+    invlpg(insn_ram);
+    // Load code TLB
+    asm volatile("call *%0" : : "r"(insn_ram + 3));
+    install_page(cr3, virt_to_phys(alt_insn_page), insn_ram);
+    // Trap, let hypervisor emulate at alt_insn_page
+    asm volatile("call *%0" : : "r"(insn_ram), "a"(mem));
+    // exit MMX mode
+    asm volatile("fnclex; emms");
+    report("movq mmx generates #MF", exceptions == 1);
+    handle_exception(MF_VECTOR, 0);
+}
+
 int main()
 {
 	void *mem;
+	void *insn_page, *alt_insn_page;
 	void *insn_ram;
 	unsigned long t1, t2;
 
 	setup_vm();
 	setup_idt();
 	mem = vmap(IORAM_BASE_PHYS, IORAM_LEN);
-	insn_ram = vmalloc(4096);
+	insn_page = alloc_page();
+	alt_insn_page = alloc_page();
+	insn_ram = vmap(virt_to_phys(insn_page), 4096);
 
 	// test mov reg, r/m and mov r/m, reg
 	t1 = 0x123456789abcdef;
@@ -690,6 +742,8 @@ int main()
 	test_rip_relative(mem, insn_ram);
 	test_shld_shrd(mem);
 
+	test_mmx_movq_mf(mem, insn_page, alt_insn_page, insn_ram);
+
 	printf("\nSUMMARY: %d tests, %d failures\n", tests, fails);
 	return fails ? 1 : 0;
 }
-- 
1.7.9


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH kvm-unit-tests] emulator: test for MMX movq raising #MF if pending x87 exceptions exist
  2012-03-25 13:52 [PATCH kvm-unit-tests] emulator: test for MMX movq raising #MF if pending x87 exceptions exist Avi Kivity
@ 2012-03-26 12:33 ` Stefan Hajnoczi
  0 siblings, 0 replies; 2+ messages in thread
From: Stefan Hajnoczi @ 2012-03-26 12:33 UTC (permalink / raw)
  To: Avi Kivity; +Cc: Marcelo Tosatti, stefanha, kvm

On Sun, Mar 25, 2012 at 2:52 PM, Avi Kivity <avi@redhat.com> wrote:
> Test that a pending #MF is raised correctly if encountered by the emulator
> (and that the host isn't trashed by an unexpected exception).  The approach
> here exploits the TLB and so will only work on more modern processors.
>
> Signed-off-by: Avi Kivity <avi@redhat.com>
> ---
>  x86/emulator.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 55 insertions(+), 1 deletions(-)

Thanks for CCing me on this example of how to sneak an emulator instruction in.

Stefan

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2012-03-26 12:33 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-25 13:52 [PATCH kvm-unit-tests] emulator: test for MMX movq raising #MF if pending x87 exceptions exist Avi Kivity
2012-03-26 12:33 ` Stefan Hajnoczi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.