bpf: Support new signed div/mod instructions.
Add interpreter/jit support for new signed div/mod insns. The new signed div/mod instructions are encoded with unsigned div/mod instructions plus insn->off == 1. Also add basic verifier support to ensure new insns get accepted. Acked-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Yonghong Song <yonghong.song@linux.dev> Link: https://lore.kernel.org/r/20230728011219.3714605-1-yonghong.song@linux.dev Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
committed by
Alexei Starovoitov
parent
0845c3db7b
commit
ec0e2da95f
+94
-16
@@ -1792,36 +1792,114 @@ select_insn:
|
||||
(*(s64 *) &DST) >>= IMM;
|
||||
CONT;
|
||||
ALU64_MOD_X:
|
||||
div64_u64_rem(DST, SRC, &AX);
|
||||
DST = AX;
|
||||
switch (OFF) {
|
||||
case 0:
|
||||
div64_u64_rem(DST, SRC, &AX);
|
||||
DST = AX;
|
||||
break;
|
||||
case 1:
|
||||
AX = div64_s64(DST, SRC);
|
||||
DST = DST - AX * SRC;
|
||||
break;
|
||||
}
|
||||
CONT;
|
||||
ALU_MOD_X:
|
||||
AX = (u32) DST;
|
||||
DST = do_div(AX, (u32) SRC);
|
||||
switch (OFF) {
|
||||
case 0:
|
||||
AX = (u32) DST;
|
||||
DST = do_div(AX, (u32) SRC);
|
||||
break;
|
||||
case 1:
|
||||
AX = abs((s32)DST);
|
||||
AX = do_div(AX, abs((s32)SRC));
|
||||
if ((s32)DST < 0)
|
||||
DST = (u32)-AX;
|
||||
else
|
||||
DST = (u32)AX;
|
||||
break;
|
||||
}
|
||||
CONT;
|
||||
ALU64_MOD_K:
|
||||
div64_u64_rem(DST, IMM, &AX);
|
||||
DST = AX;
|
||||
switch (OFF) {
|
||||
case 0:
|
||||
div64_u64_rem(DST, IMM, &AX);
|
||||
DST = AX;
|
||||
break;
|
||||
case 1:
|
||||
AX = div64_s64(DST, IMM);
|
||||
DST = DST - AX * IMM;
|
||||
break;
|
||||
}
|
||||
CONT;
|
||||
ALU_MOD_K:
|
||||
AX = (u32) DST;
|
||||
DST = do_div(AX, (u32) IMM);
|
||||
switch (OFF) {
|
||||
case 0:
|
||||
AX = (u32) DST;
|
||||
DST = do_div(AX, (u32) IMM);
|
||||
break;
|
||||
case 1:
|
||||
AX = abs((s32)DST);
|
||||
AX = do_div(AX, abs((s32)IMM));
|
||||
if ((s32)DST < 0)
|
||||
DST = (u32)-AX;
|
||||
else
|
||||
DST = (u32)AX;
|
||||
break;
|
||||
}
|
||||
CONT;
|
||||
ALU64_DIV_X:
|
||||
DST = div64_u64(DST, SRC);
|
||||
switch (OFF) {
|
||||
case 0:
|
||||
DST = div64_u64(DST, SRC);
|
||||
break;
|
||||
case 1:
|
||||
DST = div64_s64(DST, SRC);
|
||||
break;
|
||||
}
|
||||
CONT;
|
||||
ALU_DIV_X:
|
||||
AX = (u32) DST;
|
||||
do_div(AX, (u32) SRC);
|
||||
DST = (u32) AX;
|
||||
switch (OFF) {
|
||||
case 0:
|
||||
AX = (u32) DST;
|
||||
do_div(AX, (u32) SRC);
|
||||
DST = (u32) AX;
|
||||
break;
|
||||
case 1:
|
||||
AX = abs((s32)DST);
|
||||
do_div(AX, abs((s32)SRC));
|
||||
if ((s32)DST < 0 == (s32)SRC < 0)
|
||||
DST = (u32)AX;
|
||||
else
|
||||
DST = (u32)-AX;
|
||||
break;
|
||||
}
|
||||
CONT;
|
||||
ALU64_DIV_K:
|
||||
DST = div64_u64(DST, IMM);
|
||||
switch (OFF) {
|
||||
case 0:
|
||||
DST = div64_u64(DST, IMM);
|
||||
break;
|
||||
case 1:
|
||||
DST = div64_s64(DST, IMM);
|
||||
break;
|
||||
}
|
||||
CONT;
|
||||
ALU_DIV_K:
|
||||
AX = (u32) DST;
|
||||
do_div(AX, (u32) IMM);
|
||||
DST = (u32) AX;
|
||||
switch (OFF) {
|
||||
case 0:
|
||||
AX = (u32) DST;
|
||||
do_div(AX, (u32) IMM);
|
||||
DST = (u32) AX;
|
||||
break;
|
||||
case 1:
|
||||
AX = abs((s32)DST);
|
||||
do_div(AX, abs((s32)IMM));
|
||||
if ((s32)DST < 0 == (s32)IMM < 0)
|
||||
DST = (u32)AX;
|
||||
else
|
||||
DST = (u32)-AX;
|
||||
break;
|
||||
}
|
||||
CONT;
|
||||
ALU_END_TO_BE:
|
||||
switch (IMM) {
|
||||
|
||||
Reference in New Issue
Block a user