diff options
author | Paul Gortmaker <paul.gortmaker@windriver.com> | 2014-04-29 15:25:17 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-05-19 20:54:06 -0400 |
commit | 21f585073d6347651f2262da187606fa1c4ee16d (patch) | |
tree | 5ec5947a36e0a7e7fe458d13523d4036cc748ff1 /arch/powerpc/kernel/hw_breakpoint.c | |
parent | 04c32a516806ec74b62048baf4cddcbb840927db (diff) |
powerpc: Fix smp_processor_id() in preemptible splat in set_breakpoint
Currently, on 8641D, which doesn't set CONFIG_HAVE_HW_BREAKPOINT
we get the following splat:
BUG: using smp_processor_id() in preemptible [00000000] code: login/1382
caller is set_breakpoint+0x1c/0xa0
CPU: 0 PID: 1382 Comm: login Not tainted 3.15.0-rc3-00041-g2aafe1a4d451 #1
Call Trace:
[decd5d80] [c0008dc4] show_stack+0x50/0x158 (unreliable)
[decd5dc0] [c03c6fa0] dump_stack+0x7c/0xdc
[decd5de0] [c01f8818] check_preemption_disabled+0xf4/0x104
[decd5e00] [c00086b8] set_breakpoint+0x1c/0xa0
[decd5e10] [c00d4530] flush_old_exec+0x2bc/0x588
[decd5e40] [c011c468] load_elf_binary+0x2ac/0x1164
[decd5ec0] [c00d35f8] search_binary_handler+0xc4/0x1f8
[decd5ef0] [c00d4ee8] do_execve+0x3d8/0x4b8
[decd5f40] [c001185c] ret_from_syscall+0x0/0x38
--- Exception: c01 at 0xfeee554
LR = 0xfeee7d4
The call path in this case is:
flush_thread
--> set_debug_reg_defaults
--> set_breakpoint
--> __get_cpu_var
Since preemption is enabled in the cleanup of flush thread, and
there is no need to disable it, introduce the distinction between
set_breakpoint and __set_breakpoint, leaving only the flush_thread
instance as the current user of set_breakpoint.
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel/hw_breakpoint.c')
-rw-r--r-- | arch/powerpc/kernel/hw_breakpoint.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c index b0a1792279bb..0bb5918faaaf 100644 --- a/arch/powerpc/kernel/hw_breakpoint.c +++ b/arch/powerpc/kernel/hw_breakpoint.c | |||
@@ -72,7 +72,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp) | |||
72 | * If so, DABR will be populated in single_step_dabr_instruction(). | 72 | * If so, DABR will be populated in single_step_dabr_instruction(). |
73 | */ | 73 | */ |
74 | if (current->thread.last_hit_ubp != bp) | 74 | if (current->thread.last_hit_ubp != bp) |
75 | set_breakpoint(info); | 75 | __set_breakpoint(info); |
76 | 76 | ||
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
@@ -198,7 +198,7 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs) | |||
198 | 198 | ||
199 | info = counter_arch_bp(tsk->thread.last_hit_ubp); | 199 | info = counter_arch_bp(tsk->thread.last_hit_ubp); |
200 | regs->msr &= ~MSR_SE; | 200 | regs->msr &= ~MSR_SE; |
201 | set_breakpoint(info); | 201 | __set_breakpoint(info); |
202 | tsk->thread.last_hit_ubp = NULL; | 202 | tsk->thread.last_hit_ubp = NULL; |
203 | } | 203 | } |
204 | 204 | ||
@@ -284,7 +284,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args) | |||
284 | if (!(info->type & HW_BRK_TYPE_EXTRANEOUS_IRQ)) | 284 | if (!(info->type & HW_BRK_TYPE_EXTRANEOUS_IRQ)) |
285 | perf_bp_event(bp, regs); | 285 | perf_bp_event(bp, regs); |
286 | 286 | ||
287 | set_breakpoint(info); | 287 | __set_breakpoint(info); |
288 | out: | 288 | out: |
289 | rcu_read_unlock(); | 289 | rcu_read_unlock(); |
290 | return rc; | 290 | return rc; |
@@ -316,7 +316,7 @@ int __kprobes single_step_dabr_instruction(struct die_args *args) | |||
316 | if (!(info->type & HW_BRK_TYPE_EXTRANEOUS_IRQ)) | 316 | if (!(info->type & HW_BRK_TYPE_EXTRANEOUS_IRQ)) |
317 | perf_bp_event(bp, regs); | 317 | perf_bp_event(bp, regs); |
318 | 318 | ||
319 | set_breakpoint(info); | 319 | __set_breakpoint(info); |
320 | current->thread.last_hit_ubp = NULL; | 320 | current->thread.last_hit_ubp = NULL; |
321 | 321 | ||
322 | /* | 322 | /* |