]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Fix PnP BIOS fault handling
authorBrian Gerst <bgerst@didntduck.org>
Mon, 13 Jan 2003 00:36:55 +0000 (16:36 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Mon, 13 Jan 2003 00:36:55 +0000 (16:36 -0800)
Check for PnP BIOS in all fault paths, not just in do_trap().

arch/i386/kernel/traps.c
arch/i386/mm/extable.c
arch/i386/mm/fault.c
include/asm-i386/uaccess.h

index bba14fb29a365813d3c17ba65f1d3b6ece26eed0..81a09464e4d79c6801825eddf449e2d6636ddb4a 100644 (file)
@@ -297,26 +297,7 @@ static inline void do_trap(int trapnr, int signr, char *str, int vm86,
        }
 
        kernel_trap: {
-               const struct exception_table_entry *fixup;
-#ifdef CONFIG_PNPBIOS
-               if (unlikely((regs->xcs | 8) == 0x88)) /* 0x80 or 0x88 */
-               {
-                       extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
-                       extern u32 pnp_bios_is_utter_crap;
-                       pnp_bios_is_utter_crap = 1;
-                       printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n");
-                       __asm__ volatile(
-                               "movl %0, %%esp\n\t"
-                               "jmp *%1\n\t"
-                               : "=a" (pnp_bios_fault_esp), "=b" (pnp_bios_fault_eip));
-                       panic("do_trap: can't hit this");
-               }
-#endif 
-               
-               fixup = search_exception_tables(regs->eip);
-               if (fixup)
-                       regs->eip = fixup->fixup;
-               else    
+               if (!fixup_exception(regs))
                        die(str, regs, error_code);
                return;
        }
@@ -393,15 +374,8 @@ gp_in_vm86:
        return;
 
 gp_in_kernel:
-       {
-               const struct exception_table_entry *fixup;
-               fixup = search_exception_tables(regs->eip);
-               if (fixup) {
-                       regs->eip = fixup->fixup;
-                       return;
-               }
+       if (!fixup_exception(regs))
                die("general protection fault", regs, error_code);
-       }
 }
 
 static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
index 946e7ad6fbcb6a7743d0fd242e92cb8fef1279e5..1526546b5c3eb650b923cf07af4c85bb8d716f61 100644 (file)
@@ -28,3 +28,31 @@ search_extable(const struct exception_table_entry *first,
         }
         return NULL;
 }
+
+int fixup_exception(struct pt_regs *regs)
+{
+       const struct exception_table_entry *fixup;
+
+#ifdef CONFIG_PNPBIOS
+       if (unlikely((regs->xcs | 8) == 0x88)) /* 0x80 or 0x88 */
+       {
+               extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
+               extern u32 pnp_bios_is_utter_crap;
+               pnp_bios_is_utter_crap = 1;
+               printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n");
+               __asm__ volatile(
+                       "movl %0, %%esp\n\t"
+                       "jmp *%1\n\t"
+                       : "=a" (pnp_bios_fault_esp), "=b" (pnp_bios_fault_eip));
+               panic("do_trap: can't hit this");
+       }
+#endif
+
+       fixup = search_exception_tables(regs->eip);
+       if (fixup) {
+               regs->eip = fixup->fixup;
+               return 1;
+       }
+
+       return 0;
+}
index e1ebd723984996a0ee9a9eb64c54ab8bf0daa204..f65c88f6daac81a001a16a5a72d28ecf083d0512 100644 (file)
@@ -155,7 +155,6 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
        struct vm_area_struct * vma;
        unsigned long address;
        unsigned long page;
-       const struct exception_table_entry *fixup;
        int write;
        siginfo_t info;
 
@@ -311,10 +310,8 @@ bad_area:
 
 no_context:
        /* Are we prepared to handle this kernel fault?  */
-       if ((fixup = search_exception_tables(regs->eip)) != NULL) {
-               regs->eip = fixup->fixup;
+       if (fixup_exception(regs))
                return;
-       }
 
 /*
  * Oops. The kernel tried to access some bad page. We'll have to
index c919c504dca3fbf2139649eb312ae9435d6dc107..a3c50a5ecdfee86aac21a22192c6ec4ba64a8530 100644 (file)
@@ -92,6 +92,8 @@ struct exception_table_entry
        unsigned long insn, fixup;
 };
 
+extern int fixup_exception(struct pt_regs *regs);
+
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.