mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 04:31:50 +00:00
bpf: Support new unconditional bswap instruction
The existing 'be' and 'le' insns will do conditional bswap depends on host endianness. This patch implements unconditional bswap insns. Acked-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Yonghong Song <yonghong.song@linux.dev> Link: https://lore.kernel.org/r/20230728011213.3712808-1-yonghong.song@linux.dev Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
1f1e864b65
commit
0845c3db7b
@ -1322,6 +1322,7 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
|
||||
break;
|
||||
|
||||
case BPF_ALU | BPF_END | BPF_FROM_BE:
|
||||
case BPF_ALU64 | BPF_END | BPF_FROM_LE:
|
||||
switch (imm32) {
|
||||
case 16:
|
||||
/* Emit 'ror %ax, 8' to swap lower 2 bytes */
|
||||
|
@ -1524,6 +1524,7 @@ EXPORT_SYMBOL_GPL(__bpf_call_base);
|
||||
INSN_3(ALU64, DIV, X), \
|
||||
INSN_3(ALU64, MOD, X), \
|
||||
INSN_2(ALU64, NEG), \
|
||||
INSN_3(ALU64, END, TO_LE), \
|
||||
/* Immediate based. */ \
|
||||
INSN_3(ALU64, ADD, K), \
|
||||
INSN_3(ALU64, SUB, K), \
|
||||
@ -1848,6 +1849,19 @@ select_insn:
|
||||
break;
|
||||
}
|
||||
CONT;
|
||||
ALU64_END_TO_LE:
|
||||
switch (IMM) {
|
||||
case 16:
|
||||
DST = (__force u16) __swab16(DST);
|
||||
break;
|
||||
case 32:
|
||||
DST = (__force u32) __swab32(DST);
|
||||
break;
|
||||
case 64:
|
||||
DST = (__force u64) __swab64(DST);
|
||||
break;
|
||||
}
|
||||
CONT;
|
||||
|
||||
/* CALL */
|
||||
JMP_CALL:
|
||||
|
@ -3012,8 +3012,10 @@ static bool is_reg64(struct bpf_verifier_env *env, struct bpf_insn *insn,
|
||||
}
|
||||
}
|
||||
|
||||
if (class == BPF_ALU64 && op == BPF_END && (insn->imm == 16 || insn->imm == 32))
|
||||
return false;
|
||||
|
||||
if (class == BPF_ALU64 || class == BPF_JMP ||
|
||||
/* BPF_END always use BPF_ALU class. */
|
||||
(class == BPF_ALU && op == BPF_END && insn->imm == 64))
|
||||
return true;
|
||||
|
||||
@ -13076,7 +13078,8 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
||||
} else {
|
||||
if (insn->src_reg != BPF_REG_0 || insn->off != 0 ||
|
||||
(insn->imm != 16 && insn->imm != 32 && insn->imm != 64) ||
|
||||
BPF_CLASS(insn->code) == BPF_ALU64) {
|
||||
(BPF_CLASS(insn->code) == BPF_ALU64 &&
|
||||
BPF_SRC(insn->code) != BPF_TO_LE)) {
|
||||
verbose(env, "BPF_END uses reserved fields\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user