diff options
Diffstat (limited to 'tools/lib/bpf/libbpf.c')
-rw-r--r-- | tools/lib/bpf/libbpf.c | 67 |
1 files changed, 41 insertions, 26 deletions
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 794dd5064ae8..2b57d7ea7836 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <inttypes.h> | 20 | #include <inttypes.h> |
21 | #include <string.h> | 21 | #include <string.h> |
22 | #include <unistd.h> | 22 | #include <unistd.h> |
23 | #include <endian.h> | ||
23 | #include <fcntl.h> | 24 | #include <fcntl.h> |
24 | #include <errno.h> | 25 | #include <errno.h> |
25 | #include <asm/unistd.h> | 26 | #include <asm/unistd.h> |
@@ -181,7 +182,6 @@ struct bpf_program { | |||
181 | bpf_program_clear_priv_t clear_priv; | 182 | bpf_program_clear_priv_t clear_priv; |
182 | 183 | ||
183 | enum bpf_attach_type expected_attach_type; | 184 | enum bpf_attach_type expected_attach_type; |
184 | int btf_fd; | ||
185 | void *func_info; | 185 | void *func_info; |
186 | __u32 func_info_rec_size; | 186 | __u32 func_info_rec_size; |
187 | __u32 func_info_cnt; | 187 | __u32 func_info_cnt; |
@@ -312,7 +312,6 @@ void bpf_program__unload(struct bpf_program *prog) | |||
312 | prog->instances.nr = -1; | 312 | prog->instances.nr = -1; |
313 | zfree(&prog->instances.fds); | 313 | zfree(&prog->instances.fds); |
314 | 314 | ||
315 | zclose(prog->btf_fd); | ||
316 | zfree(&prog->func_info); | 315 | zfree(&prog->func_info); |
317 | zfree(&prog->line_info); | 316 | zfree(&prog->line_info); |
318 | } | 317 | } |
@@ -391,7 +390,6 @@ bpf_program__init(void *data, size_t size, char *section_name, int idx, | |||
391 | prog->instances.fds = NULL; | 390 | prog->instances.fds = NULL; |
392 | prog->instances.nr = -1; | 391 | prog->instances.nr = -1; |
393 | prog->type = BPF_PROG_TYPE_UNSPEC; | 392 | prog->type = BPF_PROG_TYPE_UNSPEC; |
394 | prog->btf_fd = -1; | ||
395 | 393 | ||
396 | return 0; | 394 | return 0; |
397 | errout: | 395 | errout: |
@@ -612,10 +610,10 @@ errout: | |||
612 | 610 | ||
613 | static int bpf_object__check_endianness(struct bpf_object *obj) | 611 | static int bpf_object__check_endianness(struct bpf_object *obj) |
614 | { | 612 | { |
615 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | 613 | #if __BYTE_ORDER == __LITTLE_ENDIAN |
616 | if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2LSB) | 614 | if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2LSB) |
617 | return 0; | 615 | return 0; |
618 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | 616 | #elif __BYTE_ORDER == __BIG_ENDIAN |
619 | if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2MSB) | 617 | if (obj->efile.ehdr.e_ident[EI_DATA] == ELFDATA2MSB) |
620 | return 0; | 618 | return 0; |
621 | #else | 619 | #else |
@@ -1377,8 +1375,13 @@ static void bpf_object__sanitize_btf(struct bpf_object *obj) | |||
1377 | if (!has_datasec && kind == BTF_KIND_VAR) { | 1375 | if (!has_datasec && kind == BTF_KIND_VAR) { |
1378 | /* replace VAR with INT */ | 1376 | /* replace VAR with INT */ |
1379 | t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0); | 1377 | t->info = BTF_INFO_ENC(BTF_KIND_INT, 0, 0); |
1380 | t->size = sizeof(int); | 1378 | /* |
1381 | *(int *)(t+1) = BTF_INT_ENC(0, 0, 32); | 1379 | * using size = 1 is the safest choice, 4 will be too |
1380 | * big and cause kernel BTF validation failure if | ||
1381 | * original variable took less than 4 bytes | ||
1382 | */ | ||
1383 | t->size = 1; | ||
1384 | *(int *)(t+1) = BTF_INT_ENC(0, 0, 8); | ||
1382 | } else if (!has_datasec && kind == BTF_KIND_DATASEC) { | 1385 | } else if (!has_datasec && kind == BTF_KIND_DATASEC) { |
1383 | /* replace DATASEC with STRUCT */ | 1386 | /* replace DATASEC with STRUCT */ |
1384 | struct btf_var_secinfo *v = (void *)(t + 1); | 1387 | struct btf_var_secinfo *v = (void *)(t + 1); |
@@ -1500,6 +1503,12 @@ static int bpf_object__sanitize_and_load_btf(struct bpf_object *obj) | |||
1500 | BTF_ELF_SEC, err); | 1503 | BTF_ELF_SEC, err); |
1501 | btf__free(obj->btf); | 1504 | btf__free(obj->btf); |
1502 | obj->btf = NULL; | 1505 | obj->btf = NULL; |
1506 | /* btf_ext can't exist without btf, so free it as well */ | ||
1507 | if (obj->btf_ext) { | ||
1508 | btf_ext__free(obj->btf_ext); | ||
1509 | obj->btf_ext = NULL; | ||
1510 | } | ||
1511 | |||
1503 | if (bpf_object__is_btf_mandatory(obj)) | 1512 | if (bpf_object__is_btf_mandatory(obj)) |
1504 | return err; | 1513 | return err; |
1505 | } | 1514 | } |
@@ -2276,9 +2285,6 @@ bpf_program_reloc_btf_ext(struct bpf_program *prog, struct bpf_object *obj, | |||
2276 | prog->line_info_rec_size = btf_ext__line_info_rec_size(obj->btf_ext); | 2285 | prog->line_info_rec_size = btf_ext__line_info_rec_size(obj->btf_ext); |
2277 | } | 2286 | } |
2278 | 2287 | ||
2279 | if (!insn_offset) | ||
2280 | prog->btf_fd = btf__fd(obj->btf); | ||
2281 | |||
2282 | return 0; | 2288 | return 0; |
2283 | } | 2289 | } |
2284 | 2290 | ||
@@ -2451,7 +2457,7 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt, | |||
2451 | char *cp, errmsg[STRERR_BUFSIZE]; | 2457 | char *cp, errmsg[STRERR_BUFSIZE]; |
2452 | int log_buf_size = BPF_LOG_BUF_SIZE; | 2458 | int log_buf_size = BPF_LOG_BUF_SIZE; |
2453 | char *log_buf; | 2459 | char *log_buf; |
2454 | int ret; | 2460 | int btf_fd, ret; |
2455 | 2461 | ||
2456 | if (!insns || !insns_cnt) | 2462 | if (!insns || !insns_cnt) |
2457 | return -EINVAL; | 2463 | return -EINVAL; |
@@ -2466,7 +2472,12 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt, | |||
2466 | load_attr.license = license; | 2472 | load_attr.license = license; |
2467 | load_attr.kern_version = kern_version; | 2473 | load_attr.kern_version = kern_version; |
2468 | load_attr.prog_ifindex = prog->prog_ifindex; | 2474 | load_attr.prog_ifindex = prog->prog_ifindex; |
2469 | load_attr.prog_btf_fd = prog->btf_fd >= 0 ? prog->btf_fd : 0; | 2475 | /* if .BTF.ext was loaded, kernel supports associated BTF for prog */ |
2476 | if (prog->obj->btf_ext) | ||
2477 | btf_fd = bpf_object__btf_fd(prog->obj); | ||
2478 | else | ||
2479 | btf_fd = -1; | ||
2480 | load_attr.prog_btf_fd = btf_fd >= 0 ? btf_fd : 0; | ||
2470 | load_attr.func_info = prog->func_info; | 2481 | load_attr.func_info = prog->func_info; |
2471 | load_attr.func_info_rec_size = prog->func_info_rec_size; | 2482 | load_attr.func_info_rec_size = prog->func_info_rec_size; |
2472 | load_attr.func_info_cnt = prog->func_info_cnt; | 2483 | load_attr.func_info_cnt = prog->func_info_cnt; |
@@ -4507,13 +4518,13 @@ struct perf_buffer *perf_buffer__new(int map_fd, size_t page_cnt, | |||
4507 | const struct perf_buffer_opts *opts) | 4518 | const struct perf_buffer_opts *opts) |
4508 | { | 4519 | { |
4509 | struct perf_buffer_params p = {}; | 4520 | struct perf_buffer_params p = {}; |
4510 | struct perf_event_attr attr = { | 4521 | struct perf_event_attr attr = { 0, }; |
4511 | .config = PERF_COUNT_SW_BPF_OUTPUT, | 4522 | |
4512 | .type = PERF_TYPE_SOFTWARE, | 4523 | attr.config = PERF_COUNT_SW_BPF_OUTPUT, |
4513 | .sample_type = PERF_SAMPLE_RAW, | 4524 | attr.type = PERF_TYPE_SOFTWARE; |
4514 | .sample_period = 1, | 4525 | attr.sample_type = PERF_SAMPLE_RAW; |
4515 | .wakeup_events = 1, | 4526 | attr.sample_period = 1; |
4516 | }; | 4527 | attr.wakeup_events = 1; |
4517 | 4528 | ||
4518 | p.attr = &attr; | 4529 | p.attr = &attr; |
4519 | p.sample_cb = opts ? opts->sample_cb : NULL; | 4530 | p.sample_cb = opts ? opts->sample_cb : NULL; |
@@ -4988,13 +4999,15 @@ int libbpf_num_possible_cpus(void) | |||
4988 | static const char *fcpu = "/sys/devices/system/cpu/possible"; | 4999 | static const char *fcpu = "/sys/devices/system/cpu/possible"; |
4989 | int len = 0, n = 0, il = 0, ir = 0; | 5000 | int len = 0, n = 0, il = 0, ir = 0; |
4990 | unsigned int start = 0, end = 0; | 5001 | unsigned int start = 0, end = 0; |
5002 | int tmp_cpus = 0; | ||
4991 | static int cpus; | 5003 | static int cpus; |
4992 | char buf[128]; | 5004 | char buf[128]; |
4993 | int error = 0; | 5005 | int error = 0; |
4994 | int fd = -1; | 5006 | int fd = -1; |
4995 | 5007 | ||
4996 | if (cpus > 0) | 5008 | tmp_cpus = READ_ONCE(cpus); |
4997 | return cpus; | 5009 | if (tmp_cpus > 0) |
5010 | return tmp_cpus; | ||
4998 | 5011 | ||
4999 | fd = open(fcpu, O_RDONLY); | 5012 | fd = open(fcpu, O_RDONLY); |
5000 | if (fd < 0) { | 5013 | if (fd < 0) { |
@@ -5017,7 +5030,7 @@ int libbpf_num_possible_cpus(void) | |||
5017 | } | 5030 | } |
5018 | buf[len] = '\0'; | 5031 | buf[len] = '\0'; |
5019 | 5032 | ||
5020 | for (ir = 0, cpus = 0; ir <= len; ir++) { | 5033 | for (ir = 0, tmp_cpus = 0; ir <= len; ir++) { |
5021 | /* Each sub string separated by ',' has format \d+-\d+ or \d+ */ | 5034 | /* Each sub string separated by ',' has format \d+-\d+ or \d+ */ |
5022 | if (buf[ir] == ',' || buf[ir] == '\0') { | 5035 | if (buf[ir] == ',' || buf[ir] == '\0') { |
5023 | buf[ir] = '\0'; | 5036 | buf[ir] = '\0'; |
@@ -5029,13 +5042,15 @@ int libbpf_num_possible_cpus(void) | |||
5029 | } else if (n == 1) { | 5042 | } else if (n == 1) { |
5030 | end = start; | 5043 | end = start; |
5031 | } | 5044 | } |
5032 | cpus += end - start + 1; | 5045 | tmp_cpus += end - start + 1; |
5033 | il = ir + 1; | 5046 | il = ir + 1; |
5034 | } | 5047 | } |
5035 | } | 5048 | } |
5036 | if (cpus <= 0) { | 5049 | if (tmp_cpus <= 0) { |
5037 | pr_warning("Invalid #CPUs %d from %s\n", cpus, fcpu); | 5050 | pr_warning("Invalid #CPUs %d from %s\n", tmp_cpus, fcpu); |
5038 | return -EINVAL; | 5051 | return -EINVAL; |
5039 | } | 5052 | } |
5040 | return cpus; | 5053 | |
5054 | WRITE_ONCE(cpus, tmp_cpus); | ||
5055 | return tmp_cpus; | ||
5041 | } | 5056 | } |