Skip to content

Commit a6ca88b

Browse files
liu-song-6rostedt
authored andcommitted
trace_uprobe: support reference counter in fd-based uprobe
This patch enables uprobes with reference counter in fd-based uprobe. Highest 32 bits of perf_event_attr.config is used to stored offset of the reference count (semaphore). Format information in /sys/bus/event_source/devices/uprobe/format/ is updated to reflect this new feature. Link: http://lkml.kernel.org/r/20181002053636.1896903-1-songliubraving@fb.com Cc: Oleg Nesterov <oleg@redhat.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-and-tested-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com> Signed-off-by: Song Liu <songliubraving@fb.com> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
1 parent 5a5e3d3 commit a6ca88b

File tree

5 files changed

+50
-16
lines changed

5 files changed

+50
-16
lines changed

include/linux/trace_events.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,8 @@ extern int bpf_get_kprobe_info(const struct perf_event *event,
575575
bool perf_type_tracepoint);
576576
#endif
577577
#ifdef CONFIG_UPROBE_EVENTS
578-
extern int perf_uprobe_init(struct perf_event *event, bool is_retprobe);
578+
extern int perf_uprobe_init(struct perf_event *event,
579+
unsigned long ref_ctr_offset, bool is_retprobe);
579580
extern void perf_uprobe_destroy(struct perf_event *event);
580581
extern int bpf_get_uprobe_info(const struct perf_event *event,
581582
u32 *fd_type, const char **filename,

kernel/events/core.c

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8368,30 +8368,39 @@ static struct pmu perf_tracepoint = {
83688368
*
83698369
* PERF_PROBE_CONFIG_IS_RETPROBE if set, create kretprobe/uretprobe
83708370
* if not set, create kprobe/uprobe
8371+
*
8372+
* The following values specify a reference counter (or semaphore in the
8373+
* terminology of tools like dtrace, systemtap, etc.) Userspace Statically
8374+
* Defined Tracepoints (USDT). Currently, we use 40 bit for the offset.
8375+
*
8376+
* PERF_UPROBE_REF_CTR_OFFSET_BITS # of bits in config as th offset
8377+
* PERF_UPROBE_REF_CTR_OFFSET_SHIFT # of bits to shift left
83718378
*/
83728379
enum perf_probe_config {
83738380
PERF_PROBE_CONFIG_IS_RETPROBE = 1U << 0, /* [k,u]retprobe */
8381+
PERF_UPROBE_REF_CTR_OFFSET_BITS = 32,
8382+
PERF_UPROBE_REF_CTR_OFFSET_SHIFT = 64 - PERF_UPROBE_REF_CTR_OFFSET_BITS,
83748383
};
83758384

83768385
PMU_FORMAT_ATTR(retprobe, "config:0");
8386+
#endif
83778387

8378-
static struct attribute *probe_attrs[] = {
8388+
#ifdef CONFIG_KPROBE_EVENTS
8389+
static struct attribute *kprobe_attrs[] = {
83798390
&format_attr_retprobe.attr,
83808391
NULL,
83818392
};
83828393

8383-
static struct attribute_group probe_format_group = {
8394+
static struct attribute_group kprobe_format_group = {
83848395
.name = "format",
8385-
.attrs = probe_attrs,
8396+
.attrs = kprobe_attrs,
83868397
};
83878398

8388-
static const struct attribute_group *probe_attr_groups[] = {
8389-
&probe_format_group,
8399+
static const struct attribute_group *kprobe_attr_groups[] = {
8400+
&kprobe_format_group,
83908401
NULL,
83918402
};
8392-
#endif
83938403

8394-
#ifdef CONFIG_KPROBE_EVENTS
83958404
static int perf_kprobe_event_init(struct perf_event *event);
83968405
static struct pmu perf_kprobe = {
83978406
.task_ctx_nr = perf_sw_context,
@@ -8401,7 +8410,7 @@ static struct pmu perf_kprobe = {
84018410
.start = perf_swevent_start,
84028411
.stop = perf_swevent_stop,
84038412
.read = perf_swevent_read,
8404-
.attr_groups = probe_attr_groups,
8413+
.attr_groups = kprobe_attr_groups,
84058414
};
84068415

84078416
static int perf_kprobe_event_init(struct perf_event *event)
@@ -8433,6 +8442,24 @@ static int perf_kprobe_event_init(struct perf_event *event)
84338442
#endif /* CONFIG_KPROBE_EVENTS */
84348443

84358444
#ifdef CONFIG_UPROBE_EVENTS
8445+
PMU_FORMAT_ATTR(ref_ctr_offset, "config:32-63");
8446+
8447+
static struct attribute *uprobe_attrs[] = {
8448+
&format_attr_retprobe.attr,
8449+
&format_attr_ref_ctr_offset.attr,
8450+
NULL,
8451+
};
8452+
8453+
static struct attribute_group uprobe_format_group = {
8454+
.name = "format",
8455+
.attrs = uprobe_attrs,
8456+
};
8457+
8458+
static const struct attribute_group *uprobe_attr_groups[] = {
8459+
&uprobe_format_group,
8460+
NULL,
8461+
};
8462+
84368463
static int perf_uprobe_event_init(struct perf_event *event);
84378464
static struct pmu perf_uprobe = {
84388465
.task_ctx_nr = perf_sw_context,
@@ -8442,12 +8469,13 @@ static struct pmu perf_uprobe = {
84428469
.start = perf_swevent_start,
84438470
.stop = perf_swevent_stop,
84448471
.read = perf_swevent_read,
8445-
.attr_groups = probe_attr_groups,
8472+
.attr_groups = uprobe_attr_groups,
84468473
};
84478474

84488475
static int perf_uprobe_event_init(struct perf_event *event)
84498476
{
84508477
int err;
8478+
unsigned long ref_ctr_offset;
84518479
bool is_retprobe;
84528480

84538481
if (event->attr.type != perf_uprobe.type)
@@ -8463,7 +8491,8 @@ static int perf_uprobe_event_init(struct perf_event *event)
84638491
return -EOPNOTSUPP;
84648492

84658493
is_retprobe = event->attr.config & PERF_PROBE_CONFIG_IS_RETPROBE;
8466-
err = perf_uprobe_init(event, is_retprobe);
8494+
ref_ctr_offset = event->attr.config >> PERF_UPROBE_REF_CTR_OFFSET_SHIFT;
8495+
err = perf_uprobe_init(event, ref_ctr_offset, is_retprobe);
84678496
if (err)
84688497
return err;
84698498

kernel/trace/trace_event_perf.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ void perf_kprobe_destroy(struct perf_event *p_event)
290290
#endif /* CONFIG_KPROBE_EVENTS */
291291

292292
#ifdef CONFIG_UPROBE_EVENTS
293-
int perf_uprobe_init(struct perf_event *p_event, bool is_retprobe)
293+
int perf_uprobe_init(struct perf_event *p_event,
294+
unsigned long ref_ctr_offset, bool is_retprobe)
294295
{
295296
int ret;
296297
char *path = NULL;
@@ -312,8 +313,8 @@ int perf_uprobe_init(struct perf_event *p_event, bool is_retprobe)
312313
goto out;
313314
}
314315

315-
tp_event = create_local_trace_uprobe(
316-
path, p_event->attr.probe_offset, is_retprobe);
316+
tp_event = create_local_trace_uprobe(path, p_event->attr.probe_offset,
317+
ref_ctr_offset, is_retprobe);
317318
if (IS_ERR(tp_event)) {
318319
ret = PTR_ERR(tp_event);
319320
goto out;

kernel/trace/trace_probe.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ create_local_trace_kprobe(char *func, void *addr, unsigned long offs,
412412
extern void destroy_local_trace_kprobe(struct trace_event_call *event_call);
413413

414414
extern struct trace_event_call *
415-
create_local_trace_uprobe(char *name, unsigned long offs, bool is_return);
415+
create_local_trace_uprobe(char *name, unsigned long offs,
416+
unsigned long ref_ctr_offset, bool is_return);
416417
extern void destroy_local_trace_uprobe(struct trace_event_call *event_call);
417418
#endif

kernel/trace/trace_uprobe.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,8 @@ static int unregister_uprobe_event(struct trace_uprobe *tu)
14051405

14061406
#ifdef CONFIG_PERF_EVENTS
14071407
struct trace_event_call *
1408-
create_local_trace_uprobe(char *name, unsigned long offs, bool is_return)
1408+
create_local_trace_uprobe(char *name, unsigned long offs,
1409+
unsigned long ref_ctr_offset, bool is_return)
14091410
{
14101411
struct trace_uprobe *tu;
14111412
struct path path;
@@ -1437,6 +1438,7 @@ create_local_trace_uprobe(char *name, unsigned long offs, bool is_return)
14371438

14381439
tu->offset = offs;
14391440
tu->path = path;
1441+
tu->ref_ctr_offset = ref_ctr_offset;
14401442
tu->filename = kstrdup(name, GFP_KERNEL);
14411443
init_trace_event_call(tu, &tu->tp.call);
14421444

0 commit comments

Comments
 (0)