[kvm-unit-tests v2 1/8] x86: emulator: asm fixes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Found several problems in the emulator test when trying to compile
with various combinations of -fno-omit-frame-pointer and -O{0,1}.

Fixed register clobbering in several tests. It's not good enough to
save & restore a register with I/O operands because the compiler can
use the register to effect the I/O! Fixing %rbp was tricky because it
can't be listed in the clobber list when -fno-omit-frame-pointer is in
effect; thus %rbp has to be saved manually using a scratch register
that's declared as clobbered.

The length of the jmp instruction in test_jmp_noncanonical was 2, not
3. This patch makes the exception handler more robust by using the
computed instruction length.

Signed-off-by: Peter Feiner <pfeiner@xxxxxxxxxx>
---
 x86/emulator.c | 60 +++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 36 insertions(+), 24 deletions(-)

diff --git a/x86/emulator.c b/x86/emulator.c
index e5c1c6b..d990961 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -260,24 +260,30 @@ void test_pop(void *mem)
 	report("ret", 1);
 
 	stack_top[-1] = 0x778899;
-	asm volatile("mov %%rsp, %[tmp] \n\t"
-		     "mov %%rbp, %[tmp3] \n\t"
-		     "mov %[stack_top], %%rbp \n\t"
+	asm volatile("mov %[stack_top], %%r8 \n\t"
+		     "mov %%rsp, %%r9 \n\t"
+		     "xchg %%rbp, %%r8 \n\t"
 		     "leave \n\t"
-		     "xchg %%rsp, %[tmp] \n\t"
-		     "xchg %%rbp, %[tmp3]"
+		     "xchg %%rsp, %%r9 \n\t"
+		     "xchg %%rbp, %%r8 \n\t"
+		     "mov %%r9, %[tmp] \n\t"
+		     "mov %%r8, %[tmp3]"
 		     : [tmp]"=&r"(tmp), [tmp3]"=&r"(tmp3) : [stack_top]"r"(stack_top-1)
-		     : "memory");
+		     : "memory", "r8", "r9");
 	report("leave", tmp == (ulong)stack_top && tmp3 == 0x778899);
 
 	rbp = 0xaa55aa55bb66bb66ULL;
 	rsp = (unsigned long)stack_top;
-	asm volatile("xchg %%rsp, %[rsp] \n\t"
-		     "xchg %%rbp, %[rbp] \n\t"
+	asm volatile("mov %[rsp], %%r8 \n\t"
+		     "mov %[rbp], %%r9 \n\t"
+		     "xchg %%rsp, %%r8 \n\t"
+		     "xchg %%rbp, %%r9 \n\t"
 		     "enter $0x1238, $0 \n\t"
-		     "xchg %%rsp, %[rsp] \n\t"
-		     "xchg %%rbp, %[rbp]"
-		     : [rsp]"+a"(rsp), [rbp]"+b"(rbp) : : "memory");
+		     "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("enter",
 	       rsp == (unsigned long)stack_top - 8 - 0x1238
 	       && rbp == (unsigned long)stack_top - 8
@@ -405,7 +411,7 @@ void test_xchg(void *mem)
 		     "mov %%rax, %[rax]\n\t"
 		     : [rax]"=r"(rax)
 		     : [memq]"r"(memq)
-		     : "memory");
+		     : "memory", "rax");
 	report("xchg reg, r/m (1)",
 	       rax == 0xfedcba98765432ef && *memq == 0x123456789abcd10);
 
@@ -416,7 +422,7 @@ void test_xchg(void *mem)
 		     "mov %%rax, %[rax]\n\t"
 		     : [rax]"=r"(rax)
 		     : [memq]"r"(memq)
-		     : "memory");
+		     : "memory", "rax");
 	report("xchg reg, r/m (2)",
 	       rax == 0xfedcba987654cdef && *memq == 0x123456789ab3210);
 
@@ -427,7 +433,7 @@ void test_xchg(void *mem)
 		     "mov %%rax, %[rax]\n\t"
 		     : [rax]"=r"(rax)
 		     : [memq]"r"(memq)
-		     : "memory");
+		     : "memory", "rax");
 	report("xchg reg, r/m (3)",
 	       rax == 0x89abcdef && *memq == 0x123456776543210);
 
