mirror of
https://github.com/torvalds/linux
synced 2024-09-06 18:01:05 +00:00
bpf: Add missed value to kprobe perf link info
Add missed value to kprobe attached through perf link info to hold the stats of missed kprobe handler execution. The kprobe's missed counter gets incremented when kprobe handler is not executed due to another kprobe running on the same cpu. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20230920213145.1941596-4-jolsa@kernel.org
This commit is contained in:
parent
e2b2cd592a
commit
3acf8ace68
|
@ -761,7 +761,8 @@ struct bpf_raw_event_map *bpf_get_raw_tracepoint(const char *name);
|
|||
void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp);
|
||||
int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
|
||||
u32 *fd_type, const char **buf,
|
||||
u64 *probe_offset, u64 *probe_addr);
|
||||
u64 *probe_offset, u64 *probe_addr,
|
||||
unsigned long *missed);
|
||||
int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
|
||||
int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
|
||||
#else
|
||||
|
@ -801,7 +802,7 @@ static inline void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp)
|
|||
static inline int bpf_get_perf_event_info(const struct perf_event *event,
|
||||
u32 *prog_id, u32 *fd_type,
|
||||
const char **buf, u64 *probe_offset,
|
||||
u64 *probe_addr)
|
||||
u64 *probe_addr, unsigned long *missed)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -877,6 +878,7 @@ extern void perf_kprobe_destroy(struct perf_event *event);
|
|||
extern int bpf_get_kprobe_info(const struct perf_event *event,
|
||||
u32 *fd_type, const char **symbol,
|
||||
u64 *probe_offset, u64 *probe_addr,
|
||||
unsigned long *missed,
|
||||
bool perf_type_tracepoint);
|
||||
#endif
|
||||
#ifdef CONFIG_UPROBE_EVENTS
|
||||
|
|
|
@ -6548,6 +6548,7 @@ struct bpf_link_info {
|
|||
__u32 name_len;
|
||||
__u32 offset; /* offset from func_name */
|
||||
__u64 addr;
|
||||
__u64 missed;
|
||||
} kprobe; /* BPF_PERF_EVENT_KPROBE, BPF_PERF_EVENT_KRETPROBE */
|
||||
struct {
|
||||
__aligned_u64 tp_name; /* in/out */
|
||||
|
|
|
@ -3374,7 +3374,7 @@ static void bpf_perf_link_dealloc(struct bpf_link *link)
|
|||
static int bpf_perf_link_fill_common(const struct perf_event *event,
|
||||
char __user *uname, u32 ulen,
|
||||
u64 *probe_offset, u64 *probe_addr,
|
||||
u32 *fd_type)
|
||||
u32 *fd_type, unsigned long *missed)
|
||||
{
|
||||
const char *buf;
|
||||
u32 prog_id;
|
||||
|
@ -3385,7 +3385,7 @@ static int bpf_perf_link_fill_common(const struct perf_event *event,
|
|||
return -EINVAL;
|
||||
|
||||
err = bpf_get_perf_event_info(event, &prog_id, fd_type, &buf,
|
||||
probe_offset, probe_addr);
|
||||
probe_offset, probe_addr, missed);
|
||||
if (err)
|
||||
return err;
|
||||
if (!uname)
|
||||
|
@ -3408,6 +3408,7 @@ static int bpf_perf_link_fill_common(const struct perf_event *event,
|
|||
static int bpf_perf_link_fill_kprobe(const struct perf_event *event,
|
||||
struct bpf_link_info *info)
|
||||
{
|
||||
unsigned long missed;
|
||||
char __user *uname;
|
||||
u64 addr, offset;
|
||||
u32 ulen, type;
|
||||
|
@ -3416,7 +3417,7 @@ static int bpf_perf_link_fill_kprobe(const struct perf_event *event,
|
|||
uname = u64_to_user_ptr(info->perf_event.kprobe.func_name);
|
||||
ulen = info->perf_event.kprobe.name_len;
|
||||
err = bpf_perf_link_fill_common(event, uname, ulen, &offset, &addr,
|
||||
&type);
|
||||
&type, &missed);
|
||||
if (err)
|
||||
return err;
|
||||
if (type == BPF_FD_TYPE_KRETPROBE)
|
||||
|
@ -3425,6 +3426,7 @@ static int bpf_perf_link_fill_kprobe(const struct perf_event *event,
|
|||
info->perf_event.type = BPF_PERF_EVENT_KPROBE;
|
||||
|
||||
info->perf_event.kprobe.offset = offset;
|
||||
info->perf_event.kprobe.missed = missed;
|
||||
if (!kallsyms_show_value(current_cred()))
|
||||
addr = 0;
|
||||
info->perf_event.kprobe.addr = addr;
|
||||
|
@ -3444,7 +3446,7 @@ static int bpf_perf_link_fill_uprobe(const struct perf_event *event,
|
|||
uname = u64_to_user_ptr(info->perf_event.uprobe.file_name);
|
||||
ulen = info->perf_event.uprobe.name_len;
|
||||
err = bpf_perf_link_fill_common(event, uname, ulen, &offset, &addr,
|
||||
&type);
|
||||
&type, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -3480,7 +3482,7 @@ static int bpf_perf_link_fill_tracepoint(const struct perf_event *event,
|
|||
uname = u64_to_user_ptr(info->perf_event.tracepoint.tp_name);
|
||||
ulen = info->perf_event.tracepoint.name_len;
|
||||
info->perf_event.type = BPF_PERF_EVENT_TRACEPOINT;
|
||||
return bpf_perf_link_fill_common(event, uname, ulen, NULL, NULL, NULL);
|
||||
return bpf_perf_link_fill_common(event, uname, ulen, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
static int bpf_perf_link_fill_perf_event(const struct perf_event *event,
|
||||
|
@ -4813,7 +4815,7 @@ static int bpf_task_fd_query(const union bpf_attr *attr,
|
|||
|
||||
err = bpf_get_perf_event_info(event, &prog_id, &fd_type,
|
||||
&buf, &probe_offset,
|
||||
&probe_addr);
|
||||
&probe_addr, NULL);
|
||||
if (!err)
|
||||
err = bpf_task_fd_query_copy(attr, uattr, prog_id,
|
||||
fd_type, buf,
|
||||
|
|
|
@ -2384,7 +2384,8 @@ int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
|
|||
|
||||
int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
|
||||
u32 *fd_type, const char **buf,
|
||||
u64 *probe_offset, u64 *probe_addr)
|
||||
u64 *probe_offset, u64 *probe_addr,
|
||||
unsigned long *missed)
|
||||
{
|
||||
bool is_tracepoint, is_syscall_tp;
|
||||
struct bpf_prog *prog;
|
||||
|
@ -2419,7 +2420,7 @@ int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
|
|||
#ifdef CONFIG_KPROBE_EVENTS
|
||||
if (flags & TRACE_EVENT_FL_KPROBE)
|
||||
err = bpf_get_kprobe_info(event, fd_type, buf,
|
||||
probe_offset, probe_addr,
|
||||
probe_offset, probe_addr, missed,
|
||||
event->attr.type == PERF_TYPE_TRACEPOINT);
|
||||
#endif
|
||||
#ifdef CONFIG_UPROBE_EVENTS
|
||||
|
|
|
@ -1189,6 +1189,12 @@ static const struct file_operations kprobe_events_ops = {
|
|||
.write = probes_write,
|
||||
};
|
||||
|
||||
static unsigned long trace_kprobe_missed(struct trace_kprobe *tk)
|
||||
{
|
||||
return trace_kprobe_is_return(tk) ?
|
||||
tk->rp.kp.nmissed + tk->rp.nmissed : tk->rp.kp.nmissed;
|
||||
}
|
||||
|
||||
/* Probes profiling interfaces */
|
||||
static int probes_profile_seq_show(struct seq_file *m, void *v)
|
||||
{
|
||||
|
@ -1200,8 +1206,7 @@ static int probes_profile_seq_show(struct seq_file *m, void *v)
|
|||
return 0;
|
||||
|
||||
tk = to_trace_kprobe(ev);
|
||||
nmissed = trace_kprobe_is_return(tk) ?
|
||||
tk->rp.kp.nmissed + tk->rp.nmissed : tk->rp.kp.nmissed;
|
||||
nmissed = trace_kprobe_missed(tk);
|
||||
seq_printf(m, " %-44s %15lu %15lu\n",
|
||||
trace_probe_name(&tk->tp),
|
||||
trace_kprobe_nhit(tk),
|
||||
|
@ -1547,7 +1552,8 @@ NOKPROBE_SYMBOL(kretprobe_perf_func);
|
|||
|
||||
int bpf_get_kprobe_info(const struct perf_event *event, u32 *fd_type,
|
||||
const char **symbol, u64 *probe_offset,
|
||||
u64 *probe_addr, bool perf_type_tracepoint)
|
||||
u64 *probe_addr, unsigned long *missed,
|
||||
bool perf_type_tracepoint)
|
||||
{
|
||||
const char *pevent = trace_event_name(event->tp_event);
|
||||
const char *group = event->tp_event->class->system;
|
||||
|
@ -1566,6 +1572,8 @@ int bpf_get_kprobe_info(const struct perf_event *event, u32 *fd_type,
|
|||
*probe_addr = kallsyms_show_value(current_cred()) ?
|
||||
(unsigned long)tk->rp.kp.addr : 0;
|
||||
*symbol = tk->symbol;
|
||||
if (missed)
|
||||
*missed = trace_kprobe_missed(tk);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PERF_EVENTS */
|
||||
|
|
|
@ -6548,6 +6548,7 @@ struct bpf_link_info {
|
|||
__u32 name_len;
|
||||
__u32 offset; /* offset from func_name */
|
||||
__u64 addr;
|
||||
__u64 missed;
|
||||
} kprobe; /* BPF_PERF_EVENT_KPROBE, BPF_PERF_EVENT_KRETPROBE */
|
||||
struct {
|
||||
__aligned_u64 tp_name; /* in/out */
|
||||
|
|
Loading…
Reference in a new issue