Linux Perf Users
 help / color / mirror / Atom feed
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", &params->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


  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