| From 50741acc651890e58abdd96c8115f56776e52686 Mon Sep 17 00:00:00 2001 |
| From: Robert Richter <robert.richter@amd.com> |
| Date: Mon, 10 Oct 2011 16:21:10 +0200 |
| Subject: [PATCH 21/24] oprofile, x86: Fix crash when unloading module (nmi |
| timer mode) |
| |
| commit 97f7f8189fe54e3cfe324ef9ad35064f3d2d3bff upstream. |
| |
| If oprofile uses the nmi timer interrupt there is a crash while |
| unloading the module. The bug can be triggered with oprofile build as |
| module and kernel parameter nolapic set. This patch fixes this. |
| |
| oprofile: using NMI timer interrupt. |
| BUG: unable to handle kernel NULL pointer dereference at 0000000000000008 |
| IP: [<ffffffff8123c226>] unregister_syscore_ops+0x41/0x58 |
| PGD 42dbca067 PUD 41da6a067 PMD 0 |
| Oops: 0002 [#1] PREEMPT SMP |
| CPU 5 |
| Modules linked in: oprofile(-) [last unloaded: oprofile] |
| |
| Pid: 2518, comm: modprobe Not tainted 3.1.0-rc7-00019-gb2fb49d #19 Advanced Micro Device Anaheim/Anaheim |
| RIP: 0010:[<ffffffff8123c226>] [<ffffffff8123c226>] unregister_syscore_ops+0x41/0x58 |
| RSP: 0018:ffff88041ef71e98 EFLAGS: 00010296 |
| RAX: 0000000000000000 RBX: ffffffffa0017100 RCX: dead000000200200 |
| RDX: 0000000000000000 RSI: dead000000100100 RDI: ffffffff8178c620 |
| RBP: ffff88041ef71ea8 R08: 0000000000000001 R09: 0000000000000082 |
| R10: 0000000000000000 R11: ffff88041ef71de8 R12: 0000000000000080 |
| R13: fffffffffffffff5 R14: 0000000000000001 R15: 0000000000610210 |
| FS: 00007fc902f20700(0000) GS:ffff88042fd40000(0000) knlGS:0000000000000000 |
| CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b |
| CR2: 0000000000000008 CR3: 000000041cdb6000 CR4: 00000000000006e0 |
| DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 |
| DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 |
| Process modprobe (pid: 2518, threadinfo ffff88041ef70000, task ffff88041d348040) |
| Stack: |
| ffff88041ef71eb8 ffffffffa0017790 ffff88041ef71eb8 ffffffffa0013532 |
| ffff88041ef71ec8 ffffffffa00132d6 ffff88041ef71ed8 ffffffffa00159b2 |
| ffff88041ef71f78 ffffffff81073115 656c69666f72706f 0000000000610200 |
| Call Trace: |
| [<ffffffffa0013532>] op_nmi_exit+0x15/0x17 [oprofile] |
| [<ffffffffa00132d6>] oprofile_arch_exit+0xe/0x10 [oprofile] |
| [<ffffffffa00159b2>] oprofile_exit+0x1e/0x20 [oprofile] |
| [<ffffffff81073115>] sys_delete_module+0x1c3/0x22f |
| [<ffffffff811bf09e>] ? trace_hardirqs_on_thunk+0x3a/0x3f |
| [<ffffffff8148070b>] system_call_fastpath+0x16/0x1b |
| Code: 20 c6 78 81 e8 c5 cc 23 00 48 8b 13 48 8b 43 08 48 be 00 01 10 00 00 00 ad de 48 b9 00 02 20 00 00 00 ad de 48 c7 c7 20 c6 78 81 |
| 89 42 08 48 89 10 48 89 33 48 89 4b 08 e8 a6 c0 23 00 5a 5b |
| RIP [<ffffffff8123c226>] unregister_syscore_ops+0x41/0x58 |
| RSP <ffff88041ef71e98> |
| CR2: 0000000000000008 |
| ---[ end trace 43a541a52956b7b0 ]--- |
| |
| Signed-off-by: Robert Richter <robert.richter@amd.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| --- |
| arch/x86/oprofile/init.c | 7 +++++-- |
| 1 file changed, 5 insertions(+), 2 deletions(-) |
| |
| diff --git a/arch/x86/oprofile/init.c b/arch/x86/oprofile/init.c |
| index cdfe4c5..f148cf6 100644 |
| --- a/arch/x86/oprofile/init.c |
| +++ b/arch/x86/oprofile/init.c |
| @@ -21,6 +21,7 @@ extern int op_nmi_timer_init(struct oprofile_operations *ops); |
| extern void op_nmi_exit(void); |
| extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth); |
| |
| +static int nmi_timer; |
| |
| int __init oprofile_arch_init(struct oprofile_operations *ops) |
| { |
| @@ -31,8 +32,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) |
| #ifdef CONFIG_X86_LOCAL_APIC |
| ret = op_nmi_init(ops); |
| #endif |
| + nmi_timer = (ret != 0); |
| #ifdef CONFIG_X86_IO_APIC |
| - if (ret < 0) |
| + if (nmi_timer) |
| ret = op_nmi_timer_init(ops); |
| #endif |
| ops->backtrace = x86_backtrace; |
| @@ -44,6 +46,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) |
| void oprofile_arch_exit(void) |
| { |
| #ifdef CONFIG_X86_LOCAL_APIC |
| - op_nmi_exit(); |
| + if (!nmi_timer) |
| + op_nmi_exit(); |
| #endif |
| } |
| -- |
| 1.7.12.1 |
| |