|
@@ -7992,7 +7992,7 @@ static struct pmu perf_tracepoint = {
|
|
.read = perf_swevent_read,
|
|
.read = perf_swevent_read,
|
|
};
|
|
};
|
|
|
|
|
|
-#ifdef CONFIG_KPROBE_EVENTS
|
|
|
|
|
|
+#if defined(CONFIG_KPROBE_EVENTS) || defined(CONFIG_UPROBE_EVENTS)
|
|
/*
|
|
/*
|
|
* Flags in config, used by dynamic PMU kprobe and uprobe
|
|
* Flags in config, used by dynamic PMU kprobe and uprobe
|
|
* The flags should match following PMU_FORMAT_ATTR().
|
|
* The flags should match following PMU_FORMAT_ATTR().
|
|
@@ -8020,7 +8020,9 @@ static const struct attribute_group *probe_attr_groups[] = {
|
|
&probe_format_group,
|
|
&probe_format_group,
|
|
NULL,
|
|
NULL,
|
|
};
|
|
};
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
+#ifdef CONFIG_KPROBE_EVENTS
|
|
static int perf_kprobe_event_init(struct perf_event *event);
|
|
static int perf_kprobe_event_init(struct perf_event *event);
|
|
static struct pmu perf_kprobe = {
|
|
static struct pmu perf_kprobe = {
|
|
.task_ctx_nr = perf_sw_context,
|
|
.task_ctx_nr = perf_sw_context,
|
|
@@ -8057,12 +8059,52 @@ static int perf_kprobe_event_init(struct perf_event *event)
|
|
}
|
|
}
|
|
#endif /* CONFIG_KPROBE_EVENTS */
|
|
#endif /* CONFIG_KPROBE_EVENTS */
|
|
|
|
|
|
|
|
+#ifdef CONFIG_UPROBE_EVENTS
|
|
|
|
+static int perf_uprobe_event_init(struct perf_event *event);
|
|
|
|
+static struct pmu perf_uprobe = {
|
|
|
|
+ .task_ctx_nr = perf_sw_context,
|
|
|
|
+ .event_init = perf_uprobe_event_init,
|
|
|
|
+ .add = perf_trace_add,
|
|
|
|
+ .del = perf_trace_del,
|
|
|
|
+ .start = perf_swevent_start,
|
|
|
|
+ .stop = perf_swevent_stop,
|
|
|
|
+ .read = perf_swevent_read,
|
|
|
|
+ .attr_groups = probe_attr_groups,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static int perf_uprobe_event_init(struct perf_event *event)
|
|
|
|
+{
|
|
|
|
+ int err;
|
|
|
|
+ bool is_retprobe;
|
|
|
|
+
|
|
|
|
+ if (event->attr.type != perf_uprobe.type)
|
|
|
|
+ return -ENOENT;
|
|
|
|
+ /*
|
|
|
|
+ * no branch sampling for probe events
|
|
|
|
+ */
|
|
|
|
+ if (has_branch_stack(event))
|
|
|
|
+ return -EOPNOTSUPP;
|
|
|
|
+
|
|
|
|
+ is_retprobe = event->attr.config & PERF_PROBE_CONFIG_IS_RETPROBE;
|
|
|
|
+ err = perf_uprobe_init(event, is_retprobe);
|
|
|
|
+ if (err)
|
|
|
|
+ return err;
|
|
|
|
+
|
|
|
|
+ event->destroy = perf_uprobe_destroy;
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+#endif /* CONFIG_UPROBE_EVENTS */
|
|
|
|
+
|
|
static inline void perf_tp_register(void)
|
|
static inline void perf_tp_register(void)
|
|
{
|
|
{
|
|
perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT);
|
|
perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT);
|
|
#ifdef CONFIG_KPROBE_EVENTS
|
|
#ifdef CONFIG_KPROBE_EVENTS
|
|
perf_pmu_register(&perf_kprobe, "kprobe", -1);
|
|
perf_pmu_register(&perf_kprobe, "kprobe", -1);
|
|
#endif
|
|
#endif
|
|
|
|
+#ifdef CONFIG_UPROBE_EVENTS
|
|
|
|
+ perf_pmu_register(&perf_uprobe, "uprobe", -1);
|
|
|
|
+#endif
|
|
}
|
|
}
|
|
|
|
|
|
static void perf_event_free_filter(struct perf_event *event)
|
|
static void perf_event_free_filter(struct perf_event *event)
|
|
@@ -8150,6 +8192,10 @@ static inline bool perf_event_is_tracing(struct perf_event *event)
|
|
#ifdef CONFIG_KPROBE_EVENTS
|
|
#ifdef CONFIG_KPROBE_EVENTS
|
|
if (event->pmu == &perf_kprobe)
|
|
if (event->pmu == &perf_kprobe)
|
|
return true;
|
|
return true;
|
|
|
|
+#endif
|
|
|
|
+#ifdef CONFIG_UPROBE_EVENTS
|
|
|
|
+ if (event->pmu == &perf_uprobe)
|
|
|
|
+ return true;
|
|
#endif
|
|
#endif
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|