x86: dumpstack, 64-bit: Disable preemption when walking the IRQ/exception stacks
authorIngo Molnar <mingo@elte.hu>
Thu, 26 Nov 2009 07:29:10 +0000 (08:29 +0100)
committerIngo Molnar <mingo@elte.hu>
Thu, 26 Nov 2009 07:29:10 +0000 (08:29 +0100)
This warning:

[  847.140022] rb_producer   D 0000000000000000  5928   519      2 0x00000000
[  847.203627] BUG: using smp_processor_id() in preemptible [00000000] code: khungtaskd/517
[  847.207360] caller is show_stack_log_lvl+0x2e/0x241
[  847.210364] Pid: 517, comm: khungtaskd Not tainted 2.6.32-rc8-tip+ #13761
[  847.213395] Call Trace:
[  847.215847]  [<ffffffff81413bde>] debug_smp_processor_id+0x1f0/0x20a
[  847.216809]  [<ffffffff81015eae>] show_stack_log_lvl+0x2e/0x241
[  847.220027]  [<ffffffff81018512>] show_stack+0x1c/0x1e
[  847.223365]  [<ffffffff8107b7db>] sched_show_task+0xe4/0xe9
[  847.226694]  [<ffffffff8112f21f>] check_hung_task+0x140/0x199
[  847.230261]  [<ffffffff8112f4a8>] check_hung_uninterruptible_tasks+0x1b7/0x20f
[  847.233371]  [<ffffffff8112f500>] ? watchdog+0x0/0x50
[  847.236683]  [<ffffffff8112f54e>] watchdog+0x4e/0x50
[  847.240034]  [<ffffffff810cee56>] kthread+0x97/0x9f
[  847.243372]  [<ffffffff81012aea>] child_rip+0xa/0x20
[  847.246690]  [<ffffffff81e43494>] ? restore_args+0x0/0x30
[  847.250019]  [<ffffffff81e43083>] ? _spin_lock+0xe/0x10
[  847.253351]  [<ffffffff810cedbf>] ? kthread+0x0/0x9f
[  847.256833]  [<ffffffff81012ae0>] ? child_rip+0x0/0x20

Happens because on preempt-RCU, khungd calls show_stack() with
preemption enabled.

Make sure we are not preemptible while walking the IRQ and exception
stacks on 64-bit. (32-bit stack dumping is preemption safe.)

Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/dumpstack_64.c

index cfec478a4e42add3862b416e56c1290b292d14c2..8e740934bd1f56307b1cc8b7c318bdaeeda5b9d5 100644 (file)
@@ -206,19 +206,22 @@ void
 show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
                   unsigned long *sp, unsigned long bp, char *log_lvl)
 {
+       unsigned long *irq_stack_end;
+       unsigned long *irq_stack;
        unsigned long *stack;
+       int cpu;
        int i;
-       const int cpu = smp_processor_id();
-       unsigned long *irq_stack_end =
-               (unsigned long *)(per_cpu(irq_stack_ptr, cpu));
-       unsigned long *irq_stack =
-               (unsigned long *)(per_cpu(irq_stack_ptr, cpu) - IRQ_STACK_SIZE);
+
+       preempt_disable();
+       cpu = smp_processor_id();
+
+       irq_stack_end   = (unsigned long *)(per_cpu(irq_stack_ptr, cpu));
+       irq_stack       = (unsigned long *)(per_cpu(irq_stack_ptr, cpu) - IRQ_STACK_SIZE);
 
        /*
-        * debugging aid: "show_stack(NULL, NULL);" prints the
-        * back trace for this cpu.
+        * Debugging aid: "show_stack(NULL, NULL);" prints the
+        * back trace for this cpu:
         */
-
        if (sp == NULL) {
                if (task)
                        sp = (unsigned long *)task->thread.sp;
@@ -242,6 +245,8 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
                printk(" %016lx", *stack++);
                touch_nmi_watchdog();
        }
+       preempt_enable();
+
        printk("\n");
        show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 }