Skip to contentSkip to conversation

Fix PnP BIOS fault handling

PATCH New Brian Gerst 1 participant 1 message Jan 13, 2003

lore
Share & tools
lore
#0 lore raw

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
diff -urN linux-2.5.56-bk1/arch/i386/kernel/traps.c linux-a1/arch/i386/kernel/traps.c
@@ -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
diff -urN linux-2.5.56-bk1/arch/i386/mm/extable.c linux-a1/arch/i386/mm/extable.c
@@ -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
diff -urN linux-2.5.56-bk1/arch/i386/mm/fault.c linux-a1/arch/i386/mm/fault.c
@@ -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
diff -urN linux-2.5.56-bk1/include/asm-i386/uaccess.h linux-a1/include/asm-i386/uaccess.h
@@ -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.