Commit 9b2ea4ae authored by Brian Gerst's avatar Brian Gerst Committed by Linus Torvalds

[PATCH] Fix PnP BIOS fault handling

Check for PnP BIOS in all fault paths, not just in do_trap().
parent 8e517818
......@@ -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 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
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)
......
......@@ -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;
}
......@@ -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 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
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
......
......@@ -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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment