History

Merge branch 'bpf-rv64-jit'

Luke Nelson says: ==================== This patch series introduces a set of optimizations to the BPF JIT on RV64. The optimizations are related to the verifier zero-extension optimization and BPF_JMP BPF_K. We tested the optimizations on a QEMU riscv64 virt machine, using lib/test_bpf and test_verifier, and formally verified their correctness using Serval. ====================

Daniel Borkmann committed 6 years ago

Commit a085a1e2 parents 5447e8e 073ca6a1 file · +44 −20Browse files

Unified · Split

arch/riscv/net/bpf_jit_comp64.c+44−20
@@ -515,7 +515,7 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, · 514 unmodified lines
515515 case BPF_ALU | BPF_LSH | BPF_X:
516516 case BPF_ALU64 | BPF_LSH | BPF_X:
517517 emit(is64 ? rv_sll(rd, rd, rs) : rv_sllw(rd, rd, rs), ctx);
518− if (!is64)
518+ if (!is64 && !aux->verifier_zext)
519519 emit_zext_32(rd, ctx);
520520 break;
521521 case BPF_ALU | BPF_RSH | BPF_X:
@@ -542,13 +542,21 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, · 20 unmodified lines
542542
543543 /* dst = BSWAP##imm(dst) */
544544 case BPF_ALU | BPF_END | BPF_FROM_LE:
545− {
546− int shift = 64 - imm;
547−
548− emit(rv_slli(rd, rd, shift), ctx);
549− emit(rv_srli(rd, rd, shift), ctx);
545+ switch (imm) {
546+ case 16:
547+ emit(rv_slli(rd, rd, 48), ctx);
548+ emit(rv_srli(rd, rd, 48), ctx);
549+ break;
550+ case 32:
551+ if (!aux->verifier_zext)
552+ emit_zext_32(rd, ctx);
553+ break;
554+ case 64:
555+ /* Do nothing */
556+ break;
557+ }
550558 break;
551− }
559+
552560 case BPF_ALU | BPF_END | BPF_FROM_BE:
553561 emit(rv_addi(RV_REG_T2, RV_REG_ZERO, 0), ctx);
554562
@@ -692,19 +700,19 @@ out_be: · 137 unmodified lines
692700 case BPF_ALU | BPF_LSH | BPF_K:
693701 case BPF_ALU64 | BPF_LSH | BPF_K:
694702 emit(is64 ? rv_slli(rd, rd, imm) : rv_slliw(rd, rd, imm), ctx);
695− if (!is64)
703+ if (!is64 && !aux->verifier_zext)
696704 emit_zext_32(rd, ctx);
697705 break;
698706 case BPF_ALU | BPF_RSH | BPF_K:
699707 case BPF_ALU64 | BPF_RSH | BPF_K:
700708 emit(is64 ? rv_srli(rd, rd, imm) : rv_srliw(rd, rd, imm), ctx);
701− if (!is64)
709+ if (!is64 && !aux->verifier_zext)
702710 emit_zext_32(rd, ctx);
703711 break;
704712 case BPF_ALU | BPF_ARSH | BPF_K:
705713 case BPF_ALU64 | BPF_ARSH | BPF_K:
706714 emit(is64 ? rv_srai(rd, rd, imm) : rv_sraiw(rd, rd, imm), ctx);
707− if (!is64)
715+ if (!is64 && !aux->verifier_zext)
708716 emit_zext_32(rd, ctx);
709717 break;
710718
@@ -784,11 +792,15 @@ out_be: · 73 unmodified lines
784792 case BPF_JMP32 | BPF_JSGE | BPF_K:
785793 case BPF_JMP | BPF_JSLE | BPF_K:
786794 case BPF_JMP32 | BPF_JSLE | BPF_K:
787− case BPF_JMP | BPF_JSET | BPF_K:
788− case BPF_JMP32 | BPF_JSET | BPF_K:
789795 rvoff = rv_offset(i, off, ctx);
790796 s = ctx->ninsns;
791− emit_imm(RV_REG_T1, imm, ctx);
797+ if (imm) {
798+ emit_imm(RV_REG_T1, imm, ctx);
799+ rs = RV_REG_T1;
800+ } else {
801+ /* If imm is 0, simply use zero register. */
802+ rs = RV_REG_ZERO;
803+ }
792804 if (!is64) {
793805 if (is_signed_bpf_cond(BPF_OP(code)))
794806 emit_sext_32_rd(&rd, ctx);
@@ -799,16 +811,28 @@ out_be: · 4 unmodified lines
799811
800812 /* Adjust for extra insns */
801813 rvoff -= (e - s) << 2;
814+ emit_branch(BPF_OP(code), rd, rs, rvoff, ctx);
815+ break;
802816
803− if (BPF_OP(code) == BPF_JSET) {
804− /* Adjust for and */
805− rvoff -= 4;
806− emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
807− emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff,
808− ctx);
817+ case BPF_JMP | BPF_JSET | BPF_K:
818+ case BPF_JMP32 | BPF_JSET | BPF_K:
819+ rvoff = rv_offset(i, off, ctx);
820+ s = ctx->ninsns;
821+ if (is_12b_int(imm)) {
822+ emit(rv_andi(RV_REG_T1, rd, imm), ctx);
809823 } else {
810− emit_branch(BPF_OP(code), rd, RV_REG_T1, rvoff, ctx);
824+ emit_imm(RV_REG_T1, imm, ctx);
825+ emit(rv_and(RV_REG_T1, rd, RV_REG_T1), ctx);
811826 }
827+ /* For jset32, we should clear the upper 32 bits of t1, but
828+ * sign-extension is sufficient here and saves one instruction,
829+ * as t1 is used only in comparison against zero.
830+ */
831+ if (!is64 && imm < 0)
832+ emit(rv_addiw(RV_REG_T1, RV_REG_T1, 0), ctx);
833+ e = ctx->ninsns;
834+ rvoff -= (e - s) << 2;
835+ emit_branch(BPF_JNE, RV_REG_T1, RV_REG_ZERO, rvoff, ctx);
812836 break;
813837
814838 /* function call */