diff options
author | Dave Airlie <airlied@redhat.com> | 2020-08-11 11:58:31 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-08-11 11:58:31 +1000 |
commit | c44264f9f729fd63bd6a81a6ac5cd6cd49af09e5 (patch) | |
tree | ad77b18ffeafb50b3eb9ba6472670dc1d96f5558 /arch/arm/kernel/hw_breakpoint.c | |
parent | ca457ab5908603b36be903e73977afde1ba03c84 (diff) | |
parent | bcf876870b95592b52519ed4aafcf9d95999bc9c (diff) | |
download | linux-c44264f9f729fd63bd6a81a6ac5cd6cd49af09e5.tar.bz2 |
Merge tag 'v5.8' into drm-next
I need to backmerge 5.8 as I've got a bunch of fixes sitting
on an rc7 base that I want to land.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'arch/arm/kernel/hw_breakpoint.c')
-rw-r--r-- | arch/arm/kernel/hw_breakpoint.c | 27 |
1 files changed, 22 insertions, 5 deletions
diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 02ca7adf5375..7fff88e61252 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -683,6 +683,12 @@ static void disable_single_step(struct perf_event *bp) arch_install_hw_breakpoint(bp); } +static int watchpoint_fault_on_uaccess(struct pt_regs *regs, + struct arch_hw_breakpoint *info) +{ + return !user_mode(regs) && info->ctrl.privilege == ARM_BREAKPOINT_USER; +} + static void watchpoint_handler(unsigned long addr, unsigned int fsr, struct pt_regs *regs) { @@ -742,16 +748,27 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, } pr_debug("watchpoint fired: address = 0x%x\n", info->trigger); + + /* + * If we triggered a user watchpoint from a uaccess routine, + * then handle the stepping ourselves since userspace really + * can't help us with this. + */ + if (watchpoint_fault_on_uaccess(regs, info)) + goto step; + perf_bp_event(wp, regs); /* - * If no overflow handler is present, insert a temporary - * mismatch breakpoint so we can single-step over the - * watchpoint trigger. + * Defer stepping to the overflow handler if one is installed. + * Otherwise, insert a temporary mismatch breakpoint so that + * we can single-step over the watchpoint trigger. */ - if (is_default_overflow_handler(wp)) - enable_single_step(wp, instruction_pointer(regs)); + if (!is_default_overflow_handler(wp)) + goto unlock; +step: + enable_single_step(wp, instruction_pointer(regs)); unlock: rcu_read_unlock(); } |