Re: [PATCH v12 04/11] tracing/wprobe: Add wprobe (watchpoint probe) trace event support
flat view
From: Jinchao Wang <hidden>
Date: 2026-08-17 11:51:33
Also in:
linux-doc, linux-perf-users, lkml
On 8/7/2026 11:34 PM, Masami Hiramatsu (Google) wrote:
quoted hunk ↗ jump to hunk
From: Masami Hiramatsu (Google) <mhiramat@kernel.org> Add hardware-breakpoint-based dynamic trace event support (wprobe). Wprobe creates a dynamic event on data read/write accesses using hardware breakpoints and logs the access context and fetchargs. Link: https://lore.kernel.org/all/59637b96946653393a7ad3c7de094094796b39c2.1785067572.git.wangjinchao600@gmail.com/ (local) Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> --- Changes in v12: - Fix syntax comment typo ('b' to 'w') and remove dead 'ret = 0' initialization in __trace_wprobe_create(). - Fix documentation notation to SYMBOL[[+|-]OFFS]. Changes in v11: - Add trace_wprobe_is_busy() to prevent releasing busy events. Changes in v9: - Use kzalloc_flex for alloc_trace_wprobe. --- Documentation/trace/index.rst | 1 Documentation/trace/wprobetrace.rst | 70 +++ include/linux/trace_events.h | 2 kernel/trace/Kconfig | 13 + kernel/trace/Makefile | 1 kernel/trace/trace.c | 9 kernel/trace/trace.h | 5 kernel/trace/trace_probe.c | 21 + kernel/trace/trace_probe.h | 10 kernel/trace/trace_wprobe.c | 765 +++++++++++++++++++++++++++++++++++ 10 files changed, 893 insertions(+), 4 deletions(-) create mode 100644 Documentation/trace/wprobetrace.rst create mode 100644 kernel/trace/trace_wprobe.cdiff --git a/Documentation/trace/index.rst b/Documentation/trace/index.rst index 5d9bf4694d5d..2f04f32001ed 100644 --- a/Documentation/trace/index.rst +++ b/Documentation/trace/index.rst@@ -36,6 +36,7 @@ the Linux kernel. kprobes kprobetrace fprobetrace + wprobetrace eprobetrace fprobe ring-buffer-designdiff --git a/Documentation/trace/wprobetrace.rst b/Documentation/trace/wprobetrace.rst new file mode 100644 index 000000000000..ad5f089b5ef5 --- /dev/null +++ b/Documentation/trace/wprobetrace.rst@@ -0,0 +1,70 @@ +.. SPDX-License-Identifier: GPL-2.0 + +======================================= +Watchpoint probe (wprobe) Event Tracing +======================================= + +.. Author: Masami Hiramatsu <mhiramat@kernel.org> + +Overview +-------- + +Wprobe event is a dynamic event based on the hardware breakpoint, which is +similar to other probe events, but it is for watching data access. It allows +you to trace which code accesses a specified data. + +As same as other dynamic events, wprobe events are defined via +`dynamic_events` interface file on tracefs. + +Synopsis of wprobe-events +------------------------- +:: + + w:[GRP/][EVENT] SPEC [FETCHARGS] : Probe on data access + + GRP : Group name for wprobe. If omitted, use "wprobes" for it. + EVENT : Event name for wprobe. If omitted, an event name is + generated based on the address or symbol. + SPEC : Breakpoint specification. + [r|w|rw]@<ADDRESS|SYMBOL[[+|-]OFFS]>[:LENGTH] + + r|w|rw : Access type, r for read, w for write, and rw for both. + Default is rw if omitted. + ADDRESS : Address to trace (hexadecimal). MUST be in kernel space. + SYMBOL : Symbol name to trace. + LENGTH : Length of the data to trace in bytes. (1, 2, 4, or 8)
Should it show default value 4?
quoted hunk ↗ jump to hunk
+ + FETCHARGS : Arguments. Each probe can have up to 128 args. + $addr : Fetch the accessing address. + $value : Fetch the memory value at the accessing address (same as +0($addr)). + @ADDR : Fetch memory at ADDR (ADDR should be in kernel) + @SYM[+|-offs] : Fetch memory at SYM +|- offs (SYM should be a data symbol) + +|-[u]OFFS(FETCHARG) : Fetch memory at FETCHARG +|- OFFS address.(\*1)(\*2) + \IMM : Store an immediate value to the argument. + NAME=FETCHARG : Set NAME as the argument name of FETCHARG. + FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types + (u8/u16/u32/u64/s8/s16/s32/s64), hexadecimal types + (x8/x16/x32/x64), "char", "string", "ustring", "symbol", "symstr" + and bitfield are supported.
FETCHARGS block is not aligned.
quoted hunk ↗ jump to hunk
+ + (\*1) this is useful for fetching a field of data structures. + (\*2) "u" means user-space dereference. + +For the details of TYPE, see :ref:`kprobetrace documentation <kprobetrace_types>`. + +Usage examples +-------------- +Here is an example to add a wprobe event on a variable `jiffies`. +:: + + # echo 'w:my_jiffies w@jiffies' >> dynamic_events + # cat dynamic_events + w:wprobes/my_jiffies w@jiffies + # echo 1 > events/wprobes/enable + # cat trace | head + # TASK-PID CPU# ||||| TIMESTAMP FUNCTION + # | | | ||||| | | + <idle>-0 [000] d.Z1. 717.026259: my_jiffies: (tick_do_update_jiffies64+0xbe/0x130) + <idle>-0 [000] d.Z1. 717.026373: my_jiffies: (tick_do_update_jiffies64+0xbe/0x130) + +You can see the code which writes to `jiffies` is `tick_do_update_jiffies64()`.diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 5cbd09c8be8d..43ffd9a76d88 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h@@ -337,6 +337,7 @@ enum { TRACE_EVENT_FL_UPROBE_BIT, TRACE_EVENT_FL_EPROBE_BIT, TRACE_EVENT_FL_FPROBE_BIT, + TRACE_EVENT_FL_WPROBE_BIT, TRACE_EVENT_FL_CUSTOM_BIT, TRACE_EVENT_FL_TEST_STR_BIT, };@@ -367,6 +368,7 @@ enum { TRACE_EVENT_FL_UPROBE = (1 << TRACE_EVENT_FL_UPROBE_BIT), TRACE_EVENT_FL_EPROBE = (1 << TRACE_EVENT_FL_EPROBE_BIT), TRACE_EVENT_FL_FPROBE = (1 << TRACE_EVENT_FL_FPROBE_BIT), + TRACE_EVENT_FL_WPROBE = (1 << TRACE_EVENT_FL_WPROBE_BIT), TRACE_EVENT_FL_CUSTOM = (1 << TRACE_EVENT_FL_CUSTOM_BIT), TRACE_EVENT_FL_TEST_STR = (1 << TRACE_EVENT_FL_TEST_STR_BIT), };diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 0ab5916575a9..b58c2565024f 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig@@ -862,6 +862,19 @@ config EPROBE_EVENTS convert the type of an event field. For example, turn an address into a string. +config WPROBE_EVENTS + bool "Enable wprobe-based dynamic events" + depends on TRACING + depends on HAVE_HW_BREAKPOINT + select PROBE_EVENTS + select DYNAMIC_EVENTS + help + This allows the user to add watchpoint tracing events based on + hardware breakpoints on the fly via the ftrace interface. + + Those events can be inserted wherever hardware breakpoints can be + set, and record accessed memory address and values. + config BPF_EVENTS depends on BPF_SYSCALL depends on (KPROBE_EVENTS || UPROBE_EVENTS) && PERF_EVENTSdiff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index f934ff586bd4..141c8323de20 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile@@ -126,6 +126,7 @@ obj-$(CONFIG_FTRACE_RECORD_RECURSION) += trace_recursion_record.o obj-$(CONFIG_FPROBE) += fprobe.o obj-$(CONFIG_RETHOOK) += rethook.o obj-$(CONFIG_FPROBE_EVENTS) += trace_fprobe.o +obj-$(CONFIG_WPROBE_EVENTS) += trace_wprobe.o obj-$(CONFIG_TRACEPOINT_BENCHMARK) += trace_benchmark.o obj-$(CONFIG_RV) += rv/diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 19cc07360005..4ebece96d8b7 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c@@ -4294,8 +4294,12 @@ static const char readme_msg[] = " uprobe_events\t\t- Create/append/remove/show the userspace dynamic events\n" "\t\t\t Write into this file to define/undefine new trace events.\n" #endif +#ifdef CONFIG_WPROBE_EVENTS + " wprobe_events\t\t- Create/append/remove/show the hardware breakpoint dynamic events\n" + "\t\t\t Write into this file to define/undefine new trace events.\n" +#endif #if defined(CONFIG_KPROBE_EVENTS) || defined(CONFIG_UPROBE_EVENTS) || \ - defined(CONFIG_FPROBE_EVENTS) + defined(CONFIG_FPROBE_EVENTS) || defined(CONFIG_WPROBE_EVENTS) "\t accepts: event-definitions (one definition per line)\n" #if defined(CONFIG_KPROBE_EVENTS) || defined(CONFIG_UPROBE_EVENTS) "\t Format: p[:[<group>/][<event>]] <place> [<args>]\n"@@ -4305,6 +4309,9 @@ static const char readme_msg[] = "\t f[:[<group>/][<event>]] <func-name>[%return] [<args>]\n" "\t t[:[<group>/][<event>]] <tracepoint> [<args>]\n" #endif +#ifdef CONFIG_WPROBE_EVENTS + "\t w[:[<group>/][<event>]] [r|w|rw]@<addr>[:<len>]\n"
missing [<args>]
quoted hunk ↗ jump to hunk
+#endif #ifdef CONFIG_HIST_TRIGGERS "\t s:[synthetic/]<event> <field> [<field>]\n" #endif
Thanks, Jinchao