aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/hw_breakpoint.c
diff options
context:
space:
mode:
authorMichael Neuling <mikey@neuling.org>2012-09-06 17:24:57 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-09-09 19:59:13 -0400
commitcd14457304c9d232267a3a76a2a43f1f791e545d (patch)
treedefabdab4b813faf7bcd083f8670020cf799003c /arch/powerpc/kernel/hw_breakpoint.c
parent4474ef055c5d8cb8eaf002d69e49af71e3aa3a88 (diff)
powerpc: Dynamically calculate the dabrx based on kernel/user/hypervisor
Currently we mark the DABRX to interrupt on all matches (hypervisor/kernel/user and then filter in software. We can be a lot smarter now that we can set the DABRX dynamically. This sets the DABRX based on the flags passed by the user. Signed-off-by: Michael Neuling <mikey@neuling.org> 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.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index 6891d79ecef6..a89cae481b04 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -73,7 +73,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
73 * If so, DABR will be populated in single_step_dabr_instruction(). 73 * If so, DABR will be populated in single_step_dabr_instruction().
74 */ 74 */
75 if (current->thread.last_hit_ubp != bp) 75 if (current->thread.last_hit_ubp != bp)
76 set_dabr(info->address | info->type | DABR_TRANSLATION, DABRX_ALL); 76 set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
77 77
78 return 0; 78 return 0;
79} 79}
@@ -170,6 +170,13 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
170 170
171 info->address = bp->attr.bp_addr; 171 info->address = bp->attr.bp_addr;
172 info->len = bp->attr.bp_len; 172 info->len = bp->attr.bp_len;
173 info->dabrx = DABRX_ALL;
174 if (bp->attr.exclude_user)
175 info->dabrx &= ~DABRX_USER;
176 if (bp->attr.exclude_kernel)
177 info->dabrx &= ~DABRX_KERNEL;
178 if (bp->attr.exclude_hv)
179 info->dabrx &= ~DABRX_HYP;
173 180
174 /* 181 /*
175 * Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8) 182 * Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8)
@@ -197,7 +204,7 @@ void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)
197 204
198 info = counter_arch_bp(tsk->thread.last_hit_ubp); 205 info = counter_arch_bp(tsk->thread.last_hit_ubp);
199 regs->msr &= ~MSR_SE; 206 regs->msr &= ~MSR_SE;
200 set_dabr(info->address | info->type | DABR_TRANSLATION, DABRX_ALL); 207 set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
201 tsk->thread.last_hit_ubp = NULL; 208 tsk->thread.last_hit_ubp = NULL;
202} 209}
203 210
@@ -281,7 +288,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
281 if (!info->extraneous_interrupt) 288 if (!info->extraneous_interrupt)
282 perf_bp_event(bp, regs); 289 perf_bp_event(bp, regs);
283 290
284 set_dabr(info->address | info->type | DABR_TRANSLATION, DABRX_ALL); 291 set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
285out: 292out:
286 rcu_read_unlock(); 293 rcu_read_unlock();
287 return rc; 294 return rc;
@@ -313,7 +320,7 @@ int __kprobes single_step_dabr_instruction(struct die_args *args)
313 if (!info->extraneous_interrupt) 320 if (!info->extraneous_interrupt)
314 perf_bp_event(bp, regs); 321 perf_bp_event(bp, regs);
315 322
316 set_dabr(info->address | info->type | DABR_TRANSLATION, DABRX_ALL); 323 set_dabr(info->address | info->type | DABR_TRANSLATION, info->dabrx);
317 current->thread.last_hit_ubp = NULL; 324 current->thread.last_hit_ubp = NULL;
318 325
319 /* 326 /*