aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/kernel/hw_breakpoint.c55
1 files changed, 40 insertions, 15 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index ba386bd94107..18d39ea4c02f 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -159,6 +159,12 @@ static int debug_arch_supported(void)
159 arch >= ARM_DEBUG_ARCH_V7_1; 159 arch >= ARM_DEBUG_ARCH_V7_1;
160} 160}
161 161
162/* Can we determine the watchpoint access type from the fsr? */
163static int debug_exception_updates_fsr(void)
164{
165 return 0;
166}
167
162/* Determine number of WRP registers available. */ 168/* Determine number of WRP registers available. */
163static int get_num_wrp_resources(void) 169static int get_num_wrp_resources(void)
164{ 170{
@@ -619,18 +625,35 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
619 info->address &= ~alignment_mask; 625 info->address &= ~alignment_mask;
620 info->ctrl.len <<= offset; 626 info->ctrl.len <<= offset;
621 627
622 /* 628 if (!bp->overflow_handler) {
623 * Currently we rely on an overflow handler to take 629 /*
624 * care of single-stepping the breakpoint when it fires. 630 * Mismatch breakpoints are required for single-stepping
625 * In the case of userspace breakpoints on a core with V7 debug, 631 * breakpoints.
626 * we can use the mismatch feature as a poor-man's hardware 632 */
627 * single-step, but this only works for per-task breakpoints. 633 if (!core_has_mismatch_brps())
628 */ 634 return -EINVAL;
629 if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) || 635
630 !core_has_mismatch_brps() || !bp->hw.bp_target)) { 636 /* We don't allow mismatch breakpoints in kernel space. */
631 pr_warning("overflow handler required but none found\n"); 637 if (arch_check_bp_in_kernelspace(bp))
632 ret = -EINVAL; 638 return -EPERM;
639
640 /*
641 * Per-cpu breakpoints are not supported by our stepping
642 * mechanism.
643 */
644 if (!bp->hw.bp_target)
645 return -EINVAL;
646
647 /*
648 * We only support specific access types if the fsr
649 * reports them.
650 */
651 if (!debug_exception_updates_fsr() &&
652 (info->ctrl.type == ARM_BREAKPOINT_LOAD ||
653 info->ctrl.type == ARM_BREAKPOINT_STORE))
654 return -EINVAL;
633 } 655 }
656
634out: 657out:
635 return ret; 658 return ret;
636} 659}
@@ -706,10 +729,12 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
706 goto unlock; 729 goto unlock;
707 730
708 /* Check that the access type matches. */ 731 /* Check that the access type matches. */
709 access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W : 732 if (debug_exception_updates_fsr()) {
710 HW_BREAKPOINT_R; 733 access = (fsr & ARM_FSR_ACCESS_MASK) ?
711 if (!(access & hw_breakpoint_type(wp))) 734 HW_BREAKPOINT_W : HW_BREAKPOINT_R;
712 goto unlock; 735 if (!(access & hw_breakpoint_type(wp)))
736 goto unlock;
737 }
713 738
714 /* We have a winner. */ 739 /* We have a winner. */
715 info->trigger = addr; 740 info->trigger = addr;