diff options
| author | Brian Gerst <bgerst@didntduck.org> | 2003-01-12 16:36:55 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-01-12 16:36:55 -0800 |
| commit | 9b2ea4ae636d28dfb97c742c3449ee25bca2ff38 (patch) | |
| tree | 4ffb099aad5225519dfa96f08a0c7556692caa04 | |
| parent | 8e517818bb290752c7be4240ee82390e342b2f53 (diff) | |
[PATCH] Fix PnP BIOS fault handling
Check for PnP BIOS in all fault paths, not just in do_trap().
| -rw-r--r-- | arch/i386/kernel/traps.c | 30 | ||||
| -rw-r--r-- | arch/i386/mm/extable.c | 28 | ||||
| -rw-r--r-- | arch/i386/mm/fault.c | 5 | ||||
| -rw-r--r-- | include/asm-i386/uaccess.h | 2 |
4 files changed, 33 insertions, 32 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index bba14fb29a36..81a09464e4d7 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -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) diff --git a/arch/i386/mm/extable.c b/arch/i386/mm/extable.c index 946e7ad6fbcb..1526546b5c3e 100644 --- a/arch/i386/mm/extable.c +++ b/arch/i386/mm/extable.c @@ -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; +} diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index e1ebd7239849..f65c88f6daac 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -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 diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h index c919c504dca3..a3c50a5ecdfe 100644 --- a/include/asm-i386/uaccess.h +++ b/include/asm-i386/uaccess.h @@ -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. |
