[PATCH 3/3] HWBP: Add modify_local_hw_breakpoint_addr() API
From: Jinchao Wang <hidden>
Date: 2026-07-26 12:23:33
Also in:
linux-edac, linux-perf-users, lkml
Subsystem:
performance events subsystem, the rest, x86 architecture (32-bit and 64-bit) · Maintainers:
Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Linus Torvalds, Thomas Gleixner, Borislav Petkov, Dave Hansen
From: "Masami Hiramatsu (Google)" <mhiramat@kernel.org> Add modify_local_hw_breakpoint_addr() to update only the watched address of an installed hardware breakpoint on the local CPU without releasing and reserving its hardware slot. This is available when the architecture selects CONFIG_HAVE_MODIFY_LOCAL_HW_BREAKPOINT_ADDR. The caller must provide an installed local event and a valid address, and update other CPUs separately. Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> Signed-off-by: Jinchao Wang <redacted> --- arch/Kconfig | 8 ++++++++ arch/x86/Kconfig | 1 + include/linux/hw_breakpoint.h | 6 ++++++ kernel/events/hw_breakpoint.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+)
diff --git a/arch/Kconfig b/arch/Kconfig
index fa7507ac8e13..bea383408e32 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig@@ -457,6 +457,14 @@ config HAVE_MIXED_BREAKPOINTS_REGS Select this option if your arch implements breakpoints under the latter fashion. +config HAVE_MODIFY_LOCAL_HW_BREAKPOINT_ADDR + bool + depends on HAVE_HW_BREAKPOINT + help + Select this if the architecture can modify the address of an + installed hardware breakpoint on the local CPU without releasing + and reserving its hardware slot. + config HAVE_USER_RETURN_NOTIFIER bool
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index bdad90f210e4..09e599f2d0dd 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig@@ -246,6 +246,7 @@ config X86 select HAVE_FUNCTION_TRACER select HAVE_GCC_PLUGINS select HAVE_HW_BREAKPOINT + select HAVE_MODIFY_LOCAL_HW_BREAKPOINT_ADDR select HAVE_IOREMAP_PROT select HAVE_IRQ_EXIT_ON_IRQ_STACK if X86_64 select HAVE_IRQ_TIME_ACCOUNTING
diff --git a/include/linux/hw_breakpoint.h b/include/linux/hw_breakpoint.h
index db199d653dd1..bf65c7fffd99 100644
--- a/include/linux/hw_breakpoint.h
+++ b/include/linux/hw_breakpoint.h@@ -81,6 +81,9 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context); +int modify_local_hw_breakpoint_addr(struct perf_event *bp, + unsigned long addr); + extern int register_perf_hw_breakpoint(struct perf_event *bp); extern void unregister_hw_breakpoint(struct perf_event *bp); extern void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events);
@@ -124,6 +127,9 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr, perf_overflow_handler_t triggered, void *context) { return NULL; } static inline int +modify_local_hw_breakpoint_addr(struct perf_event *bp, + unsigned long addr) { return -EOPNOTSUPP; } +static inline int register_perf_hw_breakpoint(struct perf_event *bp) { return -ENOSYS; } static inline void unregister_hw_breakpoint(struct perf_event *bp) { } static inline void
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index 789add0c185a..0b1fc01f1934 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c@@ -888,6 +888,36 @@ void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) } EXPORT_SYMBOL_GPL(unregister_wide_hw_breakpoint); +/** + * modify_local_hw_breakpoint_addr - update a local breakpoint address + * @bp: the hwbp perf event for this CPU + * @addr: the new address for @bp + * + * Update only the address of an installed breakpoint on the local CPU without + * releasing and reserving its hardware slot. The caller must update other CPUs. + * Return 0, or -EOPNOTSUPP if the architecture does not support this operation. + */ +#ifdef CONFIG_HAVE_MODIFY_LOCAL_HW_BREAKPOINT_ADDR +int modify_local_hw_breakpoint_addr(struct perf_event *bp, + unsigned long addr) +{ + lockdep_assert_irqs_disabled(); + + counter_arch_bp(bp)->address = addr; + bp->attr.bp_addr = addr; + arch_modify_local_hw_breakpoint_addr(bp, addr); + + return 0; +} +#else +int modify_local_hw_breakpoint_addr(struct perf_event *bp, + unsigned long addr) +{ + return -EOPNOTSUPP; +} +#endif +EXPORT_SYMBOL_GPL(modify_local_hw_breakpoint_addr); + /** * hw_breakpoint_is_used - check if breakpoints are currently used *
--
2.53.0