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