[PATCH] fix x86-64 interrupt re-enabling in oops_end()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



(Note: Patch also attached because the inline version is certain to get
line wrapped.)

Rather than blindly re-enabling interrupts in oops_end(), save their
state
in oope_begin() and then restore that state.

Signed-off-by: Jan Beulich <[email protected]>

diff -Npru 2.6.13/arch/x86_64/kernel/traps.c
2.6.13-x86_64-oops-irq/arch/x86_64/kernel/traps.c
--- 2.6.13/arch/x86_64/kernel/traps.c	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-x86_64-oops-irq/arch/x86_64/kernel/traps.c	2005-09-07
15:37:52.000000000 +0200
@@ -342,30 +342,33 @@ void out_of_line_bug(void)
 static DEFINE_SPINLOCK(die_lock);
 static int die_owner = -1;
 
-void oops_begin(void)
+unsigned long oops_begin(void)
 {
-	int cpu = safe_smp_processor_id(); 
-	/* racy, but better than risking deadlock. */ 
-	local_irq_disable();
+	int cpu = safe_smp_processor_id();
+	unsigned long flags;
+
+	/* racy, but better than risking deadlock. */
+	local_irq_save(flags);
 	if (!spin_trylock(&die_lock)) { 
 		if (cpu == die_owner) 
 			/* nested oops. should stop eventually */;
 		else
-			spin_lock(&die_lock); 
+			spin_lock(&die_lock);
 	}
-	die_owner = cpu; 
+	die_owner = cpu;
 	console_verbose();
-	bust_spinlocks(1); 
+	bust_spinlocks(1);
+	return flags;
 }
 
-void oops_end(void)
+void oops_end(unsigned long flags)
 { 
 	die_owner = -1;
-	bust_spinlocks(0); 
-	spin_unlock(&die_lock); 
+	bust_spinlocks(0);
+	spin_unlock_irqrestore(&die_lock, flags);
 	if (panic_on_oops)
-		panic("Oops"); 
-} 
+		panic("Oops");
+}
 
 void __die(const char * str, struct pt_regs * regs, long err)
 {
@@ -391,10 +394,11 @@ void __die(const char * str, struct pt_r
 
 void die(const char * str, struct pt_regs * regs, long err)
 {
-	oops_begin();
+	unsigned long flags = oops_begin();
+
 	handle_BUG(regs);
 	__die(str, regs, err);
-	oops_end();
+	oops_end(flags);
 	do_exit(SIGSEGV); 
 }
 static inline void die_if_kernel(const char * str, struct pt_regs *
regs, long err)
@@ -405,7 +409,8 @@ static inline void die_if_kernel(const c
 
 void die_nmi(char *str, struct pt_regs *regs)
 {
-	oops_begin();
+	unsigned long flags = oops_begin();
+
 	/*
 	 * We are in trouble anyway, lets at least try
 	 * to get a message out.
@@ -415,7 +420,7 @@ void die_nmi(char *str, struct pt_regs *
 	if (panic_on_timeout || panic_on_oops)
 		panic("nmi watchdog");
 	printk("console shuts up ...\n");
-	oops_end();
+	oops_end(flags);
 	do_exit(SIGSEGV);
 }
 
diff -Npru 2.6.13/arch/x86_64/mm/fault.c
2.6.13-x86_64-oops-irq/arch/x86_64/mm/fault.c
--- 2.6.13/arch/x86_64/mm/fault.c	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-x86_64-oops-irq/arch/x86_64/mm/fault.c	2005-09-07
16:15:13.000000000 +0200
@@ -220,12 +220,13 @@ int unhandled_signal(struct task_struct 
 static noinline void pgtable_bad(unsigned long address, struct pt_regs
*regs,
 				 unsigned long error_code)
 {
-	oops_begin();
+	unsigned long flags = oops_begin();
+
 	printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
 	       current->comm, address);
 	dump_pagetable(address);
 	__die("Bad pagetable", regs, error_code);
-	oops_end();
+	oops_end(flags);
 	do_exit(SIGKILL);
 }
 
@@ -302,6 +303,7 @@ asmlinkage void do_page_fault(struct pt_
 	unsigned long address;
 	const struct exception_table_entry *fixup;
 	int write;
+	unsigned long flags;
 	siginfo_t info;
 
 #ifdef CONFIG_CHECKING
@@ -519,7 +521,7 @@ no_context:
  * terminate things with extreme prejudice.
  */
 
-	oops_begin(); 
+	flags = oops_begin(); 
 
 	if (address < PAGE_SIZE)
 		printk(KERN_ALERT "Unable to handle kernel NULL pointer
dereference");
@@ -532,7 +534,7 @@ no_context:
 	__die("Oops", regs, error_code);
 	/* Executive summary in case the body of the oops scrolled away
*/
 	printk(KERN_EMERG "CR2: %016lx\n", address);
-	oops_end(); 
+	oops_end(flags); 
 	do_exit(SIGKILL);
 
 /*
diff -Npru 2.6.13/include/asm-x86_64/kdebug.h
2.6.13-x86_64-oops-irq/include/asm-x86_64/kdebug.h
--- 2.6.13/include/asm-x86_64/kdebug.h	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-x86_64-oops-irq/include/asm-x86_64/kdebug.h	2005-09-01
11:32:12.000000000 +0200
@@ -46,7 +46,7 @@ extern void die(const char *,struct pt_r
 extern void __die(const char *,struct pt_regs *,long);
 extern void show_registers(struct pt_regs *regs);
 extern void dump_pagetable(unsigned long);
-extern void oops_begin(void);
-extern void oops_end(void);
+extern unsigned long oops_begin(void);
+extern void oops_end(unsigned long);
 
 #endif
diff -Npru 2.6.13/include/asm-x86_64/proto.h
2.6.13-x86_64-oops-irq/include/asm-x86_64/proto.h
--- 2.6.13/include/asm-x86_64/proto.h	2005-08-29 01:41:01.000000000
+0200
+++ 2.6.13-x86_64-oops-irq/include/asm-x86_64/proto.h	2005-09-01
11:32:12.000000000 +0200
@@ -75,9 +75,6 @@ extern void acpi_reserve_bootmem(void);
 
 extern void swap_low_mappings(void);
 
-extern void oops_begin(void);
-extern void die(const char *,struct pt_regs *,long);
-extern void __die(const char * str, struct pt_regs * regs, long err);
 extern void __show_regs(struct pt_regs * regs);
 extern void show_regs(struct pt_regs * regs);
 

Attachment: linux-2.6.13-x86_64-oops-irq.patch
Description: Binary data


[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]
  Powered by Linux