All of lore.kernel.org
 help / color / mirror / Atom feed
* A patch to arch/i386/kernel/irq.c to help get backtraces of (near) stack overflow situations
@ 2009-01-16 12:20 John Hughes
  2009-01-16 12:38 ` Ingo Molnar
  2009-01-18  4:01 ` Andi Kleen
  0 siblings, 2 replies; 8+ messages in thread
From: John Hughes @ 2009-01-16 12:20 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 539 bytes --]

I'm working on a system that is using a bit too much stack to work 
reliably with 4K stacks (OpenSSI with DRBD for the root filesystem 
replication) and I find that the CONFIG_DEBUG_STACKOVERFLOW stuff works 
rather poorly - often the stack dump will cause a stack overflow itself.

Here's a little patch to irq.c to make stack overflow dumps use a 
separate stack.

It's based on 2.6.12 'cos that's how out of date I am.  :-)

Maybe it'll be of use to someone.

Please CC john@calva.com with any comments, I'm not subscribed to the list.

[-- Attachment #2: arch-i386-kernel-irq.c-overflow.patch --]
[-- Type: text/x-patch, Size: 3318 bytes --]

--- linux/arch/i386/kernel/irq.c	2005-06-17 21:48:29.000000000 +0200
+++ linux-ssi/arch/i386/kernel/irq.c	2009-01-15 13:09:45.000000000 +0100
@@ -41,6 +41,23 @@
 
 static union irq_ctx *hardirq_ctx[NR_CPUS];
 static union irq_ctx *softirq_ctx[NR_CPUS];
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+static union irq_ctx *overflow_ctx[NR_CPUS];
+#endif
+#ifdef	CONFIG_KDB
+const char *kdba_irq_ctx_type(int cpu, struct thread_info *tinfo)
+{
+	if (tinfo == &hardirq_ctx[cpu]->tinfo)
+		return "hardirq_ctx";
+	if (tinfo == &softirq_ctx[cpu]->tinfo)
+		return "softirq_ctx";
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+	if (tinfo == &overflow_ctx[cpu]->tinfo)
+		return "overflow_ctx";
+#endif
+	return NULL;
+}
+#endif	/* CONFIG_KDB */
 #endif
 
 /*
@@ -53,6 +70,7 @@
 	/* high bits used in ret_from_ code */
 	int irq = regs->orig_eax & 0xff;
 #ifdef CONFIG_4KSTACKS
+	int arg1, arg2, ebx;
 	union irq_ctx *curctx, *irqctx;
 	u32 *isp;
 #endif
@@ -66,9 +84,38 @@
 		__asm__ __volatile__("andl %%esp,%0" :
 					"=r" (esp) : "0" (THREAD_SIZE - 1));
 		if (unlikely(esp < (sizeof(struct thread_info) + STACK_WARN))) {
+#if CONFIG_4KSTACKS
+			/* use a special stack for overflow warning,
+			   we want to avoid overflowing while telling
+			   the user about the problem! */
+
+			curctx = (union irq_ctx *) current_thread_info();
+			irqctx = overflow_ctx[smp_processor_id()];
+
+			if (curctx == irqctx) {
+				panic("double overflow");
+			}
+			
+			/* build the stack frame on the oflow stack */
+			isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
+			irqctx->tinfo.task = curctx->tinfo.task;
+			irqctx->tinfo.previous_esp = current_stack_pointer;
+
+			asm volatile(
+				"       xchgl   %%ebx,%%esp    \n"
+				"       call    __overflow     \n"
+				"       movl   %%ebx,%%esp     \n"
+				: "=a" (arg1), "=d" (arg2), "=b" (ebx)
+				:  "0" (irq),   "1" (esp),  "2" (isp)
+				: "memory", "cc", "ecx"
+			);
+
+			printk ("Back from overflow\n");
+#else
 			printk("do_IRQ: stack overflow: %ld\n",
 				esp - sizeof(struct thread_info));
 			dump_stack();
+#endif
 		}
 	}
 #endif
@@ -109,6 +156,17 @@
 	return 1;
 }
 
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+#ifdef CONFIG_4KSTACKS
+static fastcall void __overflow (int irq, long esp)
+{
+	printk("do_IRQ: stack overflow: %ld\n",
+		esp - sizeof(struct thread_info));
+	dump_stack();
+}
+#endif
+#endif
+
 #ifdef CONFIG_4KSTACKS
 
 /*
@@ -121,6 +179,10 @@
 static char hardirq_stack[NR_CPUS * THREAD_SIZE]
 		__attribute__((__aligned__(THREAD_SIZE)));
 
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+static char overflow_stack[NR_CPUS * THREAD_SIZE]
+		__attribute__((__aligned__(THREAD_SIZE)));
+#endif
 /*
  * allocate per-cpu stacks for hardirq and for softirq processing
  */
@@ -151,6 +213,20 @@
 
 	printk("CPU %u irqstacks, hard=%p soft=%p\n",
 		cpu,hardirq_ctx[cpu],softirq_ctx[cpu]);
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+
+	irqctx = (union irq_ctx*) &overflow_stack[cpu*THREAD_SIZE];
+	irqctx->tinfo.task              = NULL;
+	irqctx->tinfo.exec_domain       = NULL;
+	irqctx->tinfo.cpu               = cpu;
+	irqctx->tinfo.preempt_count     = HARDIRQ_OFFSET;	/* ? */
+	irqctx->tinfo.addr_limit        = MAKE_MM_SEG(0);
+
+	overflow_ctx[cpu] = irqctx;
+
+	printk("CPU %u irqstacks, overflow=%p\n",
+		cpu,overflow_ctx[cpu]);
+#endif
 }
 
 extern asmlinkage void __do_softirq(void);

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-01-19  9:36 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-16 12:20 A patch to arch/i386/kernel/irq.c to help get backtraces of (near) stack overflow situations John Hughes
2009-01-16 12:38 ` Ingo Molnar
2009-01-16 12:47   ` John Hughes
2009-01-16 12:57     ` Ingo Molnar
2009-01-16 13:07       ` John Hughes
2009-01-16 13:26         ` Ingo Molnar
2009-01-18  4:01 ` Andi Kleen
2009-01-19  9:35   ` John Hughes

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.