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

Merge branch 's390-bpf-describe-the-frame-using-a-struct-instead-of-constants'

Ilya Leoshkevich says:

====================
s390/bpf: Describe the frame using a struct instead of constants

Hi,

This series contains two small refactorings without functional changes.

The first one removes the code duplication around calculating the
distance from %r15 to the stack frame.

The second one simplifies how offsets to various values stored inside
the frame are calculated.

Best regards,
Ilya
====================

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

+67 -101
-55
arch/s390/net/bpf_jit.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * BPF Jit compiler defines 4 - * 5 - * Copyright IBM Corp. 2012,2015 6 - * 7 - * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> 8 - * Michael Holzheu <holzheu@linux.vnet.ibm.com> 9 - */ 10 - 11 - #ifndef __ARCH_S390_NET_BPF_JIT_H 12 - #define __ARCH_S390_NET_BPF_JIT_H 13 - 14 - #ifndef __ASSEMBLY__ 15 - 16 - #include <linux/filter.h> 17 - #include <linux/types.h> 18 - 19 - #endif /* __ASSEMBLY__ */ 20 - 21 - /* 22 - * Stackframe layout (packed stack): 23 - * 24 - * ^ high 25 - * +---------------+ | 26 - * | old backchain | | 27 - * +---------------+ | 28 - * | r15 - r6 | | 29 - * +---------------+ | 30 - * | 4 byte align | | 31 - * | tail_call_cnt | | 32 - * BFP -> +===============+ | 33 - * | | | 34 - * | BPF stack | | 35 - * | | | 36 - * R15+160 -> +---------------+ | 37 - * | new backchain | | 38 - * R15+152 -> +---------------+ | 39 - * | + 152 byte SA | | 40 - * R15 -> +---------------+ + low 41 - * 42 - * We get 160 bytes stack space from calling function, but only use 43 - * 12 * 8 byte for old backchain, r15..r6, and tail_call_cnt. 44 - * 45 - * The stack size used by the BPF program ("BPF stack" above) is passed 46 - * via "aux->stack_depth". 47 - */ 48 - #define STK_SPACE_ADD (160) 49 - #define STK_160_UNUSED (160 - 12 * 8) 50 - #define STK_OFF (STK_SPACE_ADD - STK_160_UNUSED) 51 - 52 - #define STK_OFF_R6 (160 - 11 * 8) /* Offset of r6 on stack */ 53 - #define STK_OFF_TCCNT (160 - 12 * 8) /* Offset of tail_call_cnt on stack */ 54 - 55 - #endif /* __ARCH_S390_NET_BPF_JIT_H */
+67 -46
arch/s390/net/bpf_jit_comp.c
··· 32 32 #include <asm/set_memory.h> 33 33 #include <asm/text-patching.h> 34 34 #include <asm/unwind.h> 35 - #include "bpf_jit.h" 36 35 37 36 struct bpf_jit { 38 37 u32 seen; /* Flags to remember seen eBPF instructions */ ··· 53 54 int prologue_plt; /* Start of prologue hotpatch PLT */ 54 55 int kern_arena; /* Pool offset of kernel arena address */ 55 56 u64 user_arena; /* User arena address */ 57 + u32 frame_off; /* Offset of struct bpf_prog from %r15 */ 56 58 }; 57 59 58 60 #define SEEN_MEM BIT(0) /* use mem[] for temporary storage */ ··· 426 426 } 427 427 428 428 /* 429 + * Caller-allocated part of the frame. 430 + * Thanks to packed stack, its otherwise unused initial part can be used for 431 + * the BPF stack and for the next frame. 432 + */ 433 + struct prog_frame { 434 + u64 unused[8]; 435 + /* BPF stack starts here and grows towards 0 */ 436 + u32 tail_call_cnt; 437 + u32 pad; 438 + u64 r6[10]; /* r6 - r15 */ 439 + u64 backchain; 440 + } __packed; 441 + 442 + /* 429 443 * Save registers from "rs" (register start) to "re" (register end) on stack 430 444 */ 431 445 static void save_regs(struct bpf_jit *jit, u32 rs, u32 re) 432 446 { 433 - u32 off = STK_OFF_R6 + (rs - 6) * 8; 447 + u32 off = offsetof(struct prog_frame, r6) + (rs - 6) * 8; 434 448 435 449 if (rs == re) 436 450 /* stg %rs,off(%r15) */ ··· 457 443 /* 458 444 * Restore registers from "rs" (register start) to "re" (register end) on stack 459 445 */ 460 - static void restore_regs(struct bpf_jit *jit, u32 rs, u32 re, u32 stack_depth) 446 + static void restore_regs(struct bpf_jit *jit, u32 rs, u32 re) 461 447 { 462 - u32 off = STK_OFF_R6 + (rs - 6) * 8; 463 - 464 - if (jit->seen & SEEN_STACK) 465 - off += STK_OFF + stack_depth; 448 + u32 off = jit->frame_off + offsetof(struct prog_frame, r6) + (rs - 6) * 8; 466 449 467 450 if (rs == re) 468 451 /* lg %rs,off(%r15) */ ··· 503 492 * Save and restore clobbered registers (6-15) on stack. 504 493 * We save/restore registers in chunks with gap >= 2 registers. 505 494 */ 506 - static void save_restore_regs(struct bpf_jit *jit, int op, u32 stack_depth, 507 - u16 extra_regs) 495 + static void save_restore_regs(struct bpf_jit *jit, int op, u16 extra_regs) 508 496 { 509 497 u16 seen_regs = jit->seen_regs | extra_regs; 510 498 const int last = 15, save_restore_size = 6; ··· 526 516 if (op == REGS_SAVE) 527 517 save_regs(jit, rs, re); 528 518 else 529 - restore_regs(jit, rs, re, stack_depth); 519 + restore_regs(jit, rs, re); 530 520 re++; 531 521 } while (re <= last); 532 522 } ··· 583 573 * Emit function prologue 584 574 * 585 575 * Save registers and create stack frame if necessary. 586 - * See stack frame layout description in "bpf_jit.h"! 576 + * Stack frame layout is described by struct prog_frame. 587 577 */ 588 - static void bpf_jit_prologue(struct bpf_jit *jit, struct bpf_prog *fp, 589 - u32 stack_depth) 578 + static void bpf_jit_prologue(struct bpf_jit *jit, struct bpf_prog *fp) 590 579 { 580 + BUILD_BUG_ON(sizeof(struct prog_frame) != STACK_FRAME_OVERHEAD); 581 + 591 582 /* No-op for hotpatching */ 592 583 /* brcl 0,prologue_plt */ 593 584 EMIT6_PCREL_RILC(0xc0040000, 0, jit->prologue_plt); ··· 596 585 597 586 if (!bpf_is_subprog(fp)) { 598 587 /* Initialize the tail call counter in the main program. */ 599 - /* xc STK_OFF_TCCNT(4,%r15),STK_OFF_TCCNT(%r15) */ 600 - _EMIT6(0xd703f000 | STK_OFF_TCCNT, 0xf000 | STK_OFF_TCCNT); 588 + /* xc tail_call_cnt(4,%r15),tail_call_cnt(%r15) */ 589 + _EMIT6(0xd703f000 | offsetof(struct prog_frame, tail_call_cnt), 590 + 0xf000 | offsetof(struct prog_frame, tail_call_cnt)); 601 591 } else { 602 592 /* 603 593 * Skip the tail call counter initialization in subprograms. ··· 621 609 jit->seen_regs |= NVREGS; 622 610 } else { 623 611 /* Save registers */ 624 - save_restore_regs(jit, REGS_SAVE, stack_depth, 612 + save_restore_regs(jit, REGS_SAVE, 625 613 fp->aux->exception_boundary ? NVREGS : 0); 626 614 } 627 615 /* Setup literal pool */ ··· 641 629 if (is_first_pass(jit) || (jit->seen & SEEN_STACK)) { 642 630 /* lgr %w1,%r15 (backchain) */ 643 631 EMIT4(0xb9040000, REG_W1, REG_15); 644 - /* la %bfp,STK_160_UNUSED(%r15) (BPF frame pointer) */ 645 - EMIT4_DISP(0x41000000, BPF_REG_FP, REG_15, STK_160_UNUSED); 646 - /* aghi %r15,-STK_OFF */ 647 - EMIT4_IMM(0xa70b0000, REG_15, -(STK_OFF + stack_depth)); 648 - /* stg %w1,152(%r15) (backchain) */ 632 + /* la %bfp,unused_end(%r15) (BPF frame pointer) */ 633 + EMIT4_DISP(0x41000000, BPF_REG_FP, REG_15, 634 + offsetofend(struct prog_frame, unused)); 635 + /* aghi %r15,-frame_off */ 636 + EMIT4_IMM(0xa70b0000, REG_15, -jit->frame_off); 637 + /* stg %w1,backchain(%r15) */ 649 638 EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, 650 - REG_15, 152); 639 + REG_15, 640 + offsetof(struct prog_frame, backchain)); 651 641 } 652 642 } 653 643 ··· 683 669 /* 684 670 * Function epilogue 685 671 */ 686 - static void bpf_jit_epilogue(struct bpf_jit *jit, u32 stack_depth) 672 + static void bpf_jit_epilogue(struct bpf_jit *jit) 687 673 { 688 674 jit->exit_ip = jit->prg; 689 675 /* Load exit code: lgr %r2,%b0 */ 690 676 EMIT4(0xb9040000, REG_2, BPF_REG_0); 691 677 /* Restore registers */ 692 - save_restore_regs(jit, REGS_RESTORE, stack_depth, 0); 678 + save_restore_regs(jit, REGS_RESTORE, 0); 693 679 EMIT_JUMP_REG(14); 694 680 695 681 jit->prg = ALIGN(jit->prg, 8); ··· 871 857 * stack space for the large switch statement. 872 858 */ 873 859 static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, 874 - int i, bool extra_pass, u32 stack_depth) 860 + int i, bool extra_pass) 875 861 { 876 862 struct bpf_insn *insn = &fp->insnsi[i]; 877 863 s32 branch_oc_off = insn->off; ··· 1792 1778 * Note 2: We assume that the verifier does not let us call the 1793 1779 * main program, which clears the tail call counter on entry. 1794 1780 */ 1795 - /* mvc STK_OFF_TCCNT(4,%r15),N(%r15) */ 1796 - _EMIT6(0xd203f000 | STK_OFF_TCCNT, 1797 - 0xf000 | (STK_OFF_TCCNT + STK_OFF + stack_depth)); 1781 + /* mvc tail_call_cnt(4,%r15),frame_off+tail_call_cnt(%r15) */ 1782 + _EMIT6(0xd203f000 | offsetof(struct prog_frame, tail_call_cnt), 1783 + 0xf000 | (jit->frame_off + 1784 + offsetof(struct prog_frame, tail_call_cnt))); 1798 1785 1799 1786 /* Sign-extend the kfunc arguments. */ 1800 1787 if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) { ··· 1846 1831 * goto out; 1847 1832 */ 1848 1833 1849 - if (jit->seen & SEEN_STACK) 1850 - off = STK_OFF_TCCNT + STK_OFF + stack_depth; 1851 - else 1852 - off = STK_OFF_TCCNT; 1834 + off = jit->frame_off + 1835 + offsetof(struct prog_frame, tail_call_cnt); 1853 1836 /* lhi %w0,1 */ 1854 1837 EMIT4_IMM(0xa7080000, REG_W0, 1); 1855 1838 /* laal %w1,%w0,off(%r15) */ ··· 1877 1864 /* 1878 1865 * Restore registers before calling function 1879 1866 */ 1880 - save_restore_regs(jit, REGS_RESTORE, stack_depth, 0); 1867 + save_restore_regs(jit, REGS_RESTORE, 0); 1881 1868 1882 1869 /* 1883 1870 * goto *(prog->bpf_func + tail_call_start); ··· 2170 2157 * Compile eBPF program into s390x code 2171 2158 */ 2172 2159 static int bpf_jit_prog(struct bpf_jit *jit, struct bpf_prog *fp, 2173 - bool extra_pass, u32 stack_depth) 2160 + bool extra_pass) 2174 2161 { 2175 2162 int i, insn_count, lit32_size, lit64_size; 2176 2163 u64 kern_arena; ··· 2179 2166 jit->lit64 = jit->lit64_start; 2180 2167 jit->prg = 0; 2181 2168 jit->excnt = 0; 2169 + if (is_first_pass(jit) || (jit->seen & SEEN_STACK)) 2170 + jit->frame_off = sizeof(struct prog_frame) - 2171 + offsetofend(struct prog_frame, unused) + 2172 + round_up(fp->aux->stack_depth, 8); 2173 + else 2174 + jit->frame_off = 0; 2182 2175 2183 2176 kern_arena = bpf_arena_get_kern_vm_start(fp->aux->arena); 2184 2177 if (kern_arena) 2185 2178 jit->kern_arena = _EMIT_CONST_U64(kern_arena); 2186 2179 jit->user_arena = bpf_arena_get_user_vm_start(fp->aux->arena); 2187 2180 2188 - bpf_jit_prologue(jit, fp, stack_depth); 2181 + bpf_jit_prologue(jit, fp); 2189 2182 if (bpf_set_addr(jit, 0) < 0) 2190 2183 return -1; 2191 2184 for (i = 0; i < fp->len; i += insn_count) { 2192 - insn_count = bpf_jit_insn(jit, fp, i, extra_pass, stack_depth); 2185 + insn_count = bpf_jit_insn(jit, fp, i, extra_pass); 2193 2186 if (insn_count < 0) 2194 2187 return -1; 2195 2188 /* Next instruction address */ 2196 2189 if (bpf_set_addr(jit, i + insn_count) < 0) 2197 2190 return -1; 2198 2191 } 2199 - bpf_jit_epilogue(jit, stack_depth); 2192 + bpf_jit_epilogue(jit); 2200 2193 2201 2194 lit32_size = jit->lit32 - jit->lit32_start; 2202 2195 lit64_size = jit->lit64 - jit->lit64_start; ··· 2278 2259 */ 2279 2260 struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) 2280 2261 { 2281 - u32 stack_depth = round_up(fp->aux->stack_depth, 8); 2282 2262 struct bpf_prog *tmp, *orig_fp = fp; 2283 2263 struct bpf_binary_header *header; 2284 2264 struct s390_jit_data *jit_data; ··· 2330 2312 * - 3: Calculate program size and addrs array 2331 2313 */ 2332 2314 for (pass = 1; pass <= 3; pass++) { 2333 - if (bpf_jit_prog(&jit, fp, extra_pass, stack_depth)) { 2315 + if (bpf_jit_prog(&jit, fp, extra_pass)) { 2334 2316 fp = orig_fp; 2335 2317 goto free_addrs; 2336 2318 } ··· 2344 2326 goto free_addrs; 2345 2327 } 2346 2328 skip_init_ctx: 2347 - if (bpf_jit_prog(&jit, fp, extra_pass, stack_depth)) { 2329 + if (bpf_jit_prog(&jit, fp, extra_pass)) { 2348 2330 bpf_jit_binary_free(header); 2349 2331 fp = orig_fp; 2350 2332 goto free_addrs; ··· 2664 2646 /* stg %r1,backchain_off(%r15) */ 2665 2647 EMIT6_DISP_LH(0xe3000000, 0x0024, REG_1, REG_0, REG_15, 2666 2648 tjit->backchain_off); 2667 - /* mvc tccnt_off(4,%r15),stack_size+STK_OFF_TCCNT(%r15) */ 2649 + /* mvc tccnt_off(4,%r15),stack_size+tail_call_cnt(%r15) */ 2668 2650 _EMIT6(0xd203f000 | tjit->tccnt_off, 2669 - 0xf000 | (tjit->stack_size + STK_OFF_TCCNT)); 2651 + 0xf000 | (tjit->stack_size + 2652 + offsetof(struct prog_frame, tail_call_cnt))); 2670 2653 /* stmg %r2,%rN,fwd_reg_args_off(%r15) */ 2671 2654 if (nr_reg_args) 2672 2655 EMIT6_DISP_LH(0xeb000000, 0x0024, REG_2, ··· 2804 2785 (nr_stack_args * sizeof(u64) - 1) << 16 | 2805 2786 tjit->stack_args_off, 2806 2787 0xf000 | tjit->orig_stack_args_off); 2807 - /* mvc STK_OFF_TCCNT(4,%r15),tccnt_off(%r15) */ 2808 - _EMIT6(0xd203f000 | STK_OFF_TCCNT, 0xf000 | tjit->tccnt_off); 2788 + /* mvc tail_call_cnt(4,%r15),tccnt_off(%r15) */ 2789 + _EMIT6(0xd203f000 | offsetof(struct prog_frame, tail_call_cnt), 2790 + 0xf000 | tjit->tccnt_off); 2809 2791 /* lgr %r1,%r8 */ 2810 2792 EMIT4(0xb9040000, REG_1, REG_8); 2811 2793 /* %r1() */ ··· 2863 2843 if (flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET)) 2864 2844 EMIT6_DISP_LH(0xe3000000, 0x0004, REG_2, REG_0, REG_15, 2865 2845 tjit->retval_off); 2866 - /* mvc stack_size+STK_OFF_TCCNT(4,%r15),tccnt_off(%r15) */ 2867 - _EMIT6(0xd203f000 | (tjit->stack_size + STK_OFF_TCCNT), 2846 + /* mvc stack_size+tail_call_cnt(4,%r15),tccnt_off(%r15) */ 2847 + _EMIT6(0xd203f000 | (tjit->stack_size + 2848 + offsetof(struct prog_frame, tail_call_cnt)), 2868 2849 0xf000 | tjit->tccnt_off); 2869 2850 /* aghi %r15,stack_size */ 2870 2851 EMIT4_IMM(0xa70b0000, REG_15, tjit->stack_size);