summaryrefslogtreecommitdiff
path: root/arch/x86/mm
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2021-11-10 11:01:08 +0100
committerPeter Zijlstra <peterz@infradead.org>2021-12-11 09:09:46 +0100
commitaa93e2ad7464ffb90155a5ffdde963816f86d5dc (patch)
tree345b322a089c1ca16e708ed1123555d729c5bc82 /arch/x86/mm
parent16e617d05ef0c521d000c989796412ce713f28c9 (diff)
x86/entry_32: Remove .fixup usage
Where possible, push the .fixup into code, at the tail of functions. This is hard for macros since they're used in multiple functions, therefore introduce a new extable handler to pop zeros. Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com> Link: https://lore.kernel.org/r/20211110101325.245184699@infradead.org
Diffstat (limited to 'arch/x86/mm')
-rw-r--r--arch/x86/mm/extable.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 5cd2a88930a9..fb0c4752df1a 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -99,6 +99,18 @@ static bool ex_handler_clear_fs(const struct exception_table_entry *fixup,
return ex_handler_default(fixup, regs);
}
+static bool ex_handler_pop_zero(const struct exception_table_entry *fixup,
+ struct pt_regs *regs)
+{
+ /*
+ * Typically used for when "pop %seg" traps, in which case we'll clear
+ * the stack slot and re-try the instruction, which will then succeed
+ * to pop zero.
+ */
+ *((unsigned long *)regs->sp) = 0;
+ return ex_handler_default(fixup, regs);
+}
+
int ex_get_fixup_type(unsigned long ip)
{
const struct exception_table_entry *e = search_exception_tables(ip);
@@ -156,6 +168,8 @@ int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
case EX_TYPE_WRMSR_IN_MCE:
ex_handler_msr_mce(regs, true);
break;
+ case EX_TYPE_POP_ZERO:
+ return ex_handler_pop_zero(e, regs);
}
BUG();
}