[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250902143504.1224726-4-jolsa@kernel.org>
Date: Tue, 2 Sep 2025 16:34:56 +0200
From: Jiri Olsa <jolsa@...nel.org>
To: Oleg Nesterov <oleg@...hat.com>,
Masami Hiramatsu <mhiramat@...nel.org>,
Peter Zijlstra <peterz@...radead.org>,
Andrii Nakryiko <andrii@...nel.org>
Cc: bpf@...r.kernel.org,
linux-kernel@...r.kernel.org,
linux-trace-kernel@...r.kernel.org,
x86@...nel.org,
Song Liu <songliubraving@...com>,
Yonghong Song <yhs@...com>,
John Fastabend <john.fastabend@...il.com>,
Hao Luo <haoluo@...gle.com>,
Steven Rostedt <rostedt@...dmis.org>,
Ingo Molnar <mingo@...nel.org>
Subject: [PATCH perf/core 03/11] perf: Add support to attach standard unique uprobe
Adding support to attach unique probe through perf uprobe pmu.
Adding new 'unique' format attribute that allows to pass the
request to create unique uprobe the uprobe consumer.
Signed-off-by: Jiri Olsa <jolsa@...nel.org>
---
include/linux/trace_events.h | 2 +-
kernel/events/core.c | 8 ++++++--
kernel/trace/trace_event_perf.c | 4 ++--
kernel/trace/trace_probe.h | 2 +-
kernel/trace/trace_uprobe.c | 9 +++++----
5 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 04307a19cde3..1d35727fda27 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -877,7 +877,7 @@ extern int bpf_get_kprobe_info(const struct perf_event *event,
#endif
#ifdef CONFIG_UPROBE_EVENTS
extern int perf_uprobe_init(struct perf_event *event,
- unsigned long ref_ctr_offset, bool is_retprobe);
+ unsigned long ref_ctr_offset, bool is_retprobe, bool is_unique);
extern void perf_uprobe_destroy(struct perf_event *event);
extern int bpf_get_uprobe_info(const struct perf_event *event,
u32 *fd_type, const char **filename,
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 28de3baff792..10a9341c638f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -11046,11 +11046,13 @@ EXPORT_SYMBOL_GPL(perf_tp_event);
*/
enum perf_probe_config {
PERF_PROBE_CONFIG_IS_RETPROBE = 1U << 0, /* [k,u]retprobe */
+ PERF_PROBE_CONFIG_IS_UNIQUE = 1U << 1, /* unique uprobe */
PERF_UPROBE_REF_CTR_OFFSET_BITS = 32,
PERF_UPROBE_REF_CTR_OFFSET_SHIFT = 64 - PERF_UPROBE_REF_CTR_OFFSET_BITS,
};
PMU_FORMAT_ATTR(retprobe, "config:0");
+PMU_FORMAT_ATTR(unique, "config:1");
#endif
#ifdef CONFIG_KPROBE_EVENTS
@@ -11114,6 +11116,7 @@ PMU_FORMAT_ATTR(ref_ctr_offset, "config:32-63");
static struct attribute *uprobe_attrs[] = {
&format_attr_retprobe.attr,
+ &format_attr_unique.attr,
&format_attr_ref_ctr_offset.attr,
NULL,
};
@@ -11144,7 +11147,7 @@ static int perf_uprobe_event_init(struct perf_event *event)
{
int err;
unsigned long ref_ctr_offset;
- bool is_retprobe;
+ bool is_retprobe, is_unique;
if (event->attr.type != perf_uprobe.type)
return -ENOENT;
@@ -11159,8 +11162,9 @@ static int perf_uprobe_event_init(struct perf_event *event)
return -EOPNOTSUPP;
is_retprobe = event->attr.config & PERF_PROBE_CONFIG_IS_RETPROBE;
+ is_unique = event->attr.config & PERF_PROBE_CONFIG_IS_UNIQUE;
ref_ctr_offset = event->attr.config >> PERF_UPROBE_REF_CTR_OFFSET_SHIFT;
- err = perf_uprobe_init(event, ref_ctr_offset, is_retprobe);
+ err = perf_uprobe_init(event, ref_ctr_offset, is_retprobe, is_unique);
if (err)
return err;
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c
index a6bb7577e8c5..b4383ab21d88 100644
--- a/kernel/trace/trace_event_perf.c
+++ b/kernel/trace/trace_event_perf.c
@@ -296,7 +296,7 @@ void perf_kprobe_destroy(struct perf_event *p_event)
#ifdef CONFIG_UPROBE_EVENTS
int perf_uprobe_init(struct perf_event *p_event,
- unsigned long ref_ctr_offset, bool is_retprobe)
+ unsigned long ref_ctr_offset, bool is_retprobe, bool is_unique)
{
int ret;
char *path = NULL;
@@ -317,7 +317,7 @@ int perf_uprobe_init(struct perf_event *p_event,
}
tp_event = create_local_trace_uprobe(path, p_event->attr.probe_offset,
- ref_ctr_offset, is_retprobe);
+ ref_ctr_offset, is_retprobe, is_unique);
if (IS_ERR(tp_event)) {
ret = PTR_ERR(tp_event);
goto out;
diff --git a/kernel/trace/trace_probe.h b/kernel/trace/trace_probe.h
index 842383fbc03b..92870b98b296 100644
--- a/kernel/trace/trace_probe.h
+++ b/kernel/trace/trace_probe.h
@@ -469,7 +469,7 @@ extern void destroy_local_trace_kprobe(struct trace_event_call *event_call);
extern struct trace_event_call *
create_local_trace_uprobe(char *name, unsigned long offs,
- unsigned long ref_ctr_offset, bool is_return);
+ unsigned long ref_ctr_offset, bool is_return, bool is_unique);
extern void destroy_local_trace_uprobe(struct trace_event_call *event_call);
#endif
extern int traceprobe_define_arg_fields(struct trace_event_call *event_call,
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 8b0bcc0d8f41..4ecb6083f949 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -333,7 +333,7 @@ trace_uprobe_primary_from_call(struct trace_event_call *call)
* Allocate new trace_uprobe and initialize it (including uprobes).
*/
static struct trace_uprobe *
-alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
+alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret, bool is_unique)
{
struct trace_uprobe *tu;
int ret;
@@ -356,6 +356,7 @@ alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
tu->consumer.handler = uprobe_dispatcher;
if (is_ret)
tu->consumer.ret_handler = uretprobe_dispatcher;
+ tu->consumer.is_unique = is_unique;
init_trace_uprobe_filter(tu->tp.event->filter);
return tu;
@@ -688,7 +689,7 @@ static int __trace_uprobe_create(int argc, const char **argv)
argc -= 2;
argv += 2;
- tu = alloc_trace_uprobe(group, event, argc, is_return);
+ tu = alloc_trace_uprobe(group, event, argc, is_return, false /* unique */);
if (IS_ERR(tu)) {
ret = PTR_ERR(tu);
/* This must return -ENOMEM otherwise there is a bug */
@@ -1636,7 +1637,7 @@ static int unregister_uprobe_event(struct trace_uprobe *tu)
#ifdef CONFIG_PERF_EVENTS
struct trace_event_call *
create_local_trace_uprobe(char *name, unsigned long offs,
- unsigned long ref_ctr_offset, bool is_return)
+ unsigned long ref_ctr_offset, bool is_return, bool is_unique)
{
enum probe_print_type ptype;
struct trace_uprobe *tu;
@@ -1658,7 +1659,7 @@ create_local_trace_uprobe(char *name, unsigned long offs,
* duplicated name "DUMMY_EVENT" here.
*/
tu = alloc_trace_uprobe(UPROBE_EVENT_SYSTEM, "DUMMY_EVENT", 0,
- is_return);
+ is_return, is_unique);
if (IS_ERR(tu)) {
pr_info("Failed to allocate trace_uprobe.(%d)\n",
--
2.51.0
Powered by blists - more mailing lists