From: Jinchao Wang <wangjinchao600@gmail.com>
To: "Andrew Morton" <akpm@linux-foundation.org>,
"Masami Hiramatsu (Google)" <mhiramat@kernel.org>,
"Peter Zijlstra" <peterz@infradead.org>,
"Randy Dunlap" <rdunlap@infradead.org>,
"Marco Elver" <elver@google.com>,
"Mike Rapoport" <rppt@kernel.org>,
"Alexander Potapenko" <glider@google.com>,
"Adrian Hunter" <adrian.hunter@intel.com>,
"Alexander Shishkin" <alexander.shishkin@linux.intel.com>,
"Alice Ryhl" <aliceryhl@google.com>,
"Andrey Konovalov" <andreyknvl@gmail.com>,
"Andrey Ryabinin" <ryabinin.a.a@gmail.com>,
"Andrii Nakryiko" <andrii@kernel.org>,
"Ard Biesheuvel" <ardb@kernel.org>,
"Arnaldo Carvalho de Melo" <acme@kernel.org>,
"Ben Segall" <bsegall@google.com>,
"Bill Wendling" <morbo@google.com>,
"Borislav Petkov" <bp@alien8.de>,
"Catalin Marinas" <catalin.marinas@arm.com>,
"Dave Hansen" <dave.hansen@linux.intel.com>,
"David Hildenbrand" <david@redhat.com>,
"David Kaplan" <david.kaplan@amd.com>,
"David S. Miller" <davem@davemloft.net>,
"Dietmar Eggemann" <dietmar.eggemann@arm.com>,
"Dmitry Vyukov" <dvyukov@google.com>,
"H. Peter Anvin" <hpa@zytor.com>,
"Ian Rogers" <irogers@google.com>,
"Ingo Molnar" <mingo@redhat.com>,
"James Clark" <james.clark@linaro.org>,
"Jinchao Wang" <wangjinchao600@gmail.com>,
"Jinjie Ruan" <ruanjinjie@huawei.com>,
"Jiri Olsa" <jolsa@kernel.org>,
"Jonathan Corbet" <corbet@lwn.net>,
"Juri Lelli" <juri.lelli@redhat.com>,
"Justin Stitt" <justinstitt@google.com>,
kasan-dev@googlegroups.com, "Kees Cook" <kees@kernel.org>,
"Liam R. Howlett" <Liam.Howlett@oracle.com>,
"Liang Kan" <kan.liang@linux.intel.com>,
"Linus Walleij" <linus.walleij@linaro.org>,
linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-mm@kvack.org,
linux-perf-users@vger.kernel.org,
linux-trace-kernel@vger.kernel.org, llvm@lists.linux.dev,
"Lorenzo Stoakes" <lorenzo.stoakes@oracle.com>,
"Mark Rutland" <mark.rutland@arm.com>,
"Masahiro Yamada" <masahiroy@kernel.org>,
"Mathieu Desnoyers" <mathieu.desnoyers@efficios.com>,
"Mel Gorman" <mgorman@suse.de>, "Michal Hocko" <mhocko@suse.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Nam Cao" <namcao@linutronix.de>,
"Namhyung Kim" <namhyung@kernel.org>,
"Nathan Chancellor" <nathan@kernel.org>,
"Naveen N Rao" <naveen@kernel.org>,
"Nick Desaulniers" <nick.desaulniers+lkml@gmail.com>,
"Rong Xu" <xur@google.com>,
"Sami Tolvanen" <samitolvanen@google.com>,
"Steven Rostedt" <rostedt@goodmis.org>,
"Suren Baghdasaryan" <surenb@google.com>,
"Thomas Gleixner" <tglx@linutronix.de>,
"Thomas Weißschuh" <thomas.weissschuh@linutronix.de>,
"Valentin Schneider" <vschneid@redhat.com>,
"Vincent Guittot" <vincent.guittot@linaro.org>,
"Vincenzo Frascino" <vincenzo.frascino@arm.com>,
"Vlastimil Babka" <vbabka@suse.cz>,
"Will Deacon" <will@kernel.org>,
workflows@vger.kernel.org, x86@kernel.org
Subject: [PATCH v8 01/27] x86/hw_breakpoint: Unify breakpoint install/uninstall
Date: Tue, 11 Nov 2025 00:35:56 +0800 [thread overview]
Message-ID: <20251110163634.3686676-2-wangjinchao600@gmail.com> (raw)
In-Reply-To: <20251110163634.3686676-1-wangjinchao600@gmail.com>
Consolidate breakpoint management to reduce code duplication.
The diffstat was misleading, so the stripped code size is compared instead.
After refactoring, it is reduced from 11976 bytes to 11448 bytes on my
x86_64 system built with clang.
This also makes it easier to introduce arch_reinstall_hw_breakpoint().
In addition, including linux/types.h to fix a missing build dependency.
Signed-off-by: Jinchao Wang <wangjinchao600@gmail.com>
Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
arch/x86/include/asm/hw_breakpoint.h | 6 ++
arch/x86/kernel/hw_breakpoint.c | 141 +++++++++++++++------------
2 files changed, 84 insertions(+), 63 deletions(-)
diff --git a/arch/x86/include/asm/hw_breakpoint.h b/arch/x86/include/asm/hw_breakpoint.h
index 0bc931cd0698..aa6adac6c3a2 100644
--- a/arch/x86/include/asm/hw_breakpoint.h
+++ b/arch/x86/include/asm/hw_breakpoint.h
@@ -5,6 +5,7 @@
#include <uapi/asm/hw_breakpoint.h>
#define __ARCH_HW_BREAKPOINT_H
+#include <linux/types.h>
/*
* The name should probably be something dealt in
@@ -18,6 +19,11 @@ struct arch_hw_breakpoint {
u8 type;
};
+enum bp_slot_action {
+ BP_SLOT_ACTION_INSTALL,
+ BP_SLOT_ACTION_UNINSTALL,
+};
+
#include <linux/kdebug.h>
#include <linux/percpu.h>
#include <linux/list.h>
diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c
index b01644c949b2..3658ace4bd8d 100644
--- a/arch/x86/kernel/hw_breakpoint.c
+++ b/arch/x86/kernel/hw_breakpoint.c
@@ -48,7 +48,6 @@ static DEFINE_PER_CPU(unsigned long, cpu_debugreg[HBP_NUM]);
*/
static DEFINE_PER_CPU(struct perf_event *, bp_per_reg[HBP_NUM]);
-
static inline unsigned long
__encode_dr7(int drnum, unsigned int len, unsigned int type)
{
@@ -85,96 +84,112 @@ int decode_dr7(unsigned long dr7, int bpnum, unsigned *len, unsigned *type)
}
/*
- * Install a perf counter breakpoint.
- *
- * We seek a free debug address register and use it for this
- * breakpoint. Eventually we enable it in the debug control register.
- *
- * Atomic: we hold the counter->ctx->lock and we only handle variables
- * and registers local to this cpu.
+ * We seek a slot and change it or keep it based on the action.
+ * Returns slot number on success, negative error on failure.
+ * Must be called with IRQs disabled.
*/
-int arch_install_hw_breakpoint(struct perf_event *bp)
+static int manage_bp_slot(struct perf_event *bp, enum bp_slot_action action)
{
- struct arch_hw_breakpoint *info = counter_arch_bp(bp);
- unsigned long *dr7;
- int i;
-
- lockdep_assert_irqs_disabled();
+ struct perf_event *old_bp;
+ struct perf_event *new_bp;
+ int slot;
+
+ switch (action) {
+ case BP_SLOT_ACTION_INSTALL:
+ old_bp = NULL;
+ new_bp = bp;
+ break;
+ case BP_SLOT_ACTION_UNINSTALL:
+ old_bp = bp;
+ new_bp = NULL;
+ break;
+ default:
+ return -EINVAL;
+ }
- for (i = 0; i < HBP_NUM; i++) {
- struct perf_event **slot = this_cpu_ptr(&bp_per_reg[i]);
+ for (slot = 0; slot < HBP_NUM; slot++) {
+ struct perf_event **curr = this_cpu_ptr(&bp_per_reg[slot]);
- if (!*slot) {
- *slot = bp;
- break;
+ if (*curr == old_bp) {
+ *curr = new_bp;
+ return slot;
}
}
- if (WARN_ONCE(i == HBP_NUM, "Can't find any breakpoint slot"))
- return -EBUSY;
+ if (old_bp) {
+ WARN_ONCE(1, "Can't find matching breakpoint slot");
+ return -EINVAL;
+ }
+
+ WARN_ONCE(1, "No free breakpoint slots");
+ return -EBUSY;
+}
+
+static void setup_hwbp(struct arch_hw_breakpoint *info, int slot, bool enable)
+{
+ unsigned long dr7;
- set_debugreg(info->address, i);
- __this_cpu_write(cpu_debugreg[i], info->address);
+ set_debugreg(info->address, slot);
+ __this_cpu_write(cpu_debugreg[slot], info->address);
- dr7 = this_cpu_ptr(&cpu_dr7);
- *dr7 |= encode_dr7(i, info->len, info->type);
+ dr7 = this_cpu_read(cpu_dr7);
+ if (enable)
+ dr7 |= encode_dr7(slot, info->len, info->type);
+ else
+ dr7 &= ~__encode_dr7(slot, info->len, info->type);
/*
- * Ensure we first write cpu_dr7 before we set the DR7 register.
- * This ensures an NMI never see cpu_dr7 0 when DR7 is not.
+ * Enabling:
+ * Ensure we first write cpu_dr7 before we set the DR7 register.
+ * This ensures an NMI never see cpu_dr7 0 when DR7 is not.
*/
+ if (enable)
+ this_cpu_write(cpu_dr7, dr7);
+
barrier();
- set_debugreg(*dr7, 7);
+ set_debugreg(dr7, 7);
+
if (info->mask)
- amd_set_dr_addr_mask(info->mask, i);
+ amd_set_dr_addr_mask(enable ? info->mask : 0, slot);
- return 0;
+ /*
+ * Disabling:
+ * Ensure the write to cpu_dr7 is after we've set the DR7 register.
+ * This ensures an NMI never see cpu_dr7 0 when DR7 is not.
+ */
+ if (!enable)
+ this_cpu_write(cpu_dr7, dr7);
}
/*
- * Uninstall the breakpoint contained in the given counter.
- *
- * First we search the debug address register it uses and then we disable
- * it.
- *
- * Atomic: we hold the counter->ctx->lock and we only handle variables
- * and registers local to this cpu.
+ * find suitable breakpoint slot and set it up based on the action
*/
-void arch_uninstall_hw_breakpoint(struct perf_event *bp)
+static int arch_manage_bp(struct perf_event *bp, enum bp_slot_action action)
{
- struct arch_hw_breakpoint *info = counter_arch_bp(bp);
- unsigned long dr7;
- int i;
+ struct arch_hw_breakpoint *info;
+ int slot;
lockdep_assert_irqs_disabled();
- for (i = 0; i < HBP_NUM; i++) {
- struct perf_event **slot = this_cpu_ptr(&bp_per_reg[i]);
-
- if (*slot == bp) {
- *slot = NULL;
- break;
- }
- }
-
- if (WARN_ONCE(i == HBP_NUM, "Can't find any breakpoint slot"))
- return;
+ slot = manage_bp_slot(bp, action);
+ if (slot < 0)
+ return slot;
- dr7 = this_cpu_read(cpu_dr7);
- dr7 &= ~__encode_dr7(i, info->len, info->type);
+ info = counter_arch_bp(bp);
+ setup_hwbp(info, slot, action != BP_SLOT_ACTION_UNINSTALL);
- set_debugreg(dr7, 7);
- if (info->mask)
- amd_set_dr_addr_mask(0, i);
+ return 0;
+}
- /*
- * Ensure the write to cpu_dr7 is after we've set the DR7 register.
- * This ensures an NMI never see cpu_dr7 0 when DR7 is not.
- */
- barrier();
+int arch_install_hw_breakpoint(struct perf_event *bp)
+{
+ return arch_manage_bp(bp, BP_SLOT_ACTION_INSTALL);
+}
- this_cpu_write(cpu_dr7, dr7);
+void arch_uninstall_hw_breakpoint(struct perf_event *bp)
+{
+ arch_manage_bp(bp, BP_SLOT_ACTION_UNINSTALL);
}
static int arch_bp_generic_len(int x86_len)
--
2.43.0
next prev parent reply other threads:[~2025-11-10 16:36 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-11-10 16:35 [PATCH v8 00/27] mm/ksw: Introduce KStackWatch debugging tool Jinchao Wang
2025-11-10 16:35 ` Jinchao Wang [this message]
2025-11-10 16:35 ` [PATCH v8 02/27] x86/hw_breakpoint: Add arch_reinstall_hw_breakpoint Jinchao Wang
2025-11-10 16:35 ` [PATCH v8 03/27] HWBP: Add modify_wide_hw_breakpoint_local() API Jinchao Wang
2025-11-10 16:35 ` [PATCH v8 04/27] mm/ksw: add build system support Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 05/27] mm/ksw: add ksw_config struct and parser Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 06/27] mm/ksw: add singleton debugfs interface Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 07/27] mm/ksw: add HWBP pre-allocation Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 08/27] mm/ksw: Add atomic watchpoint management api Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 09/27] mm/ksw: ignore false positives from exit trampolines Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 10/27] mm/ksw: support CPU hotplug Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 11/27] sched/ksw: add per-task context Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 12/27] mm/ksw: add entry kprobe and exit fprobe management Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 13/27] mm/ksw: add per-task ctx tracking Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 14/27] mm/ksw: resolve stack watch addr and len Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 15/27] mm/ksw: limit canary search to current stack frame Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 16/27] mm/ksw: manage probe and HWBP lifecycle via procfs Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 17/27] mm/ksw: add KSTACKWATCH_PROFILING to measure probe cost Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 18/27] arm64/hw_breakpoint: Add arch_reinstall_hw_breakpoint Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 19/27] arm64/hwbp/ksw: integrate KStackWatch handler support Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 20/27] mm/ksw: add self-debug helpers Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 21/27] mm/ksw: add test module Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 22/27] mm/ksw: add stack overflow test Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 23/27] mm/ksw: add recursive depth test Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 24/27] mm/ksw: add multi-thread corruption test cases Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 25/27] tools/ksw: add arch-specific test script Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 26/27] docs: add KStackWatch document Jinchao Wang
2025-11-10 16:36 ` [PATCH v8 27/27] MAINTAINERS: add entry for KStackWatch Jinchao Wang
2025-11-10 17:33 ` [PATCH v8 00/27] mm/ksw: Introduce KStackWatch debugging tool Matthew Wilcox
2025-11-12 2:14 ` Jinchao Wang
2025-11-12 20:36 ` Matthew Wilcox
2025-11-13 4:40 ` Jinchao Wang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251110163634.3686676-2-wangjinchao600@gmail.com \
--to=wangjinchao600@gmail.com \
--cc=Liam.Howlett@oracle.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=akpm@linux-foundation.org \
--cc=alexander.shishkin@linux.intel.com \
--cc=aliceryhl@google.com \
--cc=andreyknvl@gmail.com \
--cc=andrii@kernel.org \
--cc=ardb@kernel.org \
--cc=bp@alien8.de \
--cc=bsegall@google.com \
--cc=catalin.marinas@arm.com \
--cc=corbet@lwn.net \
--cc=dave.hansen@linux.intel.com \
--cc=davem@davemloft.net \
--cc=david.kaplan@amd.com \
--cc=david@redhat.com \
--cc=dietmar.eggemann@arm.com \
--cc=dvyukov@google.com \
--cc=elver@google.com \
--cc=glider@google.com \
--cc=hpa@zytor.com \
--cc=irogers@google.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=juri.lelli@redhat.com \
--cc=justinstitt@google.com \
--cc=kan.liang@linux.intel.com \
--cc=kasan-dev@googlegroups.com \
--cc=kees@kernel.org \
--cc=linus.walleij@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=lorenzo.stoakes@oracle.com \
--cc=mark.rutland@arm.com \
--cc=masahiroy@kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mgorman@suse.de \
--cc=mhiramat@kernel.org \
--cc=mhocko@suse.com \
--cc=mingo@redhat.com \
--cc=morbo@google.com \
--cc=namcao@linutronix.de \
--cc=namhyung@kernel.org \
--cc=nathan@kernel.org \
--cc=naveen@kernel.org \
--cc=nick.desaulniers+lkml@gmail.com \
--cc=ojeda@kernel.org \
--cc=peterz@infradead.org \
--cc=rdunlap@infradead.org \
--cc=rostedt@goodmis.org \
--cc=rppt@kernel.org \
--cc=ruanjinjie@huawei.com \
--cc=ryabinin.a.a@gmail.com \
--cc=samitolvanen@google.com \
--cc=surenb@google.com \
--cc=tglx@linutronix.de \
--cc=thomas.weissschuh@linutronix.de \
--cc=vbabka@suse.cz \
--cc=vincent.guittot@linaro.org \
--cc=vincenzo.frascino@arm.com \
--cc=vschneid@redhat.com \
--cc=will@kernel.org \
--cc=workflows@vger.kernel.org \
--cc=x86@kernel.org \
--cc=xur@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).