x86/traps: Enable all exception handler callbacks early
[cascardo/linux.git] / arch / x86 / mm / extable.c
index 82447b3..061a237 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
+#include <asm/traps.h>
 
 typedef bool (*ex_handler_t)(const struct exception_table_entry *,
                            struct pt_regs *, int);
@@ -82,24 +83,32 @@ int fixup_exception(struct pt_regs *regs, int trapnr)
        return handler(e, regs, trapnr);
 }
 
+extern unsigned int early_recursion_flag;
+
 /* Restricted version used during very early boot */
-int __init early_fixup_exception(unsigned long *ip)
+void __init early_fixup_exception(struct pt_regs *regs, int trapnr)
 {
-       const struct exception_table_entry *e;
-       unsigned long new_ip;
-       ex_handler_t handler;
+       /* Ignore early NMIs. */
+       if (trapnr == X86_TRAP_NMI)
+               return;
 
-       e = search_exception_tables(*ip);
-       if (!e)
-               return 0;
+       if (early_recursion_flag > 2)
+               goto halt_loop;
 
-       new_ip  = ex_fixup_addr(e);
-       handler = ex_fixup_handler(e);
+       if (regs->cs != __KERNEL_CS)
+               goto fail;
 
-       /* special handling not supported during early boot */
-       if (handler != ex_handler_default)
-               return 0;
+       if (fixup_exception(regs, trapnr))
+               return;
+
+fail:
+       early_printk("PANIC: early exception 0x%02x IP %lx:%lx error %lx cr2 0x%lx\n",
+                    (unsigned)trapnr, (unsigned long)regs->cs, regs->ip,
+                    regs->orig_ax, read_cr2());
+
+       show_regs(regs);
 
-       *ip = new_ip;
-       return 1;
+halt_loop:
+       while (true)
+               halt();
 }