From: Andi Kleen <ak@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: mhiramat@kernel.org, oleg@redhat.com, peterz@infradead.org,
tglx@kernel.org, x86@kernel.org, jolsa@kernel.org,
linux-perf-users@vger.kernel.org, adrian.hunter@intel.com,
Andi Kleen <ak@kernel.org>
Subject: [RFC v1 17/19] ptwrite uprobes / perf tools probe: Add support of ptwrite probes
Date: Mon, 31 Aug 2026 08:04:53 -0700 [thread overview]
Message-ID: <20260831150651.1134594-18-ak@kernel.org> (raw)
In-Reply-To: <20260831150651.1134594-1-ak@kernel.org>
Add a --ptwrite option to perf probe to enable ptwrite probes. It is mainly
identical to the normal uprobes support, but knows about the new ptw:
probe syntax.
Assisted-by: omp:gpt-5.6-luna
Signed-off-by: Andi Kleen <ak@kernel.org>
---
tools/perf/Documentation/perf-probe.txt | 6 ++++++
tools/perf/builtin-probe.c | 17 ++++++++++++++++-
tools/perf/util/probe-event.c | 18 +++++++++++++-----
tools/perf/util/probe-event.h | 2 ++
4 files changed, 37 insertions(+), 6 deletions(-)
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 2e5790325430..859f7ec42422 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -136,6 +136,12 @@ OPTIONS
--max-probes=NUM::
Set the maximum number of probe points for an event. Default is 128.
+--ptwrite::
+ Create a ptwrite uprobe (with -x). The probe writes its values
+ into the Intel PT trace stream instead of entering the kernel,
+ which is faster. Requires an Intel PT/PTWRITE CPU and a kernel
+ with ptwrite uprobe support.
+
--target-ns=PID:
Obtain mount namespace information from the target pid. This is
used when creating a uprobe for a process that resides in a
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index a67b565278ae..f6c90bf9cd0d 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -40,6 +40,7 @@ static struct {
int command; /* Command short_name */
bool list_events;
bool uprobes;
+ bool ptwrite;
bool target_used;
int nevents;
struct perf_probe_event events[MAX_PROBES];
@@ -62,6 +63,7 @@ static int parse_probe_event(const char *str)
}
pev->uprobes = params->uprobes;
+ pev->ptwrite = params->ptwrite;
if (params->target) {
pev->target = strdup(params->target);
if (!pev->target)
@@ -73,9 +75,15 @@ static int parse_probe_event(const char *str)
/* Parse a perf-probe command into event */
ret = parse_perf_probe_command(str, pev);
+ if (ret < 0)
+ return ret;
+ if (pev->ptwrite && pev->point.retprobe) {
+ pr_err("Error: ptwrite probes are entry-only (no %%return).\n");
+ return -EINVAL;
+ }
pr_debug("%d arguments\n", pev->nargs);
- return ret;
+ return 0;
}
static int params_add_filter(const char *str)
@@ -532,6 +540,8 @@ __cmd_probe(int argc, const char **argv)
"be more verbose (show parsed arguments, etc)"),
OPT_BOOLEAN('q', "quiet", &quiet,
"be quiet (do not show any warnings or messages)"),
+ OPT_BOOLEAN(0, "ptwrite", ¶ms->ptwrite,
+ "create trap-free ptwrite uprobes (requires -x)"),
OPT_CALLBACK_DEFAULT('l', "list", NULL, "[GROUP:]EVENT",
"list up probe events",
opt_set_filter_with_command, DEFAULT_LIST_FILTER),
@@ -733,6 +743,11 @@ __cmd_probe(int argc, const char **argv)
parse_options_usage(NULL, options, "x", true);
return -EINVAL;
}
+ if (params->ptwrite && !params->uprobes) {
+ pr_err(" Error: --ptwrite requires -x.\n");
+ parse_options_usage(NULL, options, "x", true);
+ return -EINVAL;
+ }
ret = perf_add_probe_events(params->events, params->nevents);
if (ret < 0) {
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 11ae4a09412c..0417fa5ccfbe 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1930,6 +1930,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
ret = -EINVAL;
goto out;
}
+ tev->ptwrite = !strcmp(fmt1_str, "ptw");
pr = fmt1_str[0];
tev->group = strdup(fmt2_str);
tev->event = strdup(fmt3_str);
@@ -1937,7 +1938,8 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
ret = -ENOMEM;
goto out;
}
- pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
+ pr_debug("Group:%s Event:%s probe:%c%s\n", tev->group, tev->event, pr,
+ tev->ptwrite ? " (ptwrite)" : "");
tp->retprobe = (pr == 'r');
@@ -2260,9 +2262,11 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
if (strbuf_init(&buf, 32) < 0)
return NULL;
- if (strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
- tev->group, tev->event) < 0)
- goto error;
+ if (tev->ptwrite)
+ err = strbuf_addf(&buf, "ptw:%s/%s ", tev->group, tev->event);
+ else
+ err = strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
+ tev->group, tev->event);
if (tev->uprobes)
err = synthesize_uprobe_trace_def(tp, &buf);
@@ -2274,7 +2278,6 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
if (err >= 0)
ret = strbuf_detach(&buf, NULL);
-error:
strbuf_release(&buf);
return ret;
}
@@ -2996,6 +2999,7 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
ret = 0;
for (i = 0; i < ntevs; i++) {
tev = &tevs[i];
+ tev->ptwrite = pev->ptwrite;
up = tev->uprobes ? 1 : 0;
if (fd[up] == -1) { /* Open the kprobe/uprobe_events */
fd[up] = __open_probe_file_and_namelist(up,
@@ -3610,6 +3614,8 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)
/* Loop 1: convert all events */
for (i = 0; i < npevs; i++) {
+ int j;
+
/* Init kprobe blacklist if needed */
if (!pevs[i].uprobes)
kprobe_blacklist__init();
@@ -3618,6 +3624,8 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)
if (ret < 0)
return ret;
pevs[i].ntevs = ret;
+ for (j = 0; j < pevs[i].ntevs; j++)
+ pevs[i].tevs[j].ptwrite = pevs[i].ptwrite;
}
/* This just release blacklist only if allocated */
kprobe_blacklist__release();
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 71905ede0207..5fbed6c6a78a 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -60,6 +60,7 @@ struct probe_trace_event {
int nargs; /* Number of args */
int lang; /* Dwarf language code */
bool uprobes; /* uprobes only */
+ bool ptwrite; /* ptwrite uprobe (trap-free) */
struct probe_trace_arg *args; /* Arguments */
};
@@ -99,6 +100,7 @@ struct perf_probe_event {
int nargs; /* Number of arguments */
bool sdt; /* SDT/cached event flag */
bool uprobes; /* Uprobe event flag */
+ bool ptwrite; /* ptwrite uprobe (trap-free) */
char *target; /* Target binary */
struct perf_probe_arg *args; /* Arguments */
struct probe_trace_event *tevs;
--
2.54.0
next prev parent reply other threads:[~2026-08-31 15:07 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-31 15:04 [RFC] ptwrite uprobes Andi Kleen
2026-08-31 15:04 ` [RFC v1 01/19] uprobes: guard trace cleanup against error pointers Andi Kleen
2026-08-31 18:15 ` sashiko-bot
2026-09-01 0:49 ` Masami Hiramatsu
2026-08-31 15:04 ` [RFC v1 02/19] uprobes: Correctly reject anonymous VMAs for breakpoint installation Andi Kleen
2026-08-31 18:29 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 03/19] uprobes: Print warning for missing breakpoint install Andi Kleen
2026-08-31 18:42 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 04/19] ptwrite uprobes: Add infrastructure for ptwrite uprobes Andi Kleen
2026-08-31 18:55 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 05/19] ptwrite uprobes: Add minimal low level support for x86 Andi Kleen
2026-08-31 19:11 ` sashiko-bot
2026-09-02 16:35 ` Lorenzo Stoakes (ARM)
2026-08-31 15:04 ` [RFC v1 06/19] ptwrite uprobes: Add a sample module to exercise interface Andi Kleen
2026-08-31 19:19 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 07/19] ptwrite uprobes: Add support to tracing infrastructure Andi Kleen
2026-08-31 19:31 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 08/19] ptwrite uprobes / x86: Add a user fault notifier chain Andi Kleen
2026-08-31 19:38 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 09/19] ptwrite uprobes: Factor file-backed instruction reads Andi Kleen
2026-08-31 19:45 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 10/19] ptwrite uprobes: Minimal memory references and fault handling Andi Kleen
2026-08-31 19:59 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 11/19] ptwrite uprobes: Add multinop support Andi Kleen
2026-08-31 20:09 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 12/19] ptwrite uprobes: Add pacing to the probes Andi Kleen
2026-08-31 20:19 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 13/19] ptwrite uprobes: Support instruction puning Andi Kleen
2026-08-31 20:39 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 14/19] ptwrite uprobes: Use atomic patching for multinop sites Andi Kleen
2026-08-31 21:08 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 15/19] ptwrite uprobes: Add a tutorial and overview documentation Andi Kleen
2026-08-31 21:10 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 16/19] ptwrite uprobes / perf tools pt: Improve FUP error handling for ptwrite Andi Kleen
2026-08-31 21:19 ` sashiko-bot
2026-08-31 15:04 ` Andi Kleen [this message]
2026-08-31 21:32 ` [RFC v1 17/19] ptwrite uprobes / perf tools probe: Add support of ptwrite probes sashiko-bot
2026-08-31 15:04 ` [RFC v1 18/19] ptwrite uprobes / perf tools script: Add ptwrite uprobes decoder Andi Kleen
2026-08-31 21:39 ` sashiko-bot
2026-08-31 15:04 ` [RFC v1 19/19] ptwrite uprobes: Add self tests Andi Kleen
2026-08-31 21:47 ` sashiko-bot
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=20260831150651.1134594-18-ak@kernel.org \
--to=ak@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mhiramat@kernel.org \
--cc=oleg@redhat.com \
--cc=peterz@infradead.org \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
/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