aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWill Deacon <will.deacon@arm.com>2012-09-24 13:01:13 -0400
committerWill Deacon <will.deacon@arm.com>2012-11-09 06:47:06 -0500
commit0daa034e696ac601061cbf60fda41ad39678ae14 (patch)
tree5513f12675dcf390351336abb3ce7148530f28ab
parent5ad29ea24e58777aa1daaa2255670ffb40aefd99 (diff)
ARM: hw_breakpoint: check if monitor mode is enabled during validation
Rather than attempt to enable monitor mode explicitly when scheduling in a breakpoint event (which could raise an undefined exception trap when accessing DBGDSCRext), instead check that DBGDSCRint.MDBGen is set during event validation and report an error to the caller if not. Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm/kernel/hw_breakpoint.c28
1 files changed, 15 insertions, 13 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 983558eb9023..8e9532152bd9 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -228,6 +228,13 @@ static int get_num_brps(void)
228 * be put into halting debug mode at any time by an external debugger 228 * be put into halting debug mode at any time by an external debugger
229 * but there is nothing we can do to prevent that. 229 * but there is nothing we can do to prevent that.
230 */ 230 */
231static int monitor_mode_enabled(void)
232{
233 u32 dscr;
234 ARM_DBG_READ(c1, 0, dscr);
235 return !!(dscr & ARM_DSCR_MDBGEN);
236}
237
231static int enable_monitor_mode(void) 238static int enable_monitor_mode(void)
232{ 239{
233 u32 dscr; 240 u32 dscr;
@@ -321,14 +328,9 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
321{ 328{
322 struct arch_hw_breakpoint *info = counter_arch_bp(bp); 329 struct arch_hw_breakpoint *info = counter_arch_bp(bp);
323 struct perf_event **slot, **slots; 330 struct perf_event **slot, **slots;
324 int i, max_slots, ctrl_base, val_base, ret = 0; 331 int i, max_slots, ctrl_base, val_base;
325 u32 addr, ctrl; 332 u32 addr, ctrl;
326 333
327 /* Ensure that we are in monitor mode and halting mode is disabled. */
328 ret = enable_monitor_mode();
329 if (ret)
330 goto out;
331
332 addr = info->address; 334 addr = info->address;
333 ctrl = encode_ctrl_reg(info->ctrl) | 0x1; 335 ctrl = encode_ctrl_reg(info->ctrl) | 0x1;
334 336
@@ -355,10 +357,8 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
355 } 357 }
356 } 358 }
357 359
358 if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) { 360 if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
359 ret = -EBUSY; 361 return -EBUSY;
360 goto out;
361 }
362 362
363 /* Override the breakpoint data with the step data. */ 363 /* Override the breakpoint data with the step data. */
364 if (info->step_ctrl.enabled) { 364 if (info->step_ctrl.enabled) {
@@ -376,9 +376,7 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
376 376
377 /* Setup the control register. */ 377 /* Setup the control register. */
378 write_wb_reg(ctrl_base + i, ctrl); 378 write_wb_reg(ctrl_base + i, ctrl);
379 379 return 0;
380out:
381 return ret;
382} 380}
383 381
384void arch_uninstall_hw_breakpoint(struct perf_event *bp) 382void arch_uninstall_hw_breakpoint(struct perf_event *bp)
@@ -589,6 +587,10 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
589 int ret = 0; 587 int ret = 0;
590 u32 offset, alignment_mask = 0x3; 588 u32 offset, alignment_mask = 0x3;
591 589
590 /* Ensure that we are in monitor debug mode. */
591 if (!monitor_mode_enabled())
592 return -ENODEV;
593
592 /* Build the arch_hw_breakpoint. */ 594 /* Build the arch_hw_breakpoint. */
593 ret = arch_build_bp_info(bp); 595 ret = arch_build_bp_info(bp);
594 if (ret) 596 if (ret)