Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

selftests/bpf: Improve test coverage for kfunc call

On powerpc, immediate load instructions are sign extended. In case
of unsigned types, arguments should be explicitly zero-extended by
the caller. For kfunc call, this needs to be handled in the JIT code.
In bpf_kfunc_call_test4(), that tests for sign-extension of signed
argument types in kfunc calls, add some additional failure checks.
And add bpf_kfunc_call_test5() to test zero-extension of unsigned
argument types in kfunc calls.

Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20260312080113.843408-1-hbathini@linux.ibm.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Hari Bathini and committed by
Alexei Starovoitov
2af3aa70 ca0f39a3

+154 -1
+2
tools/testing/selftests/bpf/prog_tests/kfunc_call.c
··· 74 74 TC_TEST(kfunc_call_test1, 12), 75 75 TC_TEST(kfunc_call_test2, 3), 76 76 TC_TEST(kfunc_call_test4, -1234), 77 + TC_TEST(kfunc_call_test5, 0), 78 + TC_TEST(kfunc_call_test5_asm, 0), 77 79 TC_TEST(kfunc_call_test_ref_btf_id, 0), 78 80 TC_TEST(kfunc_call_test_get_mem, 42), 79 81 SYSCALL_TEST(kfunc_syscall_test, 0),
+98
tools/testing/selftests/bpf/progs/kfunc_call_test.c
··· 2 2 /* Copyright (c) 2021 Facebook */ 3 3 #include <vmlinux.h> 4 4 #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 5 6 #include "../test_kmods/bpf_testmod_kfunc.h" 7 + 8 + SEC("tc") 9 + int kfunc_call_test5(struct __sk_buff *skb) 10 + { 11 + struct bpf_sock *sk = skb->sk; 12 + int ret; 13 + u32 val32; 14 + u16 val16; 15 + u8 val8; 16 + 17 + if (!sk) 18 + return -1; 19 + 20 + sk = bpf_sk_fullsock(sk); 21 + if (!sk) 22 + return -1; 23 + 24 + /* 25 + * Test with constant values to verify zero-extension. 26 + * ISA-dependent BPF asm: 27 + * With ALU32: w1 = 0xFF; w2 = 0xFFFF; w3 = 0xFFFFffff 28 + * Without ALU32: r1 = 0xFF; r2 = 0xFFFF; r3 = 0xFFFFffff 29 + * Both zero-extend to 64-bit before the kfunc call. 30 + */ 31 + ret = bpf_kfunc_call_test5(0xFF, 0xFFFF, 0xFFFFffffULL); 32 + if (ret) 33 + return ret; 34 + 35 + val32 = bpf_get_prandom_u32(); 36 + val16 = val32 & 0xFFFF; 37 + val8 = val32 & 0xFF; 38 + ret = bpf_kfunc_call_test5(val8, val16, val32); 39 + if (ret) 40 + return ret; 41 + 42 + /* 43 + * Test multiplication with different operand sizes: 44 + * 45 + * val8 * 0xFF: 46 + * - Both operands promote to int (32-bit signed) 47 + * - Result: 32-bit multiplication, truncated to u8, then zero-extended 48 + * 49 + * val16 * 0xFFFF: 50 + * - Both operands promote to int (32-bit signed) 51 + * - Result: 32-bit multiplication, truncated to u16, then zero-extended 52 + * 53 + * val32 * 0xFFFFffffULL: 54 + * - val32 (u32) promotes to unsigned long long (due to ULL suffix) 55 + * - Result: 64-bit unsigned multiplication, truncated to u32, then zero-extended 56 + */ 57 + ret = bpf_kfunc_call_test5(val8 * 0xFF, val16 * 0xFFFF, val32 * 0xFFFFffffULL); 58 + if (ret) 59 + return ret; 60 + 61 + return 0; 62 + } 63 + 64 + /* 65 + * Assembly version testing the multiplication edge case explicitly. 66 + * This ensures consistent testing across different ISA versions. 67 + */ 68 + SEC("tc") 69 + __naked int kfunc_call_test5_asm(void) 70 + { 71 + asm volatile ( 72 + /* Get a random u32 value */ 73 + "call %[bpf_get_prandom_u32];" 74 + "r6 = r0;" /* Save val32 in r6 */ 75 + 76 + /* Prepare first argument: val8 * 0xFF */ 77 + "r1 = r6;" 78 + "r1 &= 0xFF;" /* val8 = val32 & 0xFF */ 79 + "r7 = 0xFF;" 80 + "r1 *= r7;" /* 64-bit mult: r1 = r1 * r7 */ 81 + 82 + /* Prepare second argument: val16 * 0xFFFF */ 83 + "r2 = r6;" 84 + "r2 &= 0xFFFF;" /* val16 = val32 & 0xFFFF */ 85 + "r7 = 0xFFFF;" 86 + "r2 *= r7;" /* 64-bit mult: r2 = r2 * r7 */ 87 + 88 + /* Prepare third argument: val32 * 0xFFFFffff */ 89 + "r3 = r6;" /* val32 */ 90 + "r7 = 0xFFFFffff;" 91 + "r3 *= r7;" /* 64-bit mult: r3 = r3 * r7 */ 92 + 93 + /* Call kfunc with multiplication results */ 94 + "call bpf_kfunc_call_test5;" 95 + 96 + /* Check return value */ 97 + "if r0 != 0 goto exit_%=;" 98 + "r0 = 0;" 99 + "exit_%=: exit;" 100 + : 101 + : __imm(bpf_get_prandom_u32) 102 + : __clobber_all); 103 + } 6 104 7 105 SEC("tc") 8 106 int kfunc_call_test4(struct __sk_buff *skb)
+53 -1
tools/testing/selftests/bpf/test_kmods/bpf_testmod.c
··· 760 760 761 761 __bpf_kfunc long noinline bpf_kfunc_call_test4(signed char a, short b, int c, long d) 762 762 { 763 - /* Provoke the compiler to assume that the caller has sign-extended a, 763 + /* 764 + * Make val as volatile to avoid compiler optimizations. 765 + * Verify that negative signed values remain negative after 766 + * sign-extension (JIT must sign-extend, not zero-extend). 767 + */ 768 + volatile long val; 769 + 770 + /* val will be positive, if JIT does zero-extension instead of sign-extension */ 771 + val = a; 772 + if (val >= 0) 773 + return 1; 774 + 775 + val = b; 776 + if (val >= 0) 777 + return 2; 778 + 779 + val = c; 780 + if (val >= 0) 781 + return 3; 782 + 783 + /* 784 + * Provoke the compiler to assume that the caller has sign-extended a, 764 785 * b and c on platforms where this is required (e.g. s390x). 765 786 */ 766 787 return (long)a + (long)b + (long)c + d; 788 + } 789 + 790 + __bpf_kfunc int bpf_kfunc_call_test5(u8 a, u16 b, u32 c) 791 + { 792 + /* 793 + * Make val as volatile to avoid compiler optimizations on the below checks 794 + * In C, assigning u8/u16/u32 to long performs zero-extension. 795 + */ 796 + volatile long val = a; 797 + 798 + /* Check zero-extension */ 799 + if (val != (unsigned long)a) 800 + return 1; 801 + /* Check no sign-extension */ 802 + if (val < 0) 803 + return 2; 804 + 805 + val = b; 806 + if (val != (unsigned long)b) 807 + return 3; 808 + if (val < 0) 809 + return 4; 810 + 811 + val = c; 812 + if (val != (unsigned long)c) 813 + return 5; 814 + if (val < 0) 815 + return 6; 816 + 817 + return 0; 767 818 } 768 819 769 820 static struct prog_test_ref_kfunc prog_test_struct = { ··· 1279 1228 BTF_ID_FLAGS(func, bpf_kfunc_call_test2) 1280 1229 BTF_ID_FLAGS(func, bpf_kfunc_call_test3) 1281 1230 BTF_ID_FLAGS(func, bpf_kfunc_call_test4) 1231 + BTF_ID_FLAGS(func, bpf_kfunc_call_test5) 1282 1232 BTF_ID_FLAGS(func, bpf_kfunc_call_test_mem_len_pass1) 1283 1233 BTF_ID_FLAGS(func, bpf_kfunc_call_test_mem_len_fail1) 1284 1234 BTF_ID_FLAGS(func, bpf_kfunc_call_test_mem_len_fail2)
+1
tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h
··· 110 110 int bpf_kfunc_call_test2(struct sock *sk, __u32 a, __u32 b) __ksym; 111 111 struct sock *bpf_kfunc_call_test3(struct sock *sk) __ksym; 112 112 long bpf_kfunc_call_test4(signed char a, short b, int c, long d) __ksym; 113 + int bpf_kfunc_call_test5(__u8 a, __u16 b, __u32 c) __ksym; 113 114 114 115 void bpf_kfunc_call_test_pass_ctx(struct __sk_buff *skb) __ksym; 115 116 void bpf_kfunc_call_test_pass1(struct prog_test_pass1 *p) __ksym;