diff options
author | Michael Ellerman <michael@ellerman.id.au> | 2013-06-05 21:58:20 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-06-13 21:49:28 +0400 |
commit | 878aac71d99971e7b79361b173f3ad14d3abf02b (patch) | |
tree | da0aa78f7f67218a6bc665eeed1c74db98e1c1bd /arch | |
parent | 9dc9f5e35b518c61ddff7226ee7de09b841831ff (diff) | |
download | linux-878aac71d99971e7b79361b173f3ad14d3abf02b.tar.xz |
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/perf/core-book3s.c | 2 |
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"); /* |