2003-01-13 06:20:58

by Brian Gerst

[permalink] [raw]
Subject: [PATCH] Fix PnP BIOS fault handling

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.


Attachments:
traps-a1 (3.34 kB)