diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-11-26 02:29:10 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-11-26 02:29:10 -0500 |
commit | 67f2de0bf9141dd9fe9189d0caaa28d7ad21a523 (patch) | |
tree | 6e1693295e6a38efa0a269429d74418f16a76027 | |
parent | b803090615ccec669681ff85ce28671e7bfefa3d (diff) |
x86: dumpstack, 64-bit: Disable preemption when walking the IRQ/exception stacks
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>
-rw-r--r-- | arch/x86/kernel/dumpstack_64.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index cfec478a4e42..8e740934bd1f 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c | |||
@@ -206,19 +206,22 @@ void | |||
206 | show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | 206 | show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, |
207 | unsigned long *sp, unsigned long bp, char *log_lvl) | 207 | unsigned long *sp, unsigned long bp, char *log_lvl) |
208 | { | 208 | { |
209 | unsigned long *irq_stack_end; | ||
210 | unsigned long *irq_stack; | ||
209 | unsigned long *stack; | 211 | unsigned long *stack; |
212 | int cpu; | ||
210 | int i; | 213 | int i; |
211 | const int cpu = smp_processor_id(); | 214 | |
212 | unsigned long *irq_stack_end = | 215 | preempt_disable(); |
213 | (unsigned long *)(per_cpu(irq_stack_ptr, cpu)); | 216 | cpu = smp_processor_id(); |
214 | unsigned long *irq_stack = | 217 | |
215 | (unsigned long *)(per_cpu(irq_stack_ptr, cpu) - IRQ_STACK_SIZE); | 218 | irq_stack_end = (unsigned long *)(per_cpu(irq_stack_ptr, cpu)); |
219 | irq_stack = (unsigned long *)(per_cpu(irq_stack_ptr, cpu) - IRQ_STACK_SIZE); | ||
216 | 220 | ||
217 | /* | 221 | /* |
218 | * debugging aid: "show_stack(NULL, NULL);" prints the | 222 | * Debugging aid: "show_stack(NULL, NULL);" prints the |
219 | * back trace for this cpu. | 223 | * back trace for this cpu: |
220 | */ | 224 | */ |
221 | |||
222 | if (sp == NULL) { | 225 | if (sp == NULL) { |
223 | if (task) | 226 | if (task) |
224 | sp = (unsigned long *)task->thread.sp; | 227 | sp = (unsigned long *)task->thread.sp; |
@@ -242,6 +245,8 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs, | |||
242 | printk(" %016lx", *stack++); | 245 | printk(" %016lx", *stack++); |
243 | touch_nmi_watchdog(); | 246 | touch_nmi_watchdog(); |
244 | } | 247 | } |
248 | preempt_enable(); | ||
249 | |||
245 | printk("\n"); | 250 | printk("\n"); |
246 | show_trace_log_lvl(task, regs, sp, bp, log_lvl); | 251 | show_trace_log_lvl(task, regs, sp, bp, log_lvl); |
247 | } | 252 | } |