diff options
-rw-r--r-- | arch/mips/include/asm/uasm.h | 1 | ||||
-rw-r--r-- | arch/mips/include/uapi/asm/inst.h | 1 | ||||
-rw-r--r-- | arch/mips/mm/uasm-micromips.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/uasm-mips.c | 1 | ||||
-rw-r--r-- | arch/mips/mm/uasm.c | 9 | ||||
-rw-r--r-- | arch/mips/net/ebpf_jit.c | 4 | ||||
-rw-r--r-- | arch/powerpc/include/asm/ppc-opcode.h | 2 | ||||
-rw-r--r-- | arch/powerpc/net/bpf_jit.h | 4 | ||||
-rw-r--r-- | arch/powerpc/net/bpf_jit_comp64.c | 6 | ||||
-rw-r--r-- | arch/s390/net/bpf_jit_comp.c | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/netronome/nfp/bpf/jit.c | 45 | ||||
-rw-r--r-- | kernel/bpf/core.c | 52 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 5 | ||||
-rw-r--r-- | tools/testing/selftests/bpf/test_verifier.c | 29 |
14 files changed, 137 insertions, 35 deletions
diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 59dae37f6b8d..b1990dd75f27 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h | |||
@@ -157,6 +157,7 @@ Ip_u2u1s3(_slti); | |||
157 | Ip_u2u1s3(_sltiu); | 157 | Ip_u2u1s3(_sltiu); |
158 | Ip_u3u1u2(_sltu); | 158 | Ip_u3u1u2(_sltu); |
159 | Ip_u2u1u3(_sra); | 159 | Ip_u2u1u3(_sra); |
160 | Ip_u3u2u1(_srav); | ||
160 | Ip_u2u1u3(_srl); | 161 | Ip_u2u1u3(_srl); |
161 | Ip_u3u2u1(_srlv); | 162 | Ip_u3u2u1(_srlv); |
162 | Ip_u3u1u2(_subu); | 163 | Ip_u3u1u2(_subu); |
diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h index 273ef58f4d43..40fbb5dd66df 100644 --- a/arch/mips/include/uapi/asm/inst.h +++ b/arch/mips/include/uapi/asm/inst.h | |||
@@ -371,6 +371,7 @@ enum mm_32a_minor_op { | |||
371 | mm_srl32_op = 0x040, | 371 | mm_srl32_op = 0x040, |
372 | mm_srlv32_op = 0x050, | 372 | mm_srlv32_op = 0x050, |
373 | mm_sra_op = 0x080, | 373 | mm_sra_op = 0x080, |
374 | mm_srav_op = 0x090, | ||
374 | mm_rotr_op = 0x0c0, | 375 | mm_rotr_op = 0x0c0, |
375 | mm_lwxs_op = 0x118, | 376 | mm_lwxs_op = 0x118, |
376 | mm_addu32_op = 0x150, | 377 | mm_addu32_op = 0x150, |
diff --git a/arch/mips/mm/uasm-micromips.c b/arch/mips/mm/uasm-micromips.c index 24e5b0d06899..75ef90486fe6 100644 --- a/arch/mips/mm/uasm-micromips.c +++ b/arch/mips/mm/uasm-micromips.c | |||
@@ -104,6 +104,7 @@ static const struct insn insn_table_MM[insn_invalid] = { | |||
104 | [insn_sltiu] = {M(mm_sltiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM}, | 104 | [insn_sltiu] = {M(mm_sltiu32_op, 0, 0, 0, 0, 0), RT | RS | SIMM}, |
105 | [insn_sltu] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_sltu_op), RT | RS | RD}, | 105 | [insn_sltu] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_sltu_op), RT | RS | RD}, |
106 | [insn_sra] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD}, | 106 | [insn_sra] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_sra_op), RT | RS | RD}, |
107 | [insn_srav] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_srav_op), RT | RS | RD}, | ||
107 | [insn_srl] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD}, | 108 | [insn_srl] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_srl32_op), RT | RS | RD}, |
108 | [insn_srlv] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_srlv32_op), RT | RS | RD}, | 109 | [insn_srlv] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_srlv32_op), RT | RS | RD}, |
109 | [insn_rotr] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD}, | 110 | [insn_rotr] = {M(mm_pool32a_op, 0, 0, 0, 0, mm_rotr_op), RT | RS | RD}, |
diff --git a/arch/mips/mm/uasm-mips.c b/arch/mips/mm/uasm-mips.c index 60ceb93c71a0..6abe40fc413d 100644 --- a/arch/mips/mm/uasm-mips.c +++ b/arch/mips/mm/uasm-mips.c | |||
@@ -171,6 +171,7 @@ static const struct insn insn_table[insn_invalid] = { | |||
171 | [insn_sltiu] = {M(sltiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM}, | 171 | [insn_sltiu] = {M(sltiu_op, 0, 0, 0, 0, 0), RS | RT | SIMM}, |
172 | [insn_sltu] = {M(spec_op, 0, 0, 0, 0, sltu_op), RS | RT | RD}, | 172 | [insn_sltu] = {M(spec_op, 0, 0, 0, 0, sltu_op), RS | RT | RD}, |
173 | [insn_sra] = {M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE}, | 173 | [insn_sra] = {M(spec_op, 0, 0, 0, 0, sra_op), RT | RD | RE}, |
174 | [insn_srav] = {M(spec_op, 0, 0, 0, 0, srav_op), RS | RT | RD}, | ||
174 | [insn_srl] = {M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE}, | 175 | [insn_srl] = {M(spec_op, 0, 0, 0, 0, srl_op), RT | RD | RE}, |
175 | [insn_srlv] = {M(spec_op, 0, 0, 0, 0, srlv_op), RS | RT | RD}, | 176 | [insn_srlv] = {M(spec_op, 0, 0, 0, 0, srlv_op), RS | RT | RD}, |
176 | [insn_subu] = {M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD}, | 177 | [insn_subu] = {M(spec_op, 0, 0, 0, 0, subu_op), RS | RT | RD}, |
diff --git a/arch/mips/mm/uasm.c b/arch/mips/mm/uasm.c index 57570c0649b4..45b6264ff308 100644 --- a/arch/mips/mm/uasm.c +++ b/arch/mips/mm/uasm.c | |||
@@ -61,10 +61,10 @@ enum opcode { | |||
61 | insn_mthc0, insn_mthi, insn_mtlo, insn_mul, insn_multu, insn_nor, | 61 | insn_mthc0, insn_mthi, insn_mtlo, insn_mul, insn_multu, insn_nor, |
62 | insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sb, | 62 | insn_or, insn_ori, insn_pref, insn_rfe, insn_rotr, insn_sb, |
63 | insn_sc, insn_scd, insn_sd, insn_sh, insn_sll, insn_sllv, | 63 | insn_sc, insn_scd, insn_sd, insn_sh, insn_sll, insn_sllv, |
64 | insn_slt, insn_slti, insn_sltiu, insn_sltu, insn_sra, insn_srl, | 64 | insn_slt, insn_slti, insn_sltiu, insn_sltu, insn_sra, insn_srav, |
65 | insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp, | 65 | insn_srl, insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, |
66 | insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh, insn_xor, | 66 | insn_tlbp, insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh, |
67 | insn_xori, insn_yield, | 67 | insn_xor, insn_xori, insn_yield, |
68 | insn_invalid /* insn_invalid must be last */ | 68 | insn_invalid /* insn_invalid must be last */ |
69 | }; | 69 | }; |
70 | 70 | ||
@@ -353,6 +353,7 @@ I_u2u1s3(_slti) | |||
353 | I_u2u1s3(_sltiu) | 353 | I_u2u1s3(_sltiu) |
354 | I_u3u1u2(_sltu) | 354 | I_u3u1u2(_sltu) |
355 | I_u2u1u3(_sra) | 355 | I_u2u1u3(_sra) |
356 | I_u3u2u1(_srav) | ||
356 | I_u2u1u3(_srl) | 357 | I_u2u1u3(_srl) |
357 | I_u3u2u1(_srlv) | 358 | I_u3u2u1(_srlv) |
358 | I_u2u1u3(_rotr) | 359 | I_u2u1u3(_rotr) |
diff --git a/arch/mips/net/ebpf_jit.c b/arch/mips/net/ebpf_jit.c index aeb7b1b0f202..b16710a8a9e7 100644 --- a/arch/mips/net/ebpf_jit.c +++ b/arch/mips/net/ebpf_jit.c | |||
@@ -854,6 +854,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, | |||
854 | case BPF_ALU | BPF_MOD | BPF_X: /* ALU_REG */ | 854 | case BPF_ALU | BPF_MOD | BPF_X: /* ALU_REG */ |
855 | case BPF_ALU | BPF_LSH | BPF_X: /* ALU_REG */ | 855 | case BPF_ALU | BPF_LSH | BPF_X: /* ALU_REG */ |
856 | case BPF_ALU | BPF_RSH | BPF_X: /* ALU_REG */ | 856 | case BPF_ALU | BPF_RSH | BPF_X: /* ALU_REG */ |
857 | case BPF_ALU | BPF_ARSH | BPF_X: /* ALU_REG */ | ||
857 | src = ebpf_to_mips_reg(ctx, insn, src_reg_no_fp); | 858 | src = ebpf_to_mips_reg(ctx, insn, src_reg_no_fp); |
858 | dst = ebpf_to_mips_reg(ctx, insn, dst_reg); | 859 | dst = ebpf_to_mips_reg(ctx, insn, dst_reg); |
859 | if (src < 0 || dst < 0) | 860 | if (src < 0 || dst < 0) |
@@ -913,6 +914,9 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, | |||
913 | case BPF_RSH: | 914 | case BPF_RSH: |
914 | emit_instr(ctx, srlv, dst, dst, src); | 915 | emit_instr(ctx, srlv, dst, dst, src); |
915 | break; | 916 | break; |
917 | case BPF_ARSH: | ||
918 | emit_instr(ctx, srav, dst, dst, src); | ||
919 | break; | ||
916 | default: | 920 | default: |
917 | pr_err("ALU_REG NOT HANDLED\n"); | 921 | pr_err("ALU_REG NOT HANDLED\n"); |
918 | return -EINVAL; | 922 | return -EINVAL; |
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index a6e9e314c707..901459226eca 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
@@ -342,6 +342,8 @@ | |||
342 | #define PPC_INST_SLW 0x7c000030 | 342 | #define PPC_INST_SLW 0x7c000030 |
343 | #define PPC_INST_SLD 0x7c000036 | 343 | #define PPC_INST_SLD 0x7c000036 |
344 | #define PPC_INST_SRW 0x7c000430 | 344 | #define PPC_INST_SRW 0x7c000430 |
345 | #define PPC_INST_SRAW 0x7c000630 | ||
346 | #define PPC_INST_SRAWI 0x7c000670 | ||
345 | #define PPC_INST_SRD 0x7c000436 | 347 | #define PPC_INST_SRD 0x7c000436 |
346 | #define PPC_INST_SRAD 0x7c000634 | 348 | #define PPC_INST_SRAD 0x7c000634 |
347 | #define PPC_INST_SRADI 0x7c000674 | 349 | #define PPC_INST_SRADI 0x7c000674 |
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index 47fc6660845d..c2d5192ed64f 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h | |||
@@ -152,6 +152,10 @@ | |||
152 | ___PPC_RS(a) | ___PPC_RB(s)) | 152 | ___PPC_RS(a) | ___PPC_RB(s)) |
153 | #define PPC_SRW(d, a, s) EMIT(PPC_INST_SRW | ___PPC_RA(d) | \ | 153 | #define PPC_SRW(d, a, s) EMIT(PPC_INST_SRW | ___PPC_RA(d) | \ |
154 | ___PPC_RS(a) | ___PPC_RB(s)) | 154 | ___PPC_RS(a) | ___PPC_RB(s)) |
155 | #define PPC_SRAW(d, a, s) EMIT(PPC_INST_SRAW | ___PPC_RA(d) | \ | ||
156 | ___PPC_RS(a) | ___PPC_RB(s)) | ||
157 | #define PPC_SRAWI(d, a, i) EMIT(PPC_INST_SRAWI | ___PPC_RA(d) | \ | ||
158 | ___PPC_RS(a) | __PPC_SH(i)) | ||
155 | #define PPC_SRD(d, a, s) EMIT(PPC_INST_SRD | ___PPC_RA(d) | \ | 159 | #define PPC_SRD(d, a, s) EMIT(PPC_INST_SRD | ___PPC_RA(d) | \ |
156 | ___PPC_RS(a) | ___PPC_RB(s)) | 160 | ___PPC_RS(a) | ___PPC_RB(s)) |
157 | #define PPC_SRAD(d, a, s) EMIT(PPC_INST_SRAD | ___PPC_RA(d) | \ | 161 | #define PPC_SRAD(d, a, s) EMIT(PPC_INST_SRAD | ___PPC_RA(d) | \ |
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 17482f5de3e2..7dc81877057d 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c | |||
@@ -529,9 +529,15 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, | |||
529 | if (imm != 0) | 529 | if (imm != 0) |
530 | PPC_SRDI(dst_reg, dst_reg, imm); | 530 | PPC_SRDI(dst_reg, dst_reg, imm); |
531 | break; | 531 | break; |
532 | case BPF_ALU | BPF_ARSH | BPF_X: /* (s32) dst >>= src */ | ||
533 | PPC_SRAW(dst_reg, dst_reg, src_reg); | ||
534 | goto bpf_alu32_trunc; | ||
532 | case BPF_ALU64 | BPF_ARSH | BPF_X: /* (s64) dst >>= src */ | 535 | case BPF_ALU64 | BPF_ARSH | BPF_X: /* (s64) dst >>= src */ |
533 | PPC_SRAD(dst_reg, dst_reg, src_reg); | 536 | PPC_SRAD(dst_reg, dst_reg, src_reg); |
534 | break; | 537 | break; |
538 | case BPF_ALU | BPF_ARSH | BPF_K: /* (s32) dst >>= imm */ | ||
539 | PPC_SRAWI(dst_reg, dst_reg, imm); | ||
540 | goto bpf_alu32_trunc; | ||
535 | case BPF_ALU64 | BPF_ARSH | BPF_K: /* (s64) dst >>= imm */ | 541 | case BPF_ALU64 | BPF_ARSH | BPF_K: /* (s64) dst >>= imm */ |
536 | if (imm != 0) | 542 | if (imm != 0) |
537 | PPC_SRADI(dst_reg, dst_reg, imm); | 543 | PPC_SRADI(dst_reg, dst_reg, imm); |
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index d7052cbe984f..3ff758eeb71d 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c | |||
@@ -821,10 +821,22 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, int i | |||
821 | /* | 821 | /* |
822 | * BPF_ARSH | 822 | * BPF_ARSH |
823 | */ | 823 | */ |
824 | case BPF_ALU | BPF_ARSH | BPF_X: /* ((s32) dst) >>= src */ | ||
825 | /* sra %dst,%dst,0(%src) */ | ||
826 | EMIT4_DISP(0x8a000000, dst_reg, src_reg, 0); | ||
827 | EMIT_ZERO(dst_reg); | ||
828 | break; | ||
824 | case BPF_ALU64 | BPF_ARSH | BPF_X: /* ((s64) dst) >>= src */ | 829 | case BPF_ALU64 | BPF_ARSH | BPF_X: /* ((s64) dst) >>= src */ |
825 | /* srag %dst,%dst,0(%src) */ | 830 | /* srag %dst,%dst,0(%src) */ |
826 | EMIT6_DISP_LH(0xeb000000, 0x000a, dst_reg, dst_reg, src_reg, 0); | 831 | EMIT6_DISP_LH(0xeb000000, 0x000a, dst_reg, dst_reg, src_reg, 0); |
827 | break; | 832 | break; |
833 | case BPF_ALU | BPF_ARSH | BPF_K: /* ((s32) dst >> imm */ | ||
834 | if (imm == 0) | ||
835 | break; | ||
836 | /* sra %dst,imm(%r0) */ | ||
837 | EMIT4_DISP(0x8a000000, dst_reg, REG_0, imm); | ||
838 | EMIT_ZERO(dst_reg); | ||
839 | break; | ||
828 | case BPF_ALU64 | BPF_ARSH | BPF_K: /* ((s64) dst) >>= imm */ | 840 | case BPF_ALU64 | BPF_ARSH | BPF_K: /* ((s64) dst) >>= imm */ |
829 | if (imm == 0) | 841 | if (imm == 0) |
830 | break; | 842 | break; |
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c index 97d33bb4d84d..662cbc21d909 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c | |||
@@ -2382,6 +2382,49 @@ static int neg_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) | |||
2382 | return 0; | 2382 | return 0; |
2383 | } | 2383 | } |
2384 | 2384 | ||
2385 | static int __ashr_imm(struct nfp_prog *nfp_prog, u8 dst, u8 shift_amt) | ||
2386 | { | ||
2387 | /* Set signedness bit (MSB of result). */ | ||
2388 | emit_alu(nfp_prog, reg_none(), reg_a(dst), ALU_OP_OR, reg_imm(0)); | ||
2389 | emit_shf(nfp_prog, reg_both(dst), reg_none(), SHF_OP_ASHR, reg_b(dst), | ||
2390 | SHF_SC_R_SHF, shift_amt); | ||
2391 | wrp_immed(nfp_prog, reg_both(dst + 1), 0); | ||
2392 | |||
2393 | return 0; | ||
2394 | } | ||
2395 | |||
2396 | static int ashr_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) | ||
2397 | { | ||
2398 | const struct bpf_insn *insn = &meta->insn; | ||
2399 | u64 umin, umax; | ||
2400 | u8 dst, src; | ||
2401 | |||
2402 | dst = insn->dst_reg * 2; | ||
2403 | umin = meta->umin_src; | ||
2404 | umax = meta->umax_src; | ||
2405 | if (umin == umax) | ||
2406 | return __ashr_imm(nfp_prog, dst, umin); | ||
2407 | |||
2408 | src = insn->src_reg * 2; | ||
2409 | /* NOTE: the first insn will set both indirect shift amount (source A) | ||
2410 | * and signedness bit (MSB of result). | ||
2411 | */ | ||
2412 | emit_alu(nfp_prog, reg_none(), reg_a(src), ALU_OP_OR, reg_b(dst)); | ||
2413 | emit_shf_indir(nfp_prog, reg_both(dst), reg_none(), SHF_OP_ASHR, | ||
2414 | reg_b(dst), SHF_SC_R_SHF); | ||
2415 | wrp_immed(nfp_prog, reg_both(dst + 1), 0); | ||
2416 | |||
2417 | return 0; | ||
2418 | } | ||
2419 | |||
2420 | static int ashr_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) | ||
2421 | { | ||
2422 | const struct bpf_insn *insn = &meta->insn; | ||
2423 | u8 dst = insn->dst_reg * 2; | ||
2424 | |||
2425 | return __ashr_imm(nfp_prog, dst, insn->imm); | ||
2426 | } | ||
2427 | |||
2385 | static int shl_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) | 2428 | static int shl_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta) |
2386 | { | 2429 | { |
2387 | const struct bpf_insn *insn = &meta->insn; | 2430 | const struct bpf_insn *insn = &meta->insn; |
@@ -3286,6 +3329,8 @@ static const instr_cb_t instr_cb[256] = { | |||
3286 | [BPF_ALU | BPF_DIV | BPF_K] = div_imm, | 3329 | [BPF_ALU | BPF_DIV | BPF_K] = div_imm, |
3287 | [BPF_ALU | BPF_NEG] = neg_reg, | 3330 | [BPF_ALU | BPF_NEG] = neg_reg, |
3288 | [BPF_ALU | BPF_LSH | BPF_K] = shl_imm, | 3331 | [BPF_ALU | BPF_LSH | BPF_K] = shl_imm, |
3332 | [BPF_ALU | BPF_ARSH | BPF_X] = ashr_reg, | ||
3333 | [BPF_ALU | BPF_ARSH | BPF_K] = ashr_imm, | ||
3289 | [BPF_ALU | BPF_END | BPF_X] = end_reg32, | 3334 | [BPF_ALU | BPF_END | BPF_X] = end_reg32, |
3290 | [BPF_LD | BPF_IMM | BPF_DW] = imm_ld8, | 3335 | [BPF_LD | BPF_IMM | BPF_DW] = imm_ld8, |
3291 | [BPF_LD | BPF_ABS | BPF_B] = data_ld1, | 3336 | [BPF_LD | BPF_ABS | BPF_B] = data_ld1, |
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 628b3970a49b..a5b223ef7131 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c | |||
@@ -933,32 +933,34 @@ EXPORT_SYMBOL_GPL(__bpf_call_base); | |||
933 | #define BPF_INSN_MAP(INSN_2, INSN_3) \ | 933 | #define BPF_INSN_MAP(INSN_2, INSN_3) \ |
934 | /* 32 bit ALU operations. */ \ | 934 | /* 32 bit ALU operations. */ \ |
935 | /* Register based. */ \ | 935 | /* Register based. */ \ |
936 | INSN_3(ALU, ADD, X), \ | 936 | INSN_3(ALU, ADD, X), \ |
937 | INSN_3(ALU, SUB, X), \ | 937 | INSN_3(ALU, SUB, X), \ |
938 | INSN_3(ALU, AND, X), \ | 938 | INSN_3(ALU, AND, X), \ |
939 | INSN_3(ALU, OR, X), \ | 939 | INSN_3(ALU, OR, X), \ |
940 | INSN_3(ALU, LSH, X), \ | 940 | INSN_3(ALU, LSH, X), \ |
941 | INSN_3(ALU, RSH, X), \ | 941 | INSN_3(ALU, RSH, X), \ |
942 | INSN_3(ALU, XOR, X), \ | 942 | INSN_3(ALU, XOR, X), \ |
943 | INSN_3(ALU, MUL, X), \ | 943 | INSN_3(ALU, MUL, X), \ |
944 | INSN_3(ALU, MOV, X), \ | 944 | INSN_3(ALU, MOV, X), \ |
945 | INSN_3(ALU, DIV, X), \ | 945 | INSN_3(ALU, ARSH, X), \ |
946 | INSN_3(ALU, MOD, X), \ | 946 | INSN_3(ALU, DIV, X), \ |
947 | INSN_3(ALU, MOD, X), \ | ||
947 | INSN_2(ALU, NEG), \ | 948 | INSN_2(ALU, NEG), \ |
948 | INSN_3(ALU, END, TO_BE), \ | 949 | INSN_3(ALU, END, TO_BE), \ |
949 | INSN_3(ALU, END, TO_LE), \ | 950 | INSN_3(ALU, END, TO_LE), \ |
950 | /* Immediate based. */ \ | 951 | /* Immediate based. */ \ |
951 | INSN_3(ALU, ADD, K), \ | 952 | INSN_3(ALU, ADD, K), \ |
952 | INSN_3(ALU, SUB, K), \ | 953 | INSN_3(ALU, SUB, K), \ |
953 | INSN_3(ALU, AND, K), \ | 954 | INSN_3(ALU, AND, K), \ |
954 | INSN_3(ALU, OR, K), \ | 955 | INSN_3(ALU, OR, K), \ |
955 | INSN_3(ALU, LSH, K), \ | 956 | INSN_3(ALU, LSH, K), \ |
956 | INSN_3(ALU, RSH, K), \ | 957 | INSN_3(ALU, RSH, K), \ |
957 | INSN_3(ALU, XOR, K), \ | 958 | INSN_3(ALU, XOR, K), \ |
958 | INSN_3(ALU, MUL, K), \ | 959 | INSN_3(ALU, MUL, K), \ |
959 | INSN_3(ALU, MOV, K), \ | 960 | INSN_3(ALU, MOV, K), \ |
960 | INSN_3(ALU, DIV, K), \ | 961 | INSN_3(ALU, ARSH, K), \ |
961 | INSN_3(ALU, MOD, K), \ | 962 | INSN_3(ALU, DIV, K), \ |
963 | INSN_3(ALU, MOD, K), \ | ||
962 | /* 64 bit ALU operations. */ \ | 964 | /* 64 bit ALU operations. */ \ |
963 | /* Register based. */ \ | 965 | /* Register based. */ \ |
964 | INSN_3(ALU64, ADD, X), \ | 966 | INSN_3(ALU64, ADD, X), \ |
@@ -1137,6 +1139,12 @@ select_insn: | |||
1137 | DST = (u64) (u32) insn[0].imm | ((u64) (u32) insn[1].imm) << 32; | 1139 | DST = (u64) (u32) insn[0].imm | ((u64) (u32) insn[1].imm) << 32; |
1138 | insn++; | 1140 | insn++; |
1139 | CONT; | 1141 | CONT; |
1142 | ALU_ARSH_X: | ||
1143 | DST = (u64) (u32) ((*(s32 *) &DST) >> SRC); | ||
1144 | CONT; | ||
1145 | ALU_ARSH_K: | ||
1146 | DST = (u64) (u32) ((*(s32 *) &DST) >> IMM); | ||
1147 | CONT; | ||
1140 | ALU64_ARSH_X: | 1148 | ALU64_ARSH_X: |
1141 | (*(s64 *) &DST) >>= SRC; | 1149 | (*(s64 *) &DST) >>= SRC; |
1142 | CONT; | 1150 | CONT; |
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 7658c61c1a88..2752d35ad073 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c | |||
@@ -3649,11 +3649,6 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn) | |||
3649 | return -EINVAL; | 3649 | return -EINVAL; |
3650 | } | 3650 | } |
3651 | 3651 | ||
3652 | if (opcode == BPF_ARSH && BPF_CLASS(insn->code) != BPF_ALU64) { | ||
3653 | verbose(env, "BPF_ARSH not supported for 32 bit ALU\n"); | ||
3654 | return -EINVAL; | ||
3655 | } | ||
3656 | |||
3657 | if ((opcode == BPF_LSH || opcode == BPF_RSH || | 3652 | if ((opcode == BPF_LSH || opcode == BPF_RSH || |
3658 | opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) { | 3653 | opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) { |
3659 | int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32; | 3654 | int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32; |
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c index b4b4a3f93639..36ce58b4933e 100644 --- a/tools/testing/selftests/bpf/test_verifier.c +++ b/tools/testing/selftests/bpf/test_verifier.c | |||
@@ -721,8 +721,18 @@ static struct bpf_test tests[] = { | |||
721 | BPF_ALU32_IMM(BPF_ARSH, BPF_REG_0, 5), | 721 | BPF_ALU32_IMM(BPF_ARSH, BPF_REG_0, 5), |
722 | BPF_EXIT_INSN(), | 722 | BPF_EXIT_INSN(), |
723 | }, | 723 | }, |
724 | .result = REJECT, | 724 | .result = ACCEPT, |
725 | .errstr = "unknown opcode c4", | 725 | .retval = 0, |
726 | }, | ||
727 | { | ||
728 | "arsh32 on imm 2", | ||
729 | .insns = { | ||
730 | BPF_LD_IMM64(BPF_REG_0, 0x1122334485667788), | ||
731 | BPF_ALU32_IMM(BPF_ARSH, BPF_REG_0, 7), | ||
732 | BPF_EXIT_INSN(), | ||
733 | }, | ||
734 | .result = ACCEPT, | ||
735 | .retval = -16069393, | ||
726 | }, | 736 | }, |
727 | { | 737 | { |
728 | "arsh32 on reg", | 738 | "arsh32 on reg", |
@@ -732,8 +742,19 @@ static struct bpf_test tests[] = { | |||
732 | BPF_ALU32_REG(BPF_ARSH, BPF_REG_0, BPF_REG_1), | 742 | BPF_ALU32_REG(BPF_ARSH, BPF_REG_0, BPF_REG_1), |
733 | BPF_EXIT_INSN(), | 743 | BPF_EXIT_INSN(), |
734 | }, | 744 | }, |
735 | .result = REJECT, | 745 | .result = ACCEPT, |
736 | .errstr = "unknown opcode cc", | 746 | .retval = 0, |
747 | }, | ||
748 | { | ||
749 | "arsh32 on reg 2", | ||
750 | .insns = { | ||
751 | BPF_LD_IMM64(BPF_REG_0, 0xffff55667788), | ||
752 | BPF_MOV64_IMM(BPF_REG_1, 15), | ||
753 | BPF_ALU32_REG(BPF_ARSH, BPF_REG_0, BPF_REG_1), | ||
754 | BPF_EXIT_INSN(), | ||
755 | }, | ||
756 | .result = ACCEPT, | ||
757 | .retval = 43724, | ||
737 | }, | 758 | }, |
738 | { | 759 | { |
739 | "arsh64 on imm", | 760 | "arsh64 on imm", |