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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.