| @@ -683,6 +683,12 @@ static void disable_single_step(struct perf_event *bp) · 682 unmodified lines |
| 683 | arch_install_hw_breakpoint(bp); | 683 | arch_install_hw_breakpoint(bp); |
| 684 | } | 684 | } |
| 685 | | 685 | |
| | 686 | static int watchpoint_fault_on_uaccess(struct pt_regs *regs, |
| | 687 | struct arch_hw_breakpoint *info) |
| | 688 | { |
| | 689 | return !user_mode(regs) && info->ctrl.privilege == ARM_BREAKPOINT_USER; |
| | 690 | } |
| | 691 | |
| 686 | static void watchpoint_handler(unsigned long addr, unsigned int fsr, | 692 | static void watchpoint_handler(unsigned long addr, unsigned int fsr, |
| 687 | struct pt_regs *regs) | 693 | struct pt_regs *regs) |
| 688 | { | 694 | { |
| @@ -742,16 +748,27 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, · 53 unmodified lines |
| 742 | } | 748 | } |
| 743 | | 749 | |
| 744 | pr_debug("watchpoint fired: address = 0x%x\n", info->trigger); | 750 | pr_debug("watchpoint fired: address = 0x%x\n", info->trigger); |
| | 751 | |
| | 752 | /* |
| | 753 | * If we triggered a user watchpoint from a uaccess routine, |
| | 754 | * then handle the stepping ourselves since userspace really |
| | 755 | * can't help us with this. |
| | 756 | */ |
| | 757 | if (watchpoint_fault_on_uaccess(regs, info)) |
| | 758 | goto step; |
| | 759 | |
| 745 | perf_bp_event(wp, regs); | 760 | perf_bp_event(wp, regs); |
| 746 | | 761 | |
| 747 | /* | 762 | /* |
| 748 | * If no overflow handler is present, insert a temporary | 763 | * Defer stepping to the overflow handler if one is installed. |
| 749 | * mismatch breakpoint so we can single-step over the | 764 | * Otherwise, insert a temporary mismatch breakpoint so that |
| 750 | * watchpoint trigger. | 765 | * we can single-step over the watchpoint trigger. |
| 751 | */ | 766 | */ |
| 752 | if (is_default_overflow_handler(wp)) | 767 | if (!is_default_overflow_handler(wp)) |
| 753 | enable_single_step(wp, instruction_pointer(regs)); | 768 | goto unlock; |
| 754 | | 769 | |
| | 770 | step: |
| | 771 | enable_single_step(wp, instruction_pointer(regs)); |
| 755 | unlock: | 772 | unlock: |
| 756 | rcu_read_unlock(); | 773 | rcu_read_unlock(); |
| 757 | } | 774 | } |