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

Merge branch 's390-bpf-add-s390-jit-support-for-timed-may_goto'

Ilya Leoshkevich says:

====================
s390/bpf: Add s390 JIT support for timed may_goto

v1: https://lore.kernel.org/bpf/20250821103256.291412-1-iii@linux.ibm.com/
v1 -> v2: Fix test_stream_errors (caught by CI).

This series adds timed may_goto implementation to the s390x JIT.
Patch 1 is the implementation itself, patches 2-5 are the associated
test changes.
====================

Link: https://patch.msgid.link/20250821113339.292434-1-iii@linux.ibm.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+81 -10
+1 -1
arch/s390/net/Makefile
··· 2 2 # 3 3 # Arch-specific network modules 4 4 # 5 - obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o 5 + obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o bpf_timed_may_goto.o 6 6 obj-$(CONFIG_HAVE_PNETID) += pnet.o
+21 -4
arch/s390/net/bpf_jit_comp.c
··· 1806 1806 } 1807 1807 } 1808 1808 1809 - /* brasl %r14,func */ 1810 - EMIT6_PCREL_RILB_PTR(0xc0050000, REG_14, (void *)func); 1811 - /* lgr %b0,%r2: load return value into %b0 */ 1812 - EMIT4(0xb9040000, BPF_REG_0, REG_2); 1809 + if ((void *)func == arch_bpf_timed_may_goto) { 1810 + /* 1811 + * arch_bpf_timed_may_goto() has a special ABI: the 1812 + * parameters are in BPF_REG_AX and BPF_REG_10; the 1813 + * return value is in BPF_REG_AX; and all GPRs except 1814 + * REG_W0, REG_W1, and BPF_REG_AX are callee-saved. 1815 + */ 1816 + 1817 + /* brasl %r0,func */ 1818 + EMIT6_PCREL_RILB_PTR(0xc0050000, REG_0, (void *)func); 1819 + } else { 1820 + /* brasl %r14,func */ 1821 + EMIT6_PCREL_RILB_PTR(0xc0050000, REG_14, (void *)func); 1822 + /* lgr %b0,%r2: load return value into %b0 */ 1823 + EMIT4(0xb9040000, BPF_REG_0, REG_2); 1824 + } 1813 1825 1814 1826 /* 1815 1827 * Copy the potentially updated tail call counter back. ··· 3004 2992 break; 3005 2993 prev_addr = addr; 3006 2994 } 2995 + } 2996 + 2997 + bool bpf_jit_supports_timed_may_goto(void) 2998 + { 2999 + return true; 3007 3000 }
+45
arch/s390/net/bpf_timed_may_goto.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + 3 + #include <linux/export.h> 4 + #include <linux/linkage.h> 5 + #include <asm/asm-offsets.h> 6 + #include <asm/nospec-insn.h> 7 + 8 + #define R2_OFF 0 9 + #define R5_OFF (R2_OFF + (5 - 2 + 1) * 8) 10 + #define R14_OFF (R5_OFF + 8) 11 + #define RETADDR_OFF (R14_OFF + 8) 12 + #define R15_OFF (RETADDR_OFF + 8) 13 + #define BACKCHAIN_OFF (R15_OFF + 8) 14 + #define FRAME_SIZE (BACKCHAIN_OFF + 8) 15 + #define FRAME_OFF (STACK_FRAME_OVERHEAD - FRAME_SIZE) 16 + #if (FRAME_OFF + BACKCHAIN_OFF) != __SF_BACKCHAIN 17 + #error Stack frame layout calculation is broken 18 + #endif 19 + 20 + GEN_BR_THUNK %r1 21 + 22 + SYM_FUNC_START(arch_bpf_timed_may_goto) 23 + /* 24 + * This function has a special ABI: the parameters are in %r12 and 25 + * %r13; the return value is in %r12; all GPRs except %r0, %r1, and 26 + * %r12 are callee-saved; and the return address is in %r0. 27 + */ 28 + stmg %r2,%r5,FRAME_OFF+R2_OFF(%r15) 29 + stg %r14,FRAME_OFF+R14_OFF(%r15) 30 + stg %r0,FRAME_OFF+RETADDR_OFF(%r15) 31 + stg %r15,FRAME_OFF+R15_OFF(%r15) 32 + lgr %r1,%r15 33 + lay %r15,-FRAME_SIZE(%r15) 34 + stg %r1,__SF_BACKCHAIN(%r15) 35 + 36 + lay %r2,0(%r12,%r13) 37 + brasl %r14,bpf_check_timed_may_goto 38 + lgr %r12,%r2 39 + 40 + lg %r15,FRAME_SIZE+FRAME_OFF+R15_OFF(%r15) 41 + lmg %r2,%r5,FRAME_OFF+R2_OFF(%r15) 42 + lg %r14,FRAME_OFF+R14_OFF(%r15) 43 + lg %r1,FRAME_OFF+RETADDR_OFF(%r15) 44 + BR_EX %r1 45 + SYM_FUNC_END(arch_bpf_timed_may_goto)
-1
tools/testing/selftests/bpf/DENYLIST.s390x
··· 2 2 # Alphabetical order 3 3 get_stack_raw_tp # user_stack corrupted user stack (no backchain userspace) 4 4 stacktrace_build_id # compare_map_keys stackid_hmap vs. stackmap err -2 errno 2 (?) 5 - verifier_iterating_callbacks
+1 -1
tools/testing/selftests/bpf/prog_tests/stream.c
··· 77 77 ASSERT_OK(ret, "ret"); 78 78 ASSERT_OK(opts.retval, "retval"); 79 79 80 - #if !defined(__x86_64__) 80 + #if !defined(__x86_64__) && !defined(__s390x__) 81 81 ASSERT_TRUE(1, "Timed may_goto unsupported, skip."); 82 82 if (i == 0) { 83 83 ret = bpf_prog_stream_read(prog_fd, 2, buf, sizeof(buf), &ropts);
+1
tools/testing/selftests/bpf/progs/bpf_misc.h
··· 136 136 #define __arch_x86_64 __arch("X86_64") 137 137 #define __arch_arm64 __arch("ARM64") 138 138 #define __arch_riscv64 __arch("RISCV64") 139 + #define __arch_s390x __arch("s390x") 139 140 #define __caps_unpriv(caps) __attribute__((btf_decl_tag("comment:test_caps_unpriv=" EXPAND_QUOTE(caps)))) 140 141 #define __load_if_JITed() __attribute__((btf_decl_tag("comment:load_mode=jited"))) 141 142 #define __load_if_no_JITed() __attribute__((btf_decl_tag("comment:load_mode=no_jited")))
+6 -2
tools/testing/selftests/bpf/progs/verifier_may_goto_1.c
··· 9 9 SEC("raw_tp") 10 10 __description("may_goto 0") 11 11 __arch_x86_64 12 + __arch_s390x 12 13 __xlated("0: r0 = 1") 13 14 __xlated("1: exit") 14 15 __success ··· 28 27 SEC("raw_tp") 29 28 __description("batch 2 of may_goto 0") 30 29 __arch_x86_64 30 + __arch_s390x 31 31 __xlated("0: r0 = 1") 32 32 __xlated("1: exit") 33 33 __success ··· 49 47 SEC("raw_tp") 50 48 __description("may_goto batch with offsets 2/1/0") 51 49 __arch_x86_64 50 + __arch_s390x 52 51 __xlated("0: r0 = 1") 53 52 __xlated("1: exit") 54 53 __success ··· 72 69 } 73 70 74 71 SEC("raw_tp") 75 - __description("may_goto batch with offsets 2/0 - x86_64") 72 + __description("may_goto batch with offsets 2/0 - x86_64 and s390x") 76 73 __arch_x86_64 74 + __arch_s390x 77 75 __xlated("0: *(u64 *)(r10 -16) = 65535") 78 76 __xlated("1: *(u64 *)(r10 -8) = 0") 79 77 __xlated("2: r11 = *(u64 *)(r10 -16)") ··· 88 84 __xlated("10: r0 = 2") 89 85 __xlated("11: exit") 90 86 __success 91 - __naked void may_goto_batch_2_x86_64(void) 87 + __naked void may_goto_batch_2_x86_64_s390x(void) 92 88 { 93 89 asm volatile ( 94 90 ".8byte %[may_goto1];"
+6 -1
tools/testing/selftests/bpf/test_loader.c
··· 374 374 ARCH_X86_64 = 0x2, 375 375 ARCH_ARM64 = 0x4, 376 376 ARCH_RISCV64 = 0x8, 377 + ARCH_S390X = 0x10, 377 378 }; 378 379 379 380 static int get_current_arch(void) ··· 385 384 return ARCH_ARM64; 386 385 #elif defined(__riscv) && __riscv_xlen == 64 387 386 return ARCH_RISCV64; 387 + #elif defined(__s390x__) 388 + return ARCH_S390X; 388 389 #endif 389 390 return ARCH_UNKNOWN; 390 391 } ··· 568 565 arch = ARCH_ARM64; 569 566 } else if (strcmp(val, "RISCV64") == 0) { 570 567 arch = ARCH_RISCV64; 568 + } else if (strcmp(val, "s390x") == 0) { 569 + arch = ARCH_S390X; 571 570 } else { 572 - PRINT_FAIL("bad arch spec: '%s'", val); 571 + PRINT_FAIL("bad arch spec: '%s'\n", val); 573 572 err = -EINVAL; 574 573 goto cleanup; 575 574 }