Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+15 -13
+15 -13
arch/arm/kernel/hw_breakpoint.c
··· 228 228 * be put into halting debug mode at any time by an external debugger 229 229 * but there is nothing we can do to prevent that. 230 230 */ 231 + static int monitor_mode_enabled(void) 232 + { 233 + u32 dscr; 234 + ARM_DBG_READ(c1, 0, dscr); 235 + return !!(dscr & ARM_DSCR_MDBGEN); 236 + } 237 + 231 238 static int enable_monitor_mode(void) 232 239 { 233 240 u32 dscr; ··· 328 321 { 329 322 struct arch_hw_breakpoint *info = counter_arch_bp(bp); 330 323 struct perf_event **slot, **slots; 331 - int i, max_slots, ctrl_base, val_base, ret = 0; 324 + int i, max_slots, ctrl_base, val_base; 332 325 u32 addr, ctrl; 333 - 334 - /* Ensure that we are in monitor mode and halting mode is disabled. */ 335 - ret = enable_monitor_mode(); 336 - if (ret) 337 - goto out; 338 326 339 327 addr = info->address; 340 328 ctrl = encode_ctrl_reg(info->ctrl) | 0x1; ··· 357 355 } 358 356 } 359 357 360 - if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) { 361 - ret = -EBUSY; 362 - goto out; 363 - } 358 + if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) 359 + return -EBUSY; 364 360 365 361 /* Override the breakpoint data with the step data. */ 366 362 if (info->step_ctrl.enabled) { ··· 376 376 377 377 /* Setup the control register. */ 378 378 write_wb_reg(ctrl_base + i, ctrl); 379 - 380 - out: 381 - return ret; 379 + return 0; 382 380 } 383 381 384 382 void arch_uninstall_hw_breakpoint(struct perf_event *bp) ··· 586 588 struct arch_hw_breakpoint *info = counter_arch_bp(bp); 587 589 int ret = 0; 588 590 u32 offset, alignment_mask = 0x3; 591 + 592 + /* Ensure that we are in monitor debug mode. */ 593 + if (!monitor_mode_enabled()) 594 + return -ENODEV; 589 595 590 596 /* Build the arch_hw_breakpoint. */ 591 597 ret = arch_build_bp_info(bp);