summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2013-06-05 17:58:20 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-06-13 10:49:28 -0700
commit878aac71d99971e7b79361b173f3ad14d3abf02b (patch)
treeda0aa78f7f67218a6bc665eeed1c74db98e1c1bd
parent9dc9f5e35b518c61ddff7226ee7de09b841831ff (diff)
powerpc/perf: Fix deadlock caused by calling printk() in PMU exception
commit 6772faa1ba22eba18d087c2459030a683b65be57 upstream. In commit bc09c21 "Fix finding overflowed PMC in interrupt" we added a printk() to the PMU exception handler. Unfortunately that is not safe. The problem is that the PMU exception may run even when interrupts are soft disabled, aka NMI context. We do this so that we can profile parts of the kernel that have interrupts soft-disabled. But by calling printk() from the exception handler, we can potentially deadlock in the printk code on logbuf_lock, eg: [c00000038ba575c0] c000000000081928 .vprintk_emit+0xa8/0x540 [c00000038ba576a0] c0000000007bcde8 .printk+0x48/0x58 [c00000038ba57710] c000000000076504 .perf_event_interrupt+0x2d4/0x490 [c00000038ba57810] c00000000001f6f8 .performance_monitor_exception+0x48/0x60 [c00000038ba57880] c0000000000032cc performance_monitor_common+0x14c/0x180 --- Exception: f01 (Performance Monitor) at c0000000007b25d4 ._raw_spin_lock_irq +0x64/0xc0 [c00000038ba57bf0] c00000000007ed90 .devkmsg_read+0xd0/0x5a0 [c00000038ba57d00] c0000000001c2934 .vfs_read+0xc4/0x1e0 [c00000038ba57d90] c0000000001c2cd8 .SyS_read+0x58/0xd0 [c00000038ba57e30] c000000000009d54 syscall_exit+0x0/0x98 --- Exception: c01 (System Call) at 00001fffffbf6f7c SP (3ffff6d4de10) is in userspace Fix it by making sure we only call printk() when we are not in NMI context. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--arch/powerpc/perf/core-book3s.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 65362e98eb26..9d858b0aeb53 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1528,7 +1528,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
}
}
}
- if ((!found) && printk_ratelimit())
+ if (!found && !nmi && printk_ratelimit())
printk(KERN_WARNING "Can't find PMC that caused IRQ\n");
/*