@@ -438,7 +444,7 @@ void test_xchg(void *mem)
 		     "mov %%rax, %[rax]\n\t"
 		     : [rax]"=r"(rax)
 		     : [memq]"r"(memq)
-		     : "memory");
+		     : "memory", "rax");
 	report("xchg reg, r/m (4)",
 	       rax == 0x123456789abcdef && *memq == 0xfedcba9876543210);
 }
@@ -455,7 +461,7 @@ void test_xadd(void *mem)
 		     "mov %%rax, %[rax]\n\t"
 		     : [rax]"=r"(rax)
 		     : [memq]"r"(memq)
-		     : "memory");
+		     : "memory", "rax");
 	report("xadd reg, r/m (1)",
 	       rax == 0xfedcba98765432ef && *memq == 0x123456789abcdff);
 
@@ -466,7 +472,7 @@ void test_xadd(void *mem)
 		     "mov %%rax, %[rax]\n\t"
 		     : [rax]"=r"(rax)
 		     : [memq]"r"(memq)
-		     : "memory");
+		     : "memory", "rax");
 	report("xadd reg, r/m (2)",
 	       rax == 0xfedcba987654cdef && *memq == 0x123456789abffff);
 
@@ -477,7 +483,7 @@ void test_xadd(void *mem)
 		     "mov %%rax, %[rax]\n\t"
 		     : [rax]"=r"(rax)
 		     : [memq]"r"(memq)
-		     : "memory");
+		     : "memory", "rax");
 	report("xadd reg, r/m (3)",
 	       rax == 0x89abcdef && *memq == 0x1234567ffffffff);
 
@@ -488,7 +494,7 @@ void test_xadd(void *mem)
 		     "mov %%rax, %[rax]\n\t"
 		     : [rax]"=r"(rax)
 		     : [memq]"r"(memq)
-		     : "memory");
+		     : "memory", "rax");
 	report("xadd reg, r/m (4)",
 	       rax == 0x123456789abcdef && *memq == 0xffffffffffffffff);
 }
@@ -804,10 +810,12 @@ static void trap_emulator(uint64_t *mem, void *alt_insn_page,
 	outregs = save;
 }
 
-static void advance_rip_by_3_and_note_exception(struct ex_regs *regs)
+static unsigned long rip_advance;
+
+static void advance_rip_and_note_exception(struct ex_regs *regs)
 {
     ++exceptions;
-    regs->rip += 3;
+    regs->rip += rip_advance;
 }
 
 static void test_mmx_movq_mf(uint64_t *mem, uint8_t *insn_page,
@@ -819,11 +827,12 @@ static void test_mmx_movq_mf(uint64_t *mem, uint8_t *insn_page,
 
     write_cr0(read_cr0() & ~6);  /* TS, EM */
     exceptions = 0;
-    handle_exception(MF_VECTOR, advance_rip_by_3_and_note_exception);
+    handle_exception(MF_VECTOR, advance_rip_and_note_exception);
     asm volatile("fninit; fldcw %0" : : "m"(fcw));
     asm volatile("fldz; fldz; fdivp"); /* generate exception */
 
     MK_INSN(mmx_movq_mf, "movq %mm0, (%rax) \n\t");
+    rip_advance = insn_mmx_movq_mf.len;
     inregs = (struct regs){ .rsp=(u64)stack+1024 };
     trap_emulator(mem, alt_insn_page, &insn_mmx_movq_mf);
     /* exit MMX mode */
@@ -834,11 +843,14 @@ static void test_mmx_movq_mf(uint64_t *mem, uint8_t *insn_page,
 
 static void test_jmp_noncanonical(uint64_t *mem)
 {
+	extern char nc_jmp_start, nc_jmp_end;
+
 	*mem = 0x1111111111111111ul;
 
 	exceptions = 0;
-	handle_exception(GP_VECTOR, advance_rip_by_3_and_note_exception);
-	asm volatile ("jmp *%0" : : "m"(*mem));
+	rip_advance = &nc_jmp_end - &nc_jmp_start;
+	handle_exception(GP_VECTOR, advance_rip_and_note_exception);
+	asm volatile ("nc_jmp_start: jmp *%0; nc_jmp_end:" : : "m"(*mem));
 	report("jump to non-canonical address", exceptions == 1);
 	handle_exception(GP_VECTOR, 0);
 }
-- 
2.7.0.rc3.207.g0ac5344

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux