Skip to content

Commit a67b375

Browse files
daviddaneydavem330
authored andcommitted
MIPS, bpf: Implement JLT, JLE, JSLT and JSLE ops in the eBPF JIT.
Signed-off-by: David Daney <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8d8d18c commit a67b375

File tree

1 file changed

+72
-29
lines changed

1 file changed

+72
-29
lines changed

arch/mips/net/ebpf_jit.c

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -990,8 +990,12 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
990990
goto jeq_common;
991991
case BPF_JMP | BPF_JEQ | BPF_X: /* JMP_REG */
992992
case BPF_JMP | BPF_JNE | BPF_X:
993+
case BPF_JMP | BPF_JSLT | BPF_X:
994+
case BPF_JMP | BPF_JSLE | BPF_X:
993995
case BPF_JMP | BPF_JSGT | BPF_X:
994996
case BPF_JMP | BPF_JSGE | BPF_X:
997+
case BPF_JMP | BPF_JLT | BPF_X:
998+
case BPF_JMP | BPF_JLE | BPF_X:
995999
case BPF_JMP | BPF_JGT | BPF_X:
9961000
case BPF_JMP | BPF_JGE | BPF_X:
9971001
case BPF_JMP | BPF_JSET | BPF_X:
@@ -1013,41 +1017,47 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
10131017
cmp_eq = false;
10141018
dst = MIPS_R_AT;
10151019
src = MIPS_R_ZERO;
1016-
} else if (BPF_OP(insn->code) == BPF_JSGT) {
1020+
} else if (BPF_OP(insn->code) == BPF_JSGT || BPF_OP(insn->code) == BPF_JSLE) {
10171021
emit_instr(ctx, dsubu, MIPS_R_AT, dst, src);
10181022
if ((insn + 1)->code == (BPF_JMP | BPF_EXIT) && insn->off == 1) {
10191023
b_off = b_imm(exit_idx, ctx);
10201024
if (is_bad_offset(b_off))
10211025
return -E2BIG;
1022-
emit_instr(ctx, blez, MIPS_R_AT, b_off);
1026+
if (BPF_OP(insn->code) == BPF_JSGT)
1027+
emit_instr(ctx, blez, MIPS_R_AT, b_off);
1028+
else
1029+
emit_instr(ctx, bgtz, MIPS_R_AT, b_off);
10231030
emit_instr(ctx, nop);
10241031
return 2; /* We consumed the exit. */
10251032
}
10261033
b_off = b_imm(this_idx + insn->off + 1, ctx);
10271034
if (is_bad_offset(b_off))
10281035
return -E2BIG;
1029-
emit_instr(ctx, bgtz, MIPS_R_AT, b_off);
1036+
if (BPF_OP(insn->code) == BPF_JSGT)
1037+
emit_instr(ctx, bgtz, MIPS_R_AT, b_off);
1038+
else
1039+
emit_instr(ctx, blez, MIPS_R_AT, b_off);
10301040
emit_instr(ctx, nop);
10311041
break;
1032-
} else if (BPF_OP(insn->code) == BPF_JSGE) {
1042+
} else if (BPF_OP(insn->code) == BPF_JSGE || BPF_OP(insn->code) == BPF_JSLT) {
10331043
emit_instr(ctx, slt, MIPS_R_AT, dst, src);
1034-
cmp_eq = true;
1044+
cmp_eq = BPF_OP(insn->code) == BPF_JSGE;
10351045
dst = MIPS_R_AT;
10361046
src = MIPS_R_ZERO;
1037-
} else if (BPF_OP(insn->code) == BPF_JGT) {
1047+
} else if (BPF_OP(insn->code) == BPF_JGT || BPF_OP(insn->code) == BPF_JLE) {
10381048
/* dst or src could be AT */
10391049
emit_instr(ctx, dsubu, MIPS_R_T8, dst, src);
10401050
emit_instr(ctx, sltu, MIPS_R_AT, dst, src);
10411051
/* SP known to be non-zero, movz becomes boolean not */
10421052
emit_instr(ctx, movz, MIPS_R_T9, MIPS_R_SP, MIPS_R_T8);
10431053
emit_instr(ctx, movn, MIPS_R_T9, MIPS_R_ZERO, MIPS_R_T8);
10441054
emit_instr(ctx, or, MIPS_R_AT, MIPS_R_T9, MIPS_R_AT);
1045-
cmp_eq = true;
1055+
cmp_eq = BPF_OP(insn->code) == BPF_JGT;
10461056
dst = MIPS_R_AT;
10471057
src = MIPS_R_ZERO;
1048-
} else if (BPF_OP(insn->code) == BPF_JGE) {
1058+
} else if (BPF_OP(insn->code) == BPF_JGE || BPF_OP(insn->code) == BPF_JLT) {
10491059
emit_instr(ctx, sltu, MIPS_R_AT, dst, src);
1050-
cmp_eq = true;
1060+
cmp_eq = BPF_OP(insn->code) == BPF_JGE;
10511061
dst = MIPS_R_AT;
10521062
src = MIPS_R_ZERO;
10531063
} else { /* JNE/JEQ case */
@@ -1110,6 +1120,8 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
11101120
break;
11111121
case BPF_JMP | BPF_JSGT | BPF_K: /* JMP_IMM */
11121122
case BPF_JMP | BPF_JSGE | BPF_K: /* JMP_IMM */
1123+
case BPF_JMP | BPF_JSLT | BPF_K: /* JMP_IMM */
1124+
case BPF_JMP | BPF_JSLE | BPF_K: /* JMP_IMM */
11131125
cmp_eq = (BPF_OP(insn->code) == BPF_JSGE);
11141126
dst = ebpf_to_mips_reg(ctx, insn, dst_reg_fp_ok);
11151127
if (dst < 0)
@@ -1120,65 +1132,92 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
11201132
b_off = b_imm(exit_idx, ctx);
11211133
if (is_bad_offset(b_off))
11221134
return -E2BIG;
1123-
if (cmp_eq)
1124-
emit_instr(ctx, bltz, dst, b_off);
1125-
else
1135+
switch (BPF_OP(insn->code)) {
1136+
case BPF_JSGT:
11261137
emit_instr(ctx, blez, dst, b_off);
1138+
break;
1139+
case BPF_JSGE:
1140+
emit_instr(ctx, bltz, dst, b_off);
1141+
break;
1142+
case BPF_JSLT:
1143+
emit_instr(ctx, bgez, dst, b_off);
1144+
break;
1145+
case BPF_JSLE:
1146+
emit_instr(ctx, bgtz, dst, b_off);
1147+
break;
1148+
}
11271149
emit_instr(ctx, nop);
11281150
return 2; /* We consumed the exit. */
11291151
}
11301152
b_off = b_imm(this_idx + insn->off + 1, ctx);
11311153
if (is_bad_offset(b_off))
11321154
return -E2BIG;
1133-
if (cmp_eq)
1134-
emit_instr(ctx, bgez, dst, b_off);
1135-
else
1155+
switch (BPF_OP(insn->code)) {
1156+
case BPF_JSGT:
11361157
emit_instr(ctx, bgtz, dst, b_off);
1158+
break;
1159+
case BPF_JSGE:
1160+
emit_instr(ctx, bgez, dst, b_off);
1161+
break;
1162+
case BPF_JSLT:
1163+
emit_instr(ctx, bltz, dst, b_off);
1164+
break;
1165+
case BPF_JSLE:
1166+
emit_instr(ctx, blez, dst, b_off);
1167+
break;
1168+
}
11371169
emit_instr(ctx, nop);
11381170
break;
11391171
}
11401172
/*
11411173
* only "LT" compare available, so we must use imm + 1
1142-
* to generate "GT"
1174+
* to generate "GT" and imm -1 to generate LE
11431175
*/
1144-
t64s = insn->imm + (cmp_eq ? 0 : 1);
1176+
if (BPF_OP(insn->code) == BPF_JSGT)
1177+
t64s = insn->imm + 1;
1178+
else if (BPF_OP(insn->code) == BPF_JSLE)
1179+
t64s = insn->imm + 1;
1180+
else
1181+
t64s = insn->imm;
1182+
1183+
cmp_eq = BPF_OP(insn->code) == BPF_JSGT || BPF_OP(insn->code) == BPF_JSGE;
11451184
if (t64s >= S16_MIN && t64s <= S16_MAX) {
11461185
emit_instr(ctx, slti, MIPS_R_AT, dst, (int)t64s);
11471186
src = MIPS_R_AT;
11481187
dst = MIPS_R_ZERO;
1149-
cmp_eq = true;
11501188
goto jeq_common;
11511189
}
11521190
emit_const_to_reg(ctx, MIPS_R_AT, (u64)t64s);
11531191
emit_instr(ctx, slt, MIPS_R_AT, dst, MIPS_R_AT);
11541192
src = MIPS_R_AT;
11551193
dst = MIPS_R_ZERO;
1156-
cmp_eq = true;
11571194
goto jeq_common;
11581195

11591196
case BPF_JMP | BPF_JGT | BPF_K:
11601197
case BPF_JMP | BPF_JGE | BPF_K:
1198+
case BPF_JMP | BPF_JLT | BPF_K:
1199+
case BPF_JMP | BPF_JLE | BPF_K:
11611200
cmp_eq = (BPF_OP(insn->code) == BPF_JGE);
11621201
dst = ebpf_to_mips_reg(ctx, insn, dst_reg_fp_ok);
11631202
if (dst < 0)
11641203
return dst;
11651204
/*
11661205
* only "LT" compare available, so we must use imm + 1
1167-
* to generate "GT"
1206+
* to generate "GT" and imm -1 to generate LE
11681207
*/
1169-
t64s = (u64)(u32)(insn->imm) + (cmp_eq ? 0 : 1);
1170-
if (t64s >= 0 && t64s <= S16_MAX) {
1171-
emit_instr(ctx, sltiu, MIPS_R_AT, dst, (int)t64s);
1172-
src = MIPS_R_AT;
1173-
dst = MIPS_R_ZERO;
1174-
cmp_eq = true;
1175-
goto jeq_common;
1176-
}
1208+
if (BPF_OP(insn->code) == BPF_JGT)
1209+
t64s = (u64)(u32)(insn->imm) + 1;
1210+
else if (BPF_OP(insn->code) == BPF_JLE)
1211+
t64s = (u64)(u32)(insn->imm) + 1;
1212+
else
1213+
t64s = (u64)(u32)(insn->imm);
1214+
1215+
cmp_eq = BPF_OP(insn->code) == BPF_JGT || BPF_OP(insn->code) == BPF_JGE;
1216+
11771217
emit_const_to_reg(ctx, MIPS_R_AT, (u64)t64s);
11781218
emit_instr(ctx, sltu, MIPS_R_AT, dst, MIPS_R_AT);
11791219
src = MIPS_R_AT;
11801220
dst = MIPS_R_ZERO;
1181-
cmp_eq = true;
11821221
goto jeq_common;
11831222

11841223
case BPF_JMP | BPF_JSET | BPF_K: /* JMP_IMM */
@@ -1712,10 +1751,14 @@ static int reg_val_propagate_range(struct jit_ctx *ctx, u64 initial_rvt,
17121751
case BPF_JEQ:
17131752
case BPF_JGT:
17141753
case BPF_JGE:
1754+
case BPF_JLT:
1755+
case BPF_JLE:
17151756
case BPF_JSET:
17161757
case BPF_JNE:
17171758
case BPF_JSGT:
17181759
case BPF_JSGE:
1760+
case BPF_JSLT:
1761+
case BPF_JSLE:
17191762
if (follow_taken) {
17201763
rvt[idx] |= RVT_BRANCH_TAKEN;
17211764
idx += insn->off;

0 commit comments

Comments
 (0)