Add support for identifying KStackWatch watchpoints in the ARM64 hardware breakpoint handler. When a watchpoint belongs to KStackWatch, the handler bypasses single-step re-arming to allow proper recovery. Introduce is_ksw_watch_handler() to detect KStackWatch-managed breakpoints and use it in watchpoint_report() under CONFIG_KSTACKWATCH. Signed-off-by: Jinchao Wang --- arch/arm64/kernel/hw_breakpoint.c | 7 +++++++ include/linux/kstackwatch.h | 2 ++ mm/kstackwatch/watch.c | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/arch/arm64/kernel/hw_breakpoint.c b/arch/arm64/kernel/hw_breakpoint.c index bd7d23d7893d..7abcd988c5c2 100644 --- a/arch/arm64/kernel/hw_breakpoint.c +++ b/arch/arm64/kernel/hw_breakpoint.c @@ -14,6 +14,9 @@ #include #include #include +#ifdef CONFIG_KSTACKWATCH +#include +#endif #include #include #include @@ -738,6 +741,10 @@ static int watchpoint_report(struct perf_event *wp, unsigned long addr, struct pt_regs *regs) { int step = is_default_overflow_handler(wp); +#ifdef CONFIG_KSTACKWATCH + if (is_ksw_watch_handler(wp)) + step = 1; +#endif struct arch_hw_breakpoint *info = counter_arch_bp(wp); info->trigger = addr; diff --git a/include/linux/kstackwatch.h b/include/linux/kstackwatch.h index afedd9823de9..ce3882acc5dc 100644 --- a/include/linux/kstackwatch.h +++ b/include/linux/kstackwatch.h @@ -53,6 +53,8 @@ struct ksw_watchpoint { struct llist_node node; // for atomic watch_on and off struct list_head list; // for cpu online and offline }; + +bool is_ksw_watch_handler(struct perf_event *event); int ksw_watch_init(void); void ksw_watch_exit(void); int ksw_watch_get(struct ksw_watchpoint **out_wp); diff --git a/mm/kstackwatch/watch.c b/mm/kstackwatch/watch.c index 99184f63d7e3..c2aa912bf4c4 100644 --- a/mm/kstackwatch/watch.c +++ b/mm/kstackwatch/watch.c @@ -64,6 +64,14 @@ static void ksw_watch_handler(struct perf_event *bp, panic("Stack corruption detected"); } +bool is_ksw_watch_handler(struct perf_event *event) +{ + perf_overflow_handler_t overflow_handler = event->overflow_handler; + + if (unlikely(overflow_handler == ksw_watch_handler)) + return true; + return false; +} static void ksw_watch_on_local_cpu(void *info) { struct ksw_watchpoint *wp = info; -- 2.43.0