[RFC][PATCH 18/22] x86,kvm: Remove .fixup usage

Peter Zijlstra
2021-11-04T16:56:57Z

KVM instruction emulation has a gnarly hack where the .fixup does a
return, luckily exceptions can easily emulate a return so create a new
extable type to fully do the FASTOP magic.

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
---
arch/x86/include/asm/extable_fixup_types.h | 1 +
arch/x86/kvm/emulate.c | 14 +++-----------
arch/x86/mm/extable.c | 11 +++++++++++
3 files changed, 15 insertions(+), 11 deletions(-)

--- a/arch/x86/include/asm/extable_fixup_types.h
+++ b/arch/x86/include/asm/extable_fixup_types.h
@@ -40,5 +40,6 @@
#define EX_TYPE_ONE_REG (EX_TYPE_IMM_REG | EX_TYPE_IMM(1))

#define EX_TYPE_FAULT_SGX 18
+#define EX_TYPE_KVM_FASTOP 19

#endif
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -344,7 +344,7 @@ static int fastop(struct x86_emulate_ctx
__FOP_RET(#op "_" #dst)

#define FOP1EEX(op, dst) \
- FOP1E(op, dst) _ASM_EXTABLE(10b, kvm_fastop_exception)
+ FOP1E(op, dst) _ASM_EXTABLE_TYPE(10b, 10b, EX_TYPE_KVM_FASTOP)

#define FASTOP1(op) \
FOP_START(op) \
@@ -434,10 +434,6 @@ static int fastop(struct x86_emulate_ctx
#op " %al \n\t" \
__FOP_RET(#op)

-asm(".pushsection .fixup, \"ax\"\n"
- "kvm_fastop_exception: xor %esi, %esi; ret\n"
- ".popsection");
-
FOP_START(setcc)
FOP_SETCC(seto)
FOP_SETCC(setno)
@@ -473,12 +469,8 @@ FOP_END;
\
asm volatile("1:" insn "\n" \
"2:\n" \
- ".pushsection .fixup, \"ax\"\n" \
- "3: movl $1, %[_fault]\n" \
- " jmp 2b\n" \
- ".popsection\n" \
- _ASM_EXTABLE(1b, 3b) \
- : [_fault] "+qm"(_fault) inoutclob ); \
+ _ASM_EXTABLE_TYPE_REG(1b, 2b, EX_TYPE_ONE_REG, %[_fault]) \
+ : [_fault] "+r"(_fault) inoutclob ); \
\
_fault ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE; \
})
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -10,6 +10,7 @@
#include <asm/traps.h>
#include <asm/kdebug.h>
#include <asm/sgx.h>
+#include <asm/text-patching.h>

static inline unsigned long *pt_regs_nr(struct pt_regs *regs, int nr)
{
@@ -154,6 +155,14 @@ static bool ex_handler_sgx(const struct
return ex_handler_default(fixup, regs);
}

+static bool ex_handler_kvm_fastop(const struct exception_table_entry *fixup,
+ struct pt_regs *regs)
+{
+ regs->si = 0;
+ int3_emulate_ret(regs);
+ return true;
+}
+
#define EX_TYPE_MASK 0x000000FF
#define EX_REG_MASK 0x00000F00
#define EX_FLAG_MASK 0x0000F000
@@ -231,6 +240,8 @@ int fixup_exception(struct pt_regs *regs
return ex_handler_imm_reg(e, regs, reg, imm);
case EX_TYPE_FAULT_SGX:
return ex_handler_sgx(e, regs, trapnr);
+ case EX_TYPE_KVM_FASTOP:
+ return ex_handler_kvm_fastop(e, regs);
}
BUG();
}