[PATCH] Fix PnP BIOS fault handling

From: Brian Gerst (bgerst@didntduck.org)
Date: Mon Jan 13 2003 - 01:29:51 EST


Check for PnP BIOS in all fault paths, not just in do_trap().

--
				Brian Gerst

diff -urN linux-2.5.56-bk1/arch/i386/kernel/traps.c linux-a1/arch/i386/kernel/traps.c --- linux-2.5.56-bk1/arch/i386/kernel/traps.c Sat Jan 11 03:24:59 2003 +++ linux-a1/arch/i386/kernel/traps.c Sat Jan 11 03:29:47 2003 @@ -297,26 +297,7 @@ } 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 @@ 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) diff -urN linux-2.5.56-bk1/arch/i386/mm/extable.c linux-a1/arch/i386/mm/extable.c --- linux-2.5.56-bk1/arch/i386/mm/extable.c Sat Jan 11 03:24:59 2003 +++ linux-a1/arch/i386/mm/extable.c Sat Jan 11 03:29:47 2003 @@ -28,3 +28,31 @@ } 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; +} diff -urN linux-2.5.56-bk1/arch/i386/mm/fault.c linux-a1/arch/i386/mm/fault.c --- linux-2.5.56-bk1/arch/i386/mm/fault.c Sat Jan 11 03:24:59 2003 +++ linux-a1/arch/i386/mm/fault.c Sat Jan 11 03:29:47 2003 @@ -155,7 +155,6 @@ 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 @@ 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 diff -urN linux-2.5.56-bk1/include/asm-i386/uaccess.h linux-a1/include/asm-i386/uaccess.h --- linux-2.5.56-bk1/include/asm-i386/uaccess.h Sat Jan 11 03:25:00 2003 +++ linux-a1/include/asm-i386/uaccess.h Sat Jan 11 03:29:47 2003 @@ -92,6 +92,8 @@ 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.

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Jan 15 2003 - 22:00:44 EST