Fix PnP BIOS fault handling
PATCH 1/1 Fix PnP BIOS fault handling
Check for PnP BIOS in all fault paths, not just in do_trap().
--
Brian Gerst
arch/i386/kernel/traps.c +2 -28
@@ -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)
arch/i386/mm/extable.c +28 -0
@@ -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 ; +}
arch/i386/mm/fault.c +1 -4
@@ -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
include/asm-i386/uaccess.h +2 -0
@@ -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.