Skip to content

Commit 5a5c11e

Browse files
author
Alexei Starovoitov
committed
Merge branch 'bpf: Add kprobe multi link'
Jiri Olsa says: ==================== hi, this patchset adds new link type BPF_TRACE_KPROBE_MULTI that attaches kprobe program through fprobe API [1] instroduced by Masami. The fprobe API allows to attach probe on multiple functions at once very fast, because it works on top of ftrace. On the other hand this limits the probe point to the function entry or return. With bpftrace support I see following attach speed: # perf stat --null -r 5 ./src/bpftrace -e 'kprobe:x* { } i:ms:1 { exit(); } ' Attaching 2 probes... Attaching 3342 functions ... 1.4960 +- 0.0285 seconds time elapsed ( +- 1.91% ) v3 changes: - based on latest fprobe post from Masami [2] - add acks - add extra comment to kprobe_multi_link_handler wrt entry ip setup [Masami] - keep swap_words_64 static and swap values directly in bpf_kprobe_multi_cookie_swap [Andrii] - rearrange locking/migrate setup in kprobe_multi_link_prog_run [Andrii] - move uapi fields [Andrii] - add bpf_program__attach_kprobe_multi_opts function [Andrii] - many small test changes [Andrii] - added tests for bpf_program__attach_kprobe_multi_opts - make kallsyms_lookup_name check for empty string [Andrii] v2 changes: - based on latest fprobe changes [1] - renaming the uapi interface to kprobe multi - adding support for sort_r to pass user pointer for swap functions and using that in cookie support to keep just single functions array - moving new link to kernel/trace/bpf_trace.c file - using single fprobe callback function for entry and exit - using kvzalloc, libbpf_ensure_mem functions - adding new k[ret]probe.multi sections instead of using current kprobe - used glob_match from test_progs.c, added '?' matching - move bpf_get_func_ip verifier inline change to seprate change - couple of other minor fixes Also available at: https://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf.git bpf/kprobe_multi thanks, jirka [1] https://lore.kernel.org/bpf/164458044634.586276.3261555265565111183.stgit@devnote2/ [2] https://lore.kernel.org/bpf/164735281449.1084943.12438881786173547153.stgit@devnote2/ ==================== Signed-off-by: Alexei Starovoitov <[email protected]>
2 parents 245d949 + 318c812 commit 5a5c11e

File tree

21 files changed

+1302
-44
lines changed

21 files changed

+1302
-44
lines changed

include/linux/bpf_types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,4 @@ BPF_LINK_TYPE(BPF_LINK_TYPE_XDP, xdp)
140140
#ifdef CONFIG_PERF_EVENTS
141141
BPF_LINK_TYPE(BPF_LINK_TYPE_PERF_EVENT, perf)
142142
#endif
143+
BPF_LINK_TYPE(BPF_LINK_TYPE_KPROBE_MULTI, kprobe_multi)

include/linux/sort.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
void sort_r(void *base, size_t num, size_t size,
88
cmp_r_func_t cmp_func,
9-
swap_func_t swap_func,
9+
swap_r_func_t swap_func,
1010
const void *priv);
1111

