aboutsummaryrefslogtreecommitdiffstats
path: root/arch/riscv/net
diff options
context:
space:
mode:
authorLuke Nelson <luke.r.nels@gmail.com>2019-05-30 18:29:22 -0400
committerAlexei Starovoitov <ast@kernel.org>2019-05-31 20:08:53 -0400
commit1e692f09e091bf5c8b38384f297d6dae5dbf0f12 (patch)
treebd39ab619e1c156b8a8b6701527ba6b472dc3748 /arch/riscv/net
parentcfd4921049269ee6765b4a1cb820b95d0df5dda5 (diff)
bpf, riscv: clear high 32 bits for ALU32 add/sub/neg/lsh/rsh/arsh
In BPF, 32-bit ALU operations should zero-extend their results into the 64-bit registers. The current BPF JIT on RISC-V emits incorrect instructions that perform sign extension only (e.g., addw, subw) on 32-bit add, sub, lsh, rsh, arsh, and neg. This behavior diverges from the interpreter and JITs for other architectures. This patch fixes the bugs by performing zero extension on the destination register of 32-bit ALU operations. Fixes: 2353ecc6f91f ("bpf, riscv: add BPF JIT for RV64G") Cc: Xi Wang <xi.wang@gmail.com> Signed-off-by: Luke Nelson <luke.r.nels@gmail.com> Acked-by: Song Liu <songliubraving@fb.com> Acked-by: Björn Töpel <bjorn.topel@gmail.com> Reviewed-by: Palmer Dabbelt <palmer@sifive.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'arch/riscv/net')
-rw-r--r--arch/riscv/net/bpf_jit_comp.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/arch/riscv/net/bpf_jit_comp.c b/arch/riscv/net/bpf_jit_comp.c
index e5c8d675bd6e..426d5c33ea90 100644
--- a/arch/riscv/net/bpf_jit_comp.c
+++ b/arch/riscv/net/bpf_jit_comp.c
@@ -751,10 +751,14 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
751 case BPF_ALU | BPF_ADD | BPF_X: 751 case BPF_ALU | BPF_ADD | BPF_X:
752 case BPF_ALU64 | BPF_ADD | BPF_X: 752 case BPF_ALU64 | BPF_ADD | BPF_X:
753 emit(is64 ? rv_add(rd, rd, rs) : rv_addw(rd, rd, rs), ctx); 753 emit(is64 ? rv_add(rd, rd, rs) : rv_addw(rd, rd, rs), ctx);
754 if (!is64)
755 emit_zext_32(rd, ctx);
754 break; 756 break;
755 case BPF_ALU | BPF_SUB | BPF_X: 757 case BPF_ALU | BPF_SUB | BPF_X:
756 case BPF_ALU64 | BPF_SUB | BPF_X: 758 case BPF_ALU64 | BPF_SUB | BPF_X:
757 emit(is64 ? rv_sub(rd, rd, rs) : rv_subw(rd, rd, rs), ctx); 759 emit(is64 ? rv_sub(rd, rd, rs) : rv_subw(rd, rd, rs), ctx);
760 if (!is64)
761 emit_zext_32(rd, ctx);
758 break; 762 break;
759 case BPF_ALU | BPF_AND | BPF_X: 763 case BPF_ALU | BPF_AND | BPF_X:
760 case BPF_ALU64 | BPF_AND | BPF_X: 764 case BPF_ALU64 | BPF_AND | BPF_X:
@@ -795,14 +799,20 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
795 case BPF_ALU | BPF_LSH | BPF_X: 799 case BPF_ALU | BPF_LSH | BPF_X:
796 case BPF_ALU64 | BPF_LSH | BPF_X: 800 case BPF_ALU64 | BPF_LSH | BPF_X:
797 emit(is64 ? rv_sll(rd, rd, rs) : rv_sllw(rd, rd, rs), ctx); 801 emit(is64 ? rv_sll(rd, rd, rs) : rv_sllw(rd, rd, rs), ctx);
802 if (!is64)
803 emit_zext_32(rd, ctx);
798 break; 804 break;
799 case BPF_ALU | BPF_RSH | BPF_X: 805 case BPF_ALU | BPF_RSH | BPF_X:
800 case BPF_ALU64 | BPF_RSH | BPF_X: 806 case BPF_ALU64 | BPF_RSH | BPF_X:
801 emit(is64 ? rv_srl(rd, rd, rs) : rv_srlw(rd, rd, rs), ctx); 807 emit(is64 ? rv_srl(rd, rd, rs) : rv_srlw(rd, rd, rs), ctx);
808 if (!is64)
809 emit_zext_32(rd, ctx);
802 break; 810 break;
803 case BPF_ALU | BPF_ARSH | BPF_X: 811 case BPF_ALU | BPF_ARSH | BPF_X:
804 case BPF_ALU64 | BPF_ARSH | BPF_X: 812 case BPF_ALU64 | BPF_ARSH | BPF_X:
805 emit(is64 ? rv_sra(rd, rd, rs) : rv_sraw(rd, rd, rs), ctx); 813 emit(is64 ? rv_sra(rd, rd, rs) : rv_sraw(rd, rd, rs), ctx);
814 if (!is64)
815 emit_zext_32(rd, ctx);
806 break; 816 break;
807 817
808 /* dst = -dst */ 818 /* dst = -dst */
@@ -810,6 +820,8 @@ static int emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
810 case BPF_ALU64 | BPF_NEG: 820 case BPF_ALU64 | BPF_NEG:
811 emit(is64 ? rv_sub(rd, RV_REG_ZERO, rd) : 821 emit(is64 ? rv_sub(rd, RV_REG_ZERO, rd) :
812 rv_subw(rd, RV_REG_ZERO, rd), ctx); 822 rv_subw(rd, RV_REG_ZERO, rd), ctx);
823 if (!is64)
824 emit_zext_32(rd, ctx);
813 break; 825 break;
814 826
815 /* dst = BSWAP##imm(dst) */ 827 /* dst = BSWAP##imm(dst) */
@@ -964,14 +976,20 @@ out_be:
964 case BPF_ALU | BPF_LSH | BPF_K: 976 case BPF_ALU | BPF_LSH | BPF_K:
965 case BPF_ALU64 | BPF_LSH | BPF_K: 977 case BPF_ALU64 | BPF_LSH | BPF_K:
966 emit(is64 ? rv_slli(rd, rd, imm) : rv_slliw(rd, rd, imm), ctx); 978 emit(is64 ? rv_slli(rd, rd, imm) : rv_slliw(rd, rd, imm), ctx);
979 if (!is64)
980 emit_zext_32(rd, ctx);
967 break; 981 break;
968 case BPF_ALU | BPF_RSH | BPF_K: 982 case BPF_ALU | BPF_RSH | BPF_K:
969 case BPF_ALU64 | BPF_RSH | BPF_K: 983 case BPF_ALU64 | BPF_RSH | BPF_K:
970 emit(is64 ? rv_srli(rd, rd, imm) : rv_srliw(rd, rd, imm), ctx); 984 emit(is64 ? rv_srli(rd, rd, imm) : rv_srliw(rd, rd, imm), ctx);
985 if (!is64)
986 emit_zext_32(rd, ctx);
971 break; 987 break;
972 case BPF_ALU | BPF_ARSH | BPF_K: 988 case BPF_ALU | BPF_ARSH | BPF_K:
973 case BPF_ALU64 | BPF_ARSH | BPF_K: 989 case BPF_ALU64 | BPF_ARSH | BPF_K:
974 emit(is64 ? rv_srai(rd, rd, imm) : rv_sraiw(rd, rd, imm), ctx); 990 emit(is64 ? rv_srai(rd, rd, imm) : rv_sraiw(rd, rd, imm), ctx);
991 if (!is64)
992 emit_zext_32(rd, ctx);
975 break; 993 break;
976 994
977 /* JUMP off */ 995 /* JUMP off */