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

bpf, s390x: remove ld_abs/ld_ind

Since LD_ABS/LD_IND instructions are now removed from the core and
reimplemented through a combination of inlined BPF instructions and
a slow-path helper, we can get rid of the complexity from s390x JIT.
Tested on s390x instance on LinuxONE.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Cc: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Daniel Borkmann and committed by
Alexei Starovoitov
e1cf4bef dbf44daf

+13 -252
+1 -1
arch/s390/net/Makefile
··· 2 2 # 3 3 # Arch-specific network modules 4 4 # 5 - obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_jit_comp.o 5 + obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o
-116
arch/s390/net/bpf_jit.S
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - /* 3 - * BPF Jit compiler for s390, help functions. 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 - #include <linux/linkage.h> 12 - #include "bpf_jit.h" 13 - 14 - /* 15 - * Calling convention: 16 - * registers %r7-%r10, %r11,%r13, and %r15 are call saved 17 - * 18 - * Input (64 bit): 19 - * %r3 (%b2) = offset into skb data 20 - * %r6 (%b5) = return address 21 - * %r7 (%b6) = skb pointer 22 - * %r12 = skb data pointer 23 - * 24 - * Output: 25 - * %r14= %b0 = return value (read skb value) 26 - * 27 - * Work registers: %r2,%r4,%r5,%r14 28 - * 29 - * skb_copy_bits takes 4 parameters: 30 - * %r2 = skb pointer 31 - * %r3 = offset into skb data 32 - * %r4 = pointer to temp buffer 33 - * %r5 = length to copy 34 - * Return value in %r2: 0 = ok 35 - * 36 - * bpf_internal_load_pointer_neg_helper takes 3 parameters: 37 - * %r2 = skb pointer 38 - * %r3 = offset into data 39 - * %r4 = length to copy 40 - * Return value in %r2: Pointer to data 41 - */ 42 - 43 - #define SKF_MAX_NEG_OFF -0x200000 /* SKF_LL_OFF from filter.h */ 44 - 45 - /* 46 - * Load SIZE bytes from SKB 47 - */ 48 - #define sk_load_common(NAME, SIZE, LOAD) \ 49 - ENTRY(sk_load_##NAME); \ 50 - ltgr %r3,%r3; /* Is offset negative? */ \ 51 - jl sk_load_##NAME##_slow_neg; \ 52 - ENTRY(sk_load_##NAME##_pos); \ 53 - aghi %r3,SIZE; /* Offset + SIZE */ \ 54 - clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \ 55 - jh sk_load_##NAME##_slow; \ 56 - LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \ 57 - b OFF_OK(%r6); /* Return */ \ 58 - \ 59 - sk_load_##NAME##_slow:; \ 60 - lgr %r2,%r7; /* Arg1 = skb pointer */ \ 61 - aghi %r3,-SIZE; /* Arg2 = offset */ \ 62 - la %r4,STK_OFF_TMP(%r15); /* Arg3 = temp bufffer */ \ 63 - lghi %r5,SIZE; /* Arg4 = size */ \ 64 - brasl %r14,skb_copy_bits; /* Get data from skb */ \ 65 - LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \ 66 - ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \ 67 - br %r6; /* Return */ 68 - 69 - sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */ 70 - sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */ 71 - 72 - /* 73 - * Load 1 byte from SKB (optimized version) 74 - */ 75 - /* r14 = *(u8 *) (skb->data+offset) */ 76 - ENTRY(sk_load_byte) 77 - ltgr %r3,%r3 # Is offset negative? 78 - jl sk_load_byte_slow_neg 79 - ENTRY(sk_load_byte_pos) 80 - clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen? 81 - jnl sk_load_byte_slow 82 - llgc %r14,0(%r3,%r12) # Get byte from skb 83 - b OFF_OK(%r6) # Return OK 84 - 85 - sk_load_byte_slow: 86 - lgr %r2,%r7 # Arg1 = skb pointer 87 - # Arg2 = offset 88 - la %r4,STK_OFF_TMP(%r15) # Arg3 = pointer to temp buffer 89 - lghi %r5,1 # Arg4 = size (1 byte) 90 - brasl %r14,skb_copy_bits # Get data from skb 91 - llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer 92 - ltgr %r2,%r2 # Set cc to (%r2 != 0) 93 - br %r6 # Return cc 94 - 95 - #define sk_negative_common(NAME, SIZE, LOAD) \ 96 - sk_load_##NAME##_slow_neg:; \ 97 - cgfi %r3,SKF_MAX_NEG_OFF; \ 98 - jl bpf_error; \ 99 - lgr %r2,%r7; /* Arg1 = skb pointer */ \ 100 - /* Arg2 = offset */ \ 101 - lghi %r4,SIZE; /* Arg3 = size */ \ 102 - brasl %r14,bpf_internal_load_pointer_neg_helper; \ 103 - ltgr %r2,%r2; \ 104 - jz bpf_error; \ 105 - LOAD %r14,0(%r2); /* Get data from pointer */ \ 106 - xr %r3,%r3; /* Set cc to zero */ \ 107 - br %r6; /* Return cc */ 108 - 109 - sk_negative_common(word, 4, llgf) 110 - sk_negative_common(half, 2, llgh) 111 - sk_negative_common(byte, 1, llgc) 112 - 113 - bpf_error: 114 - # force a return 0 from jit handler 115 - ltgr %r15,%r15 # Set condition code 116 - br %r6
+1 -19
arch/s390/net/bpf_jit.h
··· 16 16 #include <linux/filter.h> 17 17 #include <linux/types.h> 18 18 19 - extern u8 sk_load_word_pos[], sk_load_half_pos[], sk_load_byte_pos[]; 20 - extern u8 sk_load_word[], sk_load_half[], sk_load_byte[]; 21 - 22 19 #endif /* __ASSEMBLY__ */ 23 20 24 21 /* ··· 33 36 * | | | 34 37 * | BPF stack | | 35 38 * | | | 36 - * +---------------+ | 37 - * | 8 byte skbp | | 38 - * R15+176 -> +---------------+ | 39 - * | 8 byte hlen | | 40 - * R15+168 -> +---------------+ | 41 - * | 4 byte align | | 42 - * +---------------+ | 43 - * | 4 byte temp | | 44 - * | for bpf_jit.S | | 45 39 * R15+160 -> +---------------+ | 46 40 * | new backchain | | 47 41 * R15+152 -> +---------------+ | ··· 45 57 * The stack size used by the BPF program ("BPF stack" above) is passed 46 58 * via "aux->stack_depth". 47 59 */ 48 - #define STK_SPACE_ADD (8 + 8 + 4 + 4 + 160) 60 + #define STK_SPACE_ADD (160) 49 61 #define STK_160_UNUSED (160 - 12 * 8) 50 62 #define STK_OFF (STK_SPACE_ADD - STK_160_UNUSED) 51 - #define STK_OFF_TMP 160 /* Offset of tmp buffer on stack */ 52 - #define STK_OFF_HLEN 168 /* Offset of SKB header length on stack */ 53 - #define STK_OFF_SKBP 176 /* Offset of SKB pointer on stack */ 54 63 55 64 #define STK_OFF_R6 (160 - 11 * 8) /* Offset of r6 on stack */ 56 65 #define STK_OFF_TCCNT (160 - 12 * 8) /* Offset of tail_call_cnt on stack */ 57 - 58 - /* Offset to skip condition code check */ 59 - #define OFF_OK 4 60 66 61 67 #endif /* __ARCH_S390_NET_BPF_JIT_H */
+11 -116
arch/s390/net/bpf_jit_comp.c
··· 47 47 48 48 #define BPF_SIZE_MAX 0xffff /* Max size for program (16 bit branches) */ 49 49 50 - #define SEEN_SKB 1 /* skb access */ 51 - #define SEEN_MEM 2 /* use mem[] for temporary storage */ 52 - #define SEEN_RET0 4 /* ret0_ip points to a valid return 0 */ 53 - #define SEEN_LITERAL 8 /* code uses literals */ 54 - #define SEEN_FUNC 16 /* calls C functions */ 55 - #define SEEN_TAIL_CALL 32 /* code uses tail calls */ 56 - #define SEEN_REG_AX 64 /* code uses constant blinding */ 57 - #define SEEN_STACK (SEEN_FUNC | SEEN_MEM | SEEN_SKB) 50 + #define SEEN_MEM (1 << 0) /* use mem[] for temporary storage */ 51 + #define SEEN_RET0 (1 << 1) /* ret0_ip points to a valid return 0 */ 52 + #define SEEN_LITERAL (1 << 2) /* code uses literals */ 53 + #define SEEN_FUNC (1 << 3) /* calls C functions */ 54 + #define SEEN_TAIL_CALL (1 << 4) /* code uses tail calls */ 55 + #define SEEN_REG_AX (1 << 5) /* code uses constant blinding */ 56 + #define SEEN_STACK (SEEN_FUNC | SEEN_MEM) 58 57 59 58 /* 60 59 * s390 registers 61 60 */ 62 61 #define REG_W0 (MAX_BPF_JIT_REG + 0) /* Work register 1 (even) */ 63 62 #define REG_W1 (MAX_BPF_JIT_REG + 1) /* Work register 2 (odd) */ 64 - #define REG_SKB_DATA (MAX_BPF_JIT_REG + 2) /* SKB data register */ 65 - #define REG_L (MAX_BPF_JIT_REG + 3) /* Literal pool register */ 66 - #define REG_15 (MAX_BPF_JIT_REG + 4) /* Register 15 */ 63 + #define REG_L (MAX_BPF_JIT_REG + 2) /* Literal pool register */ 64 + #define REG_15 (MAX_BPF_JIT_REG + 3) /* Register 15 */ 67 65 #define REG_0 REG_W0 /* Register 0 */ 68 66 #define REG_1 REG_W1 /* Register 1 */ 69 67 #define REG_2 BPF_REG_1 /* Register 2 */ ··· 86 88 [BPF_REG_9] = 10, 87 89 /* BPF stack pointer */ 88 90 [BPF_REG_FP] = 13, 89 - /* Register for blinding (shared with REG_SKB_DATA) */ 91 + /* Register for blinding */ 90 92 [BPF_REG_AX] = 12, 91 - /* SKB data pointer */ 92 - [REG_SKB_DATA] = 12, 93 93 /* Work registers for s390x backend */ 94 94 [REG_W0] = 0, 95 95 [REG_W1] = 1, ··· 381 385 } 382 386 383 387 /* 384 - * For SKB access %b1 contains the SKB pointer. For "bpf_jit.S" 385 - * we store the SKB header length on the stack and the SKB data 386 - * pointer in REG_SKB_DATA if BPF_REG_AX is not used. 387 - */ 388 - static void emit_load_skb_data_hlen(struct bpf_jit *jit) 389 - { 390 - /* Header length: llgf %w1,<len>(%b1) */ 391 - EMIT6_DISP_LH(0xe3000000, 0x0016, REG_W1, REG_0, BPF_REG_1, 392 - offsetof(struct sk_buff, len)); 393 - /* s %w1,<data_len>(%b1) */ 394 - EMIT4_DISP(0x5b000000, REG_W1, BPF_REG_1, 395 - offsetof(struct sk_buff, data_len)); 396 - /* stg %w1,ST_OFF_HLEN(%r0,%r15) */ 397 - EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, REG_15, STK_OFF_HLEN); 398 - if (!(jit->seen & SEEN_REG_AX)) 399 - /* lg %skb_data,data_off(%b1) */ 400 - EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0, 401 - BPF_REG_1, offsetof(struct sk_buff, data)); 402 - } 403 - 404 - /* 405 388 * Emit function prologue 406 389 * 407 390 * Save registers and create stack frame if necessary. ··· 420 445 EMIT6_DISP_LH(0xe3000000, 0x0024, REG_W1, REG_0, 421 446 REG_15, 152); 422 447 } 423 - if (jit->seen & SEEN_SKB) { 424 - emit_load_skb_data_hlen(jit); 425 - /* stg %b1,ST_OFF_SKBP(%r0,%r15) */ 426 - EMIT6_DISP_LH(0xe3000000, 0x0024, BPF_REG_1, REG_0, REG_15, 427 - STK_OFF_SKBP); 428 - } 429 448 } 430 449 431 450 /* ··· 452 483 { 453 484 struct bpf_insn *insn = &fp->insnsi[i]; 454 485 int jmp_off, last, insn_count = 1; 455 - unsigned int func_addr, mask; 456 486 u32 dst_reg = insn->dst_reg; 457 487 u32 src_reg = insn->src_reg; 458 488 u32 *addrs = jit->addrs; 459 489 s32 imm = insn->imm; 460 490 s16 off = insn->off; 491 + unsigned int mask; 461 492 462 493 if (dst_reg == BPF_REG_AX || src_reg == BPF_REG_AX) 463 494 jit->seen |= SEEN_REG_AX; ··· 939 970 EMIT2(0x0d00, REG_14, REG_W1); 940 971 /* lgr %b0,%r2: load return value into %b0 */ 941 972 EMIT4(0xb9040000, BPF_REG_0, REG_2); 942 - if ((jit->seen & SEEN_SKB) && 943 - bpf_helper_changes_pkt_data((void *)func)) { 944 - /* lg %b1,ST_OFF_SKBP(%r15) */ 945 - EMIT6_DISP_LH(0xe3000000, 0x0004, BPF_REG_1, REG_0, 946 - REG_15, STK_OFF_SKBP); 947 - emit_load_skb_data_hlen(jit); 948 - } 949 973 break; 950 974 } 951 975 case BPF_JMP | BPF_TAIL_CALL: ··· 1137 1175 /* brc mask,jmp_off (branch instruction needs 4 bytes) */ 1138 1176 jmp_off = addrs[i + off + 1] - (addrs[i + 1] - 4); 1139 1177 EMIT4_PCREL(0xa7040000 | mask << 8, jmp_off); 1140 - break; 1141 - /* 1142 - * BPF_LD 1143 - */ 1144 - case BPF_LD | BPF_ABS | BPF_B: /* b0 = *(u8 *) (skb->data+imm) */ 1145 - case BPF_LD | BPF_IND | BPF_B: /* b0 = *(u8 *) (skb->data+imm+src) */ 1146 - if ((BPF_MODE(insn->code) == BPF_ABS) && (imm >= 0)) 1147 - func_addr = __pa(sk_load_byte_pos); 1148 - else 1149 - func_addr = __pa(sk_load_byte); 1150 - goto call_fn; 1151 - case BPF_LD | BPF_ABS | BPF_H: /* b0 = *(u16 *) (skb->data+imm) */ 1152 - case BPF_LD | BPF_IND | BPF_H: /* b0 = *(u16 *) (skb->data+imm+src) */ 1153 - if ((BPF_MODE(insn->code) == BPF_ABS) && (imm >= 0)) 1154 - func_addr = __pa(sk_load_half_pos); 1155 - else 1156 - func_addr = __pa(sk_load_half); 1157 - goto call_fn; 1158 - case BPF_LD | BPF_ABS | BPF_W: /* b0 = *(u32 *) (skb->data+imm) */ 1159 - case BPF_LD | BPF_IND | BPF_W: /* b0 = *(u32 *) (skb->data+imm+src) */ 1160 - if ((BPF_MODE(insn->code) == BPF_ABS) && (imm >= 0)) 1161 - func_addr = __pa(sk_load_word_pos); 1162 - else 1163 - func_addr = __pa(sk_load_word); 1164 - goto call_fn; 1165 - call_fn: 1166 - jit->seen |= SEEN_SKB | SEEN_RET0 | SEEN_FUNC; 1167 - REG_SET_SEEN(REG_14); /* Return address of possible func call */ 1168 - 1169 - /* 1170 - * Implicit input: 1171 - * BPF_REG_6 (R7) : skb pointer 1172 - * REG_SKB_DATA (R12): skb data pointer (if no BPF_REG_AX) 1173 - * 1174 - * Calculated input: 1175 - * BPF_REG_2 (R3) : offset of byte(s) to fetch in skb 1176 - * BPF_REG_5 (R6) : return address 1177 - * 1178 - * Output: 1179 - * BPF_REG_0 (R14): data read from skb 1180 - * 1181 - * Scratch registers (BPF_REG_1-5) 1182 - */ 1183 - 1184 - /* Call function: llilf %w1,func_addr */ 1185 - EMIT6_IMM(0xc00f0000, REG_W1, func_addr); 1186 - 1187 - /* Offset: lgfi %b2,imm */ 1188 - EMIT6_IMM(0xc0010000, BPF_REG_2, imm); 1189 - if (BPF_MODE(insn->code) == BPF_IND) 1190 - /* agfr %b2,%src (%src is s32 here) */ 1191 - EMIT4(0xb9180000, BPF_REG_2, src_reg); 1192 - 1193 - /* Reload REG_SKB_DATA if BPF_REG_AX is used */ 1194 - if (jit->seen & SEEN_REG_AX) 1195 - /* lg %skb_data,data_off(%b6) */ 1196 - EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0, 1197 - BPF_REG_6, offsetof(struct sk_buff, data)); 1198 - /* basr %b5,%w1 (%b5 is call saved) */ 1199 - EMIT2(0x0d00, BPF_REG_5, REG_W1); 1200 - 1201 - /* 1202 - * Note: For fast access we jump directly after the 1203 - * jnz instruction from bpf_jit.S 1204 - */ 1205 - /* jnz <ret0> */ 1206 - EMIT4_PCREL(0xa7740000, jit->ret0_ip - jit->prg); 1207 1178 break; 1208 1179 default: /* too complex, give up */ 1209 1180 pr_err("Unknown opcode %02x\n", insn->code);