[kvm-unit-tests PATCH v3 3/7] x86: Introduce ASM_TRY_FEP() to handle exceptions on forced emulation

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

 



From: Michal Luczaj <mhal@xxxxxxx>

Introduce ASM_TRY_FEP() to allow using the try-catch method to handle
exceptions that occur on forced emulation.  ASM_TRY() mishandles
exceptions thrown by the forced-emulation-triggered emulator. While the
faulting address stored in the exception table points at forced emulation
prefix, when an exceptions comes, RIP is 5 bytes (size of KVM_FEP) ahead
due to KVM advancing RIP to skip the prefix and the exception ends up
unhandled.

Signed-off-by: Michal Luczaj <mhal@xxxxxxx>
Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
 lib/x86/desc.h | 13 ++++++++++---
 x86/emulator.c |  1 -
 x86/pmu.c      |  1 -
 3 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index 10ba8cb..8f708fd 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -92,13 +92,20 @@ typedef struct  __attribute__((packed)) {
 	u16 iomap_base;
 } tss64_t;
 
-#define ASM_TRY(catch)						\
-	"movl $0, %%gs:4 \n\t"					\
-	".pushsection .data.ex \n\t"				\
+#define __ASM_TRY(prefix, catch)				\
+	"movl $0, %%gs:4\n\t"					\
+	".pushsection .data.ex\n\t"				\
 	__ASM_SEL(.long, .quad) " 1111f,  " catch "\n\t"	\
 	".popsection \n\t"					\
+	prefix "\n\t"						\
 	"1111:"
 
+#define ASM_TRY(catch) __ASM_TRY("", catch)
+
+/* Forced emulation prefix, used to invoke the emulator unconditionally. */
+#define KVM_FEP "ud2; .byte 'k', 'v', 'm';"
+#define ASM_TRY_FEP(catch) __ASM_TRY(KVM_FEP, catch)
+
 /*
  * selector     32-bit                        64-bit
  * 0x00         NULL descriptor               NULL descriptor
diff --git a/x86/emulator.c b/x86/emulator.c
index 769a049..6dc88f1 100644
--- a/x86/emulator.c
+++ b/x86/emulator.c
@@ -18,7 +18,6 @@
 static int exceptions;
 
 /* Forced emulation prefix, used to invoke the emulator unconditionally.  */
-#define KVM_FEP "ud2; .byte 'k', 'v', 'm';"
 #define KVM_FEP_LENGTH 5
 static int fep_available = 1;
 
diff --git a/x86/pmu.c b/x86/pmu.c
index 01be1e9..457c5b9 100644
--- a/x86/pmu.c
+++ b/x86/pmu.c
@@ -33,7 +33,6 @@
 
 #define N 1000000
 
-#define KVM_FEP "ud2; .byte 'k', 'v', 'm';"
 // These values match the number of instructions and branches in the
 // assembly block in check_emulated_instr().
 #define EXPECTED_INSTR 17
-- 
2.37.1.559.g78731f0fdb-goog




[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