1212
void sort(void *base, size_t num, size_t size,

include/linux/trace_events.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ struct array_buffer;
1515
struct tracer;
1616
struct dentry;
1717
struct bpf_prog;
18+
union bpf_attr;
1819

1920
const char *trace_print_flags_seq(struct trace_seq *p, const char *delim,
2021
unsigned long flags,
@@ -738,6 +739,7 @@ void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp);
738739
int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
739740
u32 *fd_type, const char **buf,
740741
u64 *probe_offset, u64 *probe_addr);
742+
int bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
741743
#else
742744
static inline unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx)
743745
{
@@ -779,6 +781,11 @@ static inline int bpf_get_perf_event_info(const struct perf_event *event,
779781
{
780782
return -EOPNOTSUPP;
781783
}
784+
static inline int
785+
bpf_kprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
786+
{
787+
return -EOPNOTSUPP;
788+
}
782789
#endif
783790

784791
enum {

include/linux/types.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ struct callback_head {
226226
typedef void (*rcu_callback_t)(struct rcu_head *head);
227227
typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func);
228228

229+
typedef void (*swap_r_func_t)(void *a, void *b, int size, const void *priv);
229230
typedef void (*swap_func_t)(void *a, void *b, int size);
230231

231232
typedef int (*cmp_r_func_t)(const void *a, const void *b, const void *priv);

include/uapi/linux/bpf.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,7 @@ enum bpf_attach_type {
997997
BPF_SK_REUSEPORT_SELECT,
998998
BPF_SK_REUSEPORT_SELECT_OR_MIGRATE,
999999
BPF_PERF_EVENT,
1000+
BPF_TRACE_KPROBE_MULTI,
10001001
__MAX_BPF_ATTACH_TYPE
10011002
};
10021003

@@ -1011,6 +1012,7 @@ enum bpf_link_type {
10111012
BPF_LINK_TYPE_NETNS = 5,
10121013
BPF_LINK_TYPE_XDP = 6,
10131014
BPF_LINK_TYPE_PERF_EVENT = 7,
1015+
BPF_LINK_TYPE_KPROBE_MULTI = 8,
10141016

10151017
MAX_BPF_LINK_TYPE,
10161018
};
@@ -1118,6 +1120,11 @@ enum bpf_link_type {
11181120
*/
11191121
#define BPF_F_XDP_HAS_FRAGS (1U << 5)
11201122

1123+
/* link_create.kprobe_multi.flags used in LINK_CREATE command for
1124+
* BPF_TRACE_KPROBE_MULTI attach type to create return probe.
1125+
*/
1126+
#define BPF_F_KPROBE_MULTI_RETURN (1U << 0)
1127+
11211128
/* When BPF ldimm64's insn[0].src_reg != 0 then this can have
11221129
* the following extensions:
11231130
*
@@ -1475,6 +1482,13 @@ union bpf_attr {
14751482
*/
14761483
__u64 bpf_cookie;
14771484
} perf_event;
1485+
struct {
1486+
__u32 flags;
1487+
__u32 cnt;
1488+
__aligned_u64 syms;
1489+
__aligned_u64 addrs;
1490+
__aligned_u64 cookies;
1491+
} kprobe_multi;
14781492
};
14791493
} link_create;
14801494

kernel/bpf/syscall.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/bpf-netns.h>
3333
#include <linux/rcupdate_trace.h>
3434
#include <linux/memcontrol.h>
35+
#include <linux/trace_events.h>
3536

3637
#define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PERF_EVENT_ARRAY || \
3738
(map)->map_type == BPF_MAP_TYPE_CGROUP_ARRAY || \
@@ -3022,6 +3023,11 @@ static int bpf_perf_link_attach(const union bpf_attr *attr, struct bpf_prog *pro
30223023
fput(perf_file);
30233024
return err;
30243025
}
3026+
#else
3027+
static int bpf_perf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
3028+
{
3029+
return -EOPNOTSUPP;
3030+
}
30253031
#endif /* CONFIG_PERF_EVENTS */
30263032

30273033
#define BPF_RAW_TRACEPOINT_OPEN_LAST_FIELD raw_tracepoint.prog_fd
@@ -4255,7 +4261,7 @@ static int tracing_bpf_link_attach(const union bpf_attr *attr, bpfptr_t uattr,
42554261
return -EINVAL;
42564262
}
42574263

4258-
#define BPF_LINK_CREATE_LAST_FIELD link_create.iter_info_len
4264+
#define BPF_LINK_CREATE_LAST_FIELD link_create.kprobe_multi.cookies
42594265
static int link_create(union bpf_attr *attr, bpfptr_t uattr)
42604266
{
42614267
enum bpf_prog_type ptype;
@@ -4279,14 +4285,21 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
42794285
ret = tracing_bpf_link_attach(attr, uattr, prog);
42804286
goto out;
42814287
case BPF_PROG_TYPE_PERF_EVENT:
4282-
case BPF_PROG_TYPE_KPROBE:
42834288
case BPF_PROG_TYPE_TRACEPOINT:
42844289
if (attr->link_create.attach_type != BPF_PERF_EVENT) {
42854290
ret = -EINVAL;
42864291
goto out;
42874292
}
42884293
ptype = prog->type;
42894294
break;
4295+
case BPF_PROG_TYPE_KPROBE:
4296+
if (attr->link_create.attach_type != BPF_PERF_EVENT &&
4297+
attr->link_create.attach_type != BPF_TRACE_KPROBE_MULTI) {
4298+
ret = -EINVAL;
4299+
goto out;
4300+
}
4301+
ptype = prog->type;
4302+
break;
42904303
default:
42914304
ptype = attach_type_to_prog_type(attr->link_create.attach_type);
42924305
if (ptype == BPF_PROG_TYPE_UNSPEC || ptype != prog->type) {
@@ -4318,13 +4331,16 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr)
43184331
ret = bpf_xdp_link_attach(attr, prog);
43194332
break;
43204333
#endif
4321-
#ifdef CONFIG_PERF_EVENTS
43224334
case BPF_PROG_TYPE_PERF_EVENT:
43234335
case BPF_PROG_TYPE_TRACEPOINT:
4324-
case BPF_PROG_TYPE_KPROBE:
43254336
ret = bpf_perf_link_attach(attr, prog);
43264337
break;
4327-
#endif
4338+
case BPF_PROG_TYPE_KPROBE:
4339+
if (attr->link_create.attach_type == BPF_PERF_EVENT)
4340+
ret = bpf_perf_link_attach(attr, prog);
4341+
else
4342+
ret = bpf_kprobe_multi_link_attach(attr, prog);
4343+
break;
43284344
default:
43294345
ret = -EINVAL;
43304346
}

kernel/bpf/verifier.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13678,7 +13678,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1367813678
continue;
1367913679
}
1368013680

13681-
/* Implement bpf_get_func_ip inline. */
13681+
/* Implement tracing bpf_get_func_ip inline. */
1368213682
if (prog_type == BPF_PROG_TYPE_TRACING &&
1368313683
insn->imm == BPF_FUNC_get_func_ip) {
1368413684
/* Load IP address from ctx - 16 */
@@ -13693,6 +13693,25 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1369313693
continue;
1369413694
}
1369513695

13696+
#ifdef CONFIG_X86
13697+
/* Implement kprobe_multi bpf_get_func_ip inline. */
13698+
if (prog_type == BPF_PROG_TYPE_KPROBE &&
13699+
eatype == BPF_TRACE_KPROBE_MULTI &&
13700+
insn->imm == BPF_FUNC_get_func_ip) {
13701+
/* Load IP address from ctx (struct pt_regs) ip */
13702+
insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1,
13703+
offsetof(struct pt_regs, ip));
13704+
13705+
new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, 1);
13706+
if (!new_prog)
13707+
return -ENOMEM;
13708+
13709+
env->prog = prog = new_prog;
13710+
insn = new_prog->insnsi + i + delta;
13711+
continue;
13712+
}
13713+
#endif
13714+
1369613715
patch_call_imm:
1369713716
fn = env->ops->get_func_proto(insn->imm, env->prog);
1369813717
/* all functions that have prototype and verifier allowed

kernel/kallsyms.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,10 @@ unsigned long kallsyms_lookup_name(const char *name)
212212
unsigned long i;
213213
unsigned int off;
214214

215+
/* Skip the search for empty string. */
216+
if (!*name)
217+
return 0;
218+
215219
for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
216220
off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
217221

0 commit comments

Comments
 (0)