4k stacks and BUILD_INTERRUPT
I was getting some pretty repeatable oopses while large numbers of processes were exiting on my 16-way PIII while irqstacks, and 4k stacks were turned on. It is hard to trigger, and only happens when you're using 4k stacks, not just irqstacks.
I traced it down to when smp_* interrupts were running. It seems that they use an interrupt entry path that doesn't include do_IRQ or common_interrupt. They use a BUILD_INTERRUPT macro, instead. They were blowing their 4k stacks when running softirqs.
So, what I did, was put the irqstack operations in a macro and call it from common_interrupt, and the BUILD_INTERRUPT macros. I also had to change the calling conventions of the newly-affected handlers.
Ben, was there a reason that you didn't include these functions in your original irqstack patches? I always (wrongly) assumed that they were really quick interrupts, and didn't use the stack heavily enough to be worth modifying.
The a diff for the -mjb tree is attached. I'll cook up another set of vanilla ones tomorrow.
Does anybody want to see irqstacks as a config option? These macros would make it easier.
Signature · 2 lines
Dave Hansen [email protected]
arch/i386/kernel/apic.c +10 -4
@@ -1038,7 +1038,8 @@* interrupt as well. Thus we cannot inline the local irq ... ] */ -void smp_apic_timer_interrupt (struct pt_regs regs) +struct pt_regs *smp_apic_timer_interrupt (struct pt_regs * regs) __attribute__((regparm (1 ))); +struct pt_regs *smp_apic_timer_interrupt (struct pt_regs * regs) {int cpu =smp_processor_id ();
@@ -1058,14 +1059,16 @@* interrupt lock, which is the WrongThing (tm) to do. */ irq_enter (); -smp_local_timer_interrupt (®s); +smp_local_timer_interrupt (regs);irq_exit (); +return regs; }/* * This interrupt should _never_ happen with our APIC/SMP architecture */ -asmlinkage void smp_spurious_interrupt(void) +struct pt_regs *smp_spurious_interrupt (struct pt_regs * regs) __attribute__((regparm (1 ))); +struct pt_regs *smp_spurious_interrupt (struct pt_regs * regs) {unsigned long v;
@@ -1083,13 +1086,15 @@printk (KERN_INFO "spurious APIC interrupt on CPU#%d, should never happen.\n" ,smp_processor_id ());irq_exit (); +return regs; }/* * This interrupt should never happen with our APIC/SMP architecture */ -asmlinkage void smp_error_interrupt(void) +struct pt_regs *smp_error_interrupt (struct pt_regs * regs) __attribute__((regparm (1 ))); +struct pt_regs *smp_error_interrupt (struct pt_regs * regs) {unsigned long v, v1;
@@ -1114,6 +1119,7 @@printk (KERN_INFO "APIC error on CPU%d: %02lx(%02lx)\n" ,smp_processor_id (), v , v1);irq_exit (); +return regs; }/*
arch/i386/kernel/entry.S +41 -42
100 lines not on this page · raw message
arch/i386/kernel/smp.c +12 -4
@@ -305,7 +305,8 @@* 2) Leave the mm if we are in the lazy tlb mode. */ -asmlinkage void smp_invalidate_interrupt (void) +struct pt_regs *smp_invalidate_interrupt (struct pt_regs *regs) __attribute__((regparm (1 ))); +struct pt_regs *smp_invalidate_interrupt (struct pt_regs *regs) {unsigned long cpu;
@@ -336,6 +337,7 @@ out:put_cpu_no_resched (); +return regs; } static void flush_tlb_others (unsigned long cpumask, struct mm_struct *mm,
@@ -598,12 +600,17 @@* all the work is done automatically when * we return from the interrupt. */ -asmlinkage void smp_reschedule_interrupt(void) + +asmlinkage struct pt_regs * smp_reschedule_interrupt(struct pt_regs *regs) __attribute__((regparm(1))); +struct pt_regs *smp_reschedule_interrupt (struct pt_regs *regs) {ack_APIC_irq (); +return regs; } -asmlinkage void smp_call_function_interrupt(struct pt_regs regs) + +asmlinkage struct pt_regs * smp_call_function_interrupt(struct pt_regs *regs) __attribute__((regparm(1))); +struct pt_regs *smp_call_function_interrupt (struct pt_regs *regs) {void (*func) (void *info,struct pt_regs *) = (void (*)(void *,struct pt_regs *))call_data->func;void *info = call_data->info;
@@ -620,12 +627,13 @@* At this point the info structure may be out of scope unless wait==1 */ irq_enter (); - (*func)(info, ®s); + (*func)(info, regs);irq_exit ();if (wait) {mb ();atomic_inc (&call_data->finished); } +return regs; }
Don't anyone go applying that. I screwed up the macro definitions. It compiled, but the macros aren't complete, so it will die pretty quickly the first time it hits an interrupt.
I'll fix it and send some real ones tomorrow.
Signature · 2 lines
Dave Hansen [email protected]