Teach test_loader to select IA32-specific cases and add unsigned bool and signed int kfunc-return tests. Each case consumes the high half of R0 after the call and checks the required zero or sign extension.
Signed-off-by: Yiyang Chen <[email protected]> --- tools/testing/selftests/bpf/prog_tests/verifier.c | 2 + tools/testing/selftests/bpf/progs/bpf_misc.h | 1 + .../selftests/bpf/progs/verifier_kfunc_return.c | 84 ++++++++++++++++++++++ tools/testing/selftests/bpf/test_loader.c | 13 ++-- 4 files changed, 96 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c index 8113fea7ba86c..4638e0a45db6e 100644 --- a/tools/testing/selftests/bpf/prog_tests/verifier.c +++ b/tools/testing/selftests/bpf/prog_tests/verifier.c @@ -127,6 +127,7 @@ #include "verifier_set_retval.skel.h" #include "verifier_lsm.skel.h" #include "verifier_jit_inline.skel.h" +#include "verifier_kfunc_return.skel.h" #include "irq.skel.h" #include "verifier_ctx_ptr_param.skel.h" #include "verifier_zext.skel.h" @@ -289,6 +290,7 @@ void test_verifier_lsm(void) { RUN(verifier_lsm); } void test_irq(void) { RUN(irq); } void test_verifier_mtu(void) { RUN(verifier_mtu); } void test_verifier_jit_inline(void) { RUN(verifier_jit_inline); } +void test_verifier_kfunc_return(void) { RUN(verifier_kfunc_return); } void test_verifier_ctx_ptr_param(void) { RUN(verifier_ctx_ptr_param); } void test_verifier_zext(void) { RUN_TESTS(verifier_zext); } diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h index 5eacf1b432521..1498da04597af 100644 --- a/tools/testing/selftests/bpf/progs/bpf_misc.h +++ b/tools/testing/selftests/bpf/progs/bpf_misc.h @@ -155,6 +155,7 @@ #define __btf_func_path(path) __test_tag("test_btf_func_path=" path) #define __arch(arch) __test_tag("test_arch=" arch) #define __arch_x86_64 __arch("X86_64") +#define __arch_x86_32 __arch("X86_32") #define __arch_arm64 __arch("ARM64") #define __arch_riscv64 __arch("RISCV64") #define __arch_s390x __arch("s390x") diff --git a/tools/testing/selftests/bpf/progs/verifier_kfunc_return.c b/tools/testing/selftests/bpf/progs/verifier_kfunc_return.c new file mode 100644 index 0000000000000..52a94daf03922 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/verifier_kfunc_return.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: GPL-2.0 + +#define BPF_NO_KFUNC_PROTOTYPES +#include <vmlinux.h> +#include <bpf/bpf_helpers.h> +#include "bpf_misc.h" + +extern int bpf_strcmp(const char *s1__ign, const char *s2__ign) __ksym; +extern bool bpf_dynptr_is_null(const struct bpf_dynptr *p) __ksym; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, __u32); + __type(value, __u64); +} kfunc_return_map SEC(".maps"); + +static const char string_a[] = "a"; +static const char string_b[] = "b"; + +void __kfunc_btf_root(void) +{ + struct bpf_dynptr ptr = {}; + + bpf_strcmp(string_a, string_b); + bpf_dynptr_is_null(&ptr); +} + +SEC("syscall") +__flag(BPF_F_SLEEPABLE) +__success __retval(0) +__arch_x86_32 +__naked void kfunc_bool_return_zero_extended(void) +{ + asm volatile (" \ + r0 = 0; \ + *(u32 *)(r10 - 4) = r0; \ + r2 = r10; \ + r2 += -4; \ + r1 = %[kfunc_return_map] ll; \ + call %[bpf_map_lookup_elem]; \ + if r0 == 0 goto 1f; \ + r1 = r0; \ + r2 = 8; \ + r3 = 0; \ + r4 = r10; \ + r4 += -24; \ + call %[bpf_dynptr_from_mem]; \ + if r0 != 0 goto 1f; \ + r0 = 0x100000000 ll; \ + r1 = r10; \ + r1 += -24; \ + call bpf_dynptr_is_null; \ + r0 >>= 32; \ + exit; \ +1: r0 = 2; \ + exit; \ +" : + : __imm_addr(kfunc_return_map), + __imm(bpf_map_lookup_elem), + __imm(bpf_dynptr_from_mem) + : __clobber_all); +} + +SEC("syscall") +__flag(BPF_F_SLEEPABLE) +__success __retval(-1) +__arch_x86_32 +__naked void kfunc_int_return_sign_extended(void) +{ + asm volatile (" \ + r0 = 0; \ + r1 = %[string_a] ll; \ + r2 = %[string_b] ll; \ + call bpf_strcmp; \ + r0 >>= 32; \ + exit; \ +" : + : __imm_addr(string_a), + __imm_addr(string_b) + : __clobber_all); +} + +char _license[] SEC("license") = "GPL"; diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c index 07807757b518d..8a9f4a31a1bb1 100644 --- a/tools/testing/selftests/bpf/test_loader.c +++ b/tools/testing/selftests/bpf/test_loader.c @@ -374,16 +374,19 @@ static const char **collect_decl_tags(struct btf *btf, int id, int *cnt) enum arch { ARCH_UNKNOWN = 0x1, ARCH_X86_64 = 0x2, - ARCH_ARM64 = 0x4, - ARCH_RISCV64 = 0x8, - ARCH_S390X = 0x10, - ARCH_LOONGARCH = 0x20, + ARCH_X86_32 = 0x4, + ARCH_ARM64 = 0x8, + ARCH_RISCV64 = 0x10, + ARCH_S390X = 0x20, + ARCH_LOONGARCH = 0x40, }; static int get_current_arch(void) { #if defined(__x86_64__) return ARCH_X86_64; +#elif defined(__i386__) + return ARCH_X86_32; #elif defined(__aarch64__) return ARCH_ARM64; #elif defined(__riscv) && __riscv_xlen == 64 @@ -577,6 +580,8 @@ static int parse_test_spec(struct test_loader *tester, } else if ((val = str_has_pfx(s, "test_arch="))) { if (strcmp(val, "X86_64") == 0) { arch = ARCH_X86_64; + } else if (strcmp(val, "X86_32") == 0) { + arch = ARCH_X86_32; } else if (strcmp(val, "ARM64") == 0) { arch = ARCH_ARM64; } else if (strcmp(val, "RISCV64") == 0) { -- 2.43.0

