summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Gerst <bgerst@didntduck.org>2003-01-12 16:36:55 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-01-12 16:36:55 -0800
commit9b2ea4ae636d28dfb97c742c3449ee25bca2ff38 (patch)
tree4ffb099aad5225519dfa96f08a0c7556692caa04
parent8e517818bb290752c7be4240ee82390e342b2f53 (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.c30
-rw-r--r--arch/i386/mm/extable.c28
-rw-r--r--arch/i386/mm/fault.c5
-rw-r--r--include/asm-i386/uaccess.h2
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.