diff options
| -rw-r--r-- | arch/arm/kernel/hw_breakpoint.c | 55 |
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? */ | ||
| 163 | static 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. */ |
| 163 | static int get_num_wrp_resources(void) | 169 | static 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 | |||
| 634 | out: | 657 | out: |
| 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; |
