From 8b1cb1c9601f835c025af5b3cf0e98c8048ad30b Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Fri, 1 Nov 2019 15:28:09 -0700 Subject: selftest/bpf: Add relocatable bitfield reading tests Add a bunch of selftests verifying correctness of relocatable bitfield reading support in libbpf. Both bpf_probe_read()-based and direct read-based bitfield macros are tested. core_reloc.c "test_harness" is extended to support raw tracepoint and new typed raw tracepoints as test BPF program types. Signed-off-by: Andrii Nakryiko Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20191101222810.1246166-5-andriin@fb.com --- .../bpf/progs/test_core_reloc_bitfields_probed.c | 62 ++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/test_core_reloc_bitfields_probed.c (limited to 'tools/testing/selftests/bpf/progs/test_core_reloc_bitfields_probed.c') diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_bitfields_probed.c b/tools/testing/selftests/bpf/progs/test_core_reloc_bitfields_probed.c new file mode 100644 index 000000000000..a381f8ac2419 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_bitfields_probed.c @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2019 Facebook + +#include +#include +#include "bpf_helpers.h" +#include "bpf_core_read.h" + +char _license[] SEC("license") = "GPL"; + +static volatile struct data { + char in[256]; + char out[256]; +} data; + +struct core_reloc_bitfields { + /* unsigned bitfields */ + uint8_t ub1: 1; + uint8_t ub2: 2; + uint32_t ub7: 7; + /* signed bitfields */ + int8_t sb4: 4; + int32_t sb20: 20; + /* non-bitfields */ + uint32_t u32; + int32_t s32; +}; + +/* bitfield read results, all as plain integers */ +struct core_reloc_bitfields_output { + int64_t ub1; + int64_t ub2; + int64_t ub7; + int64_t sb4; + int64_t sb20; + int64_t u32; + int64_t s32; +}; + +#define TRANSFER_BITFIELD(in, out, field) \ + if (BPF_CORE_READ_BITFIELD_PROBED(in, field, &res)) \ + return 1; \ + out->field = res + +SEC("raw_tracepoint/sys_enter") +int test_core_bitfields(void *ctx) +{ + struct core_reloc_bitfields *in = (void *)&data.in; + struct core_reloc_bitfields_output *out = (void *)&data.out; + uint64_t res; + + TRANSFER_BITFIELD(in, out, ub1); + TRANSFER_BITFIELD(in, out, ub2); + TRANSFER_BITFIELD(in, out, ub7); + TRANSFER_BITFIELD(in, out, sb4); + TRANSFER_BITFIELD(in, out, sb20); + TRANSFER_BITFIELD(in, out, u32); + TRANSFER_BITFIELD(in, out, s32); + + return 0; +} + -- cgit v1.2.3-59-g8ed1b From ed578021210e14f15a654c825fba6a700c9a39a7 Mon Sep 17 00:00:00 2001 From: Andrii Nakryiko Date: Wed, 6 Nov 2019 12:15:00 -0800 Subject: libbpf: Simplify BPF_CORE_READ_BITFIELD_PROBED usage Streamline BPF_CORE_READ_BITFIELD_PROBED interface to follow BPF_CORE_READ_BITFIELD (direct) and BPF_CORE_READ, in general, i.e., just return read result or 0, if underlying bpf_probe_read() failed. In practice, real applications rarely check bpf_probe_read() result, because it has to always work or otherwise it's a bug. So propagating internal bpf_probe_read() error from this macro hurts usability without providing real benefits in practice. This patch fixes the issue and simplifies usage, noticeable even in selftest itself. Signed-off-by: Andrii Nakryiko Signed-off-by: Alexei Starovoitov Acked-by: Yonghong Song Link: https://lore.kernel.org/bpf/20191106201500.2582438-1-andriin@fb.com --- tools/lib/bpf/bpf_core_read.h | 27 +++++++++------------- .../bpf/progs/test_core_reloc_bitfields_probed.c | 19 ++++++--------- 2 files changed, 18 insertions(+), 28 deletions(-) (limited to 'tools/testing/selftests/bpf/progs/test_core_reloc_bitfields_probed.c') diff --git a/tools/lib/bpf/bpf_core_read.h b/tools/lib/bpf/bpf_core_read.h index 11461b2623b0..7009dc90e012 100644 --- a/tools/lib/bpf/bpf_core_read.h +++ b/tools/lib/bpf/bpf_core_read.h @@ -39,32 +39,27 @@ enum bpf_field_info_kind { #endif /* - * Extract bitfield, identified by src->field, and put its value into u64 - * *res. All this is done in relocatable manner, so bitfield changes such as + * Extract bitfield, identified by s->field, and return its value as u64. + * All this is done in relocatable manner, so bitfield changes such as * signedness, bit size, offset changes, this will be handled automatically. * This version of macro is using bpf_probe_read() to read underlying integer * storage. Macro functions as an expression and its return type is * bpf_probe_read()'s return value: 0, on success, <0 on error. */ -#define BPF_CORE_READ_BITFIELD_PROBED(src, field, res) ({ \ - unsigned long long val; \ +#define BPF_CORE_READ_BITFIELD_PROBED(s, field) ({ \ + unsigned long long val = 0; \ \ - *res = 0; \ - val = __CORE_BITFIELD_PROBE_READ(res, src, field); \ - if (!val) { \ - *res <<= __CORE_RELO(src, field, LSHIFT_U64); \ - val = __CORE_RELO(src, field, RSHIFT_U64); \ - if (__CORE_RELO(src, field, SIGNED)) \ - *res = ((long long)*res) >> val; \ - else \ - *res = ((unsigned long long)*res) >> val; \ - val = 0; \ - } \ + __CORE_BITFIELD_PROBE_READ(&val, s, field); \ + val <<= __CORE_RELO(s, field, LSHIFT_U64); \ + if (__CORE_RELO(s, field, SIGNED)) \ + val = ((long long)val) >> __CORE_RELO(s, field, RSHIFT_U64); \ + else \ + val = val >> __CORE_RELO(s, field, RSHIFT_U64); \ val; \ }) /* - * Extract bitfield, identified by src->field, and return its value as u64. + * Extract bitfield, identified by s->field, and return its value as u64. * This version of macro is using direct memory reads and should be used from * BPF program types that support such functionality (e.g., typed raw * tracepoints). diff --git a/tools/testing/selftests/bpf/progs/test_core_reloc_bitfields_probed.c b/tools/testing/selftests/bpf/progs/test_core_reloc_bitfields_probed.c index a381f8ac2419..e466e3ab7de4 100644 --- a/tools/testing/selftests/bpf/progs/test_core_reloc_bitfields_probed.c +++ b/tools/testing/selftests/bpf/progs/test_core_reloc_bitfields_probed.c @@ -37,11 +37,6 @@ struct core_reloc_bitfields_output { int64_t s32; }; -#define TRANSFER_BITFIELD(in, out, field) \ - if (BPF_CORE_READ_BITFIELD_PROBED(in, field, &res)) \ - return 1; \ - out->field = res - SEC("raw_tracepoint/sys_enter") int test_core_bitfields(void *ctx) { @@ -49,13 +44,13 @@ int test_core_bitfields(void *ctx) struct core_reloc_bitfields_output *out = (void *)&data.out; uint64_t res; - TRANSFER_BITFIELD(in, out, ub1); - TRANSFER_BITFIELD(in, out, ub2); - TRANSFER_BITFIELD(in, out, ub7); - TRANSFER_BITFIELD(in, out, sb4); - TRANSFER_BITFIELD(in, out, sb20); - TRANSFER_BITFIELD(in, out, u32); - TRANSFER_BITFIELD(in, out, s32); + out->ub1 = BPF_CORE_READ_BITFIELD_PROBED(in, ub1); + out->ub2 = BPF_CORE_READ_BITFIELD_PROBED(in, ub2); + out->ub7 = BPF_CORE_READ_BITFIELD_PROBED(in, ub7); + out->sb4 = BPF_CORE_READ_BITFIELD_PROBED(in, sb4); + out->sb20 = BPF_CORE_READ_BITFIELD_PROBED(in, sb20); + out->u32 = BPF_CORE_READ_BITFIELD_PROBED(in, u32); + out->s32 = BPF_CORE_READ_BITFIELD_PROBED(in, s32); return 0; } -- cgit v1.2.3-59-g8ed1b