x32: bpf: eliminate zero extension code-gen
Cc: Wang YanQing <udknight@gmail.com> Tested-by: Wang YanQing <udknight@gmail.com> Signed-off-by: Jiong Wang <jiong.wang@netronome.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
3e2a33cf7e
commit
836256bf5f
|
@ -253,13 +253,14 @@ static inline void emit_ia32_mov_r(const u8 dst, const u8 src, bool dstk,
|
|||
/* dst = src */
|
||||
static inline void emit_ia32_mov_r64(const bool is64, const u8 dst[],
|
||||
const u8 src[], bool dstk,
|
||||
bool sstk, u8 **pprog)
|
||||
bool sstk, u8 **pprog,
|
||||
const struct bpf_prog_aux *aux)
|
||||
{
|
||||
emit_ia32_mov_r(dst_lo, src_lo, dstk, sstk, pprog);
|
||||
if (is64)
|
||||
/* complete 8 byte move */
|
||||
emit_ia32_mov_r(dst_hi, src_hi, dstk, sstk, pprog);
|
||||
else
|
||||
else if (!aux->verifier_zext)
|
||||
/* zero out high 4 bytes */
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, pprog);
|
||||
}
|
||||
|
@ -313,7 +314,8 @@ static inline void emit_ia32_mul_r(const u8 dst, const u8 src, bool dstk,
|
|||
}
|
||||
|
||||
static inline void emit_ia32_to_le_r64(const u8 dst[], s32 val,
|
||||
bool dstk, u8 **pprog)
|
||||
bool dstk, u8 **pprog,
|
||||
const struct bpf_prog_aux *aux)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
int cnt = 0;
|
||||
|
@ -334,12 +336,14 @@ static inline void emit_ia32_to_le_r64(const u8 dst[], s32 val,
|
|||
*/
|
||||
EMIT2(0x0F, 0xB7);
|
||||
EMIT1(add_2reg(0xC0, dreg_lo, dreg_lo));
|
||||
/* xor dreg_hi,dreg_hi */
|
||||
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
|
||||
if (!aux->verifier_zext)
|
||||
/* xor dreg_hi,dreg_hi */
|
||||
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
|
||||
break;
|
||||
case 32:
|
||||
/* xor dreg_hi,dreg_hi */
|
||||
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
|
||||
if (!aux->verifier_zext)
|
||||
/* xor dreg_hi,dreg_hi */
|
||||
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
|
||||
break;
|
||||
case 64:
|
||||
/* nop */
|
||||
|
@ -358,7 +362,8 @@ static inline void emit_ia32_to_le_r64(const u8 dst[], s32 val,
|
|||
}
|
||||
|
||||
static inline void emit_ia32_to_be_r64(const u8 dst[], s32 val,
|
||||
bool dstk, u8 **pprog)
|
||||
bool dstk, u8 **pprog,
|
||||
const struct bpf_prog_aux *aux)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
int cnt = 0;
|
||||
|
@ -380,16 +385,18 @@ static inline void emit_ia32_to_be_r64(const u8 dst[], s32 val,
|
|||
EMIT2(0x0F, 0xB7);
|
||||
EMIT1(add_2reg(0xC0, dreg_lo, dreg_lo));
|
||||
|
||||
/* xor dreg_hi,dreg_hi */
|
||||
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
|
||||
if (!aux->verifier_zext)
|
||||
/* xor dreg_hi,dreg_hi */
|
||||
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
|
||||
break;
|
||||
case 32:
|
||||
/* Emit 'bswap eax' to swap lower 4 bytes */
|
||||
EMIT1(0x0F);
|
||||
EMIT1(add_1reg(0xC8, dreg_lo));
|
||||
|
||||
/* xor dreg_hi,dreg_hi */
|
||||
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
|
||||
if (!aux->verifier_zext)
|
||||
/* xor dreg_hi,dreg_hi */
|
||||
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
|
||||
break;
|
||||
case 64:
|
||||
/* Emit 'bswap eax' to swap lower 4 bytes */
|
||||
|
@ -569,7 +576,7 @@ static inline void emit_ia32_alu_r(const bool is64, const bool hi, const u8 op,
|
|||
static inline void emit_ia32_alu_r64(const bool is64, const u8 op,
|
||||
const u8 dst[], const u8 src[],
|
||||
bool dstk, bool sstk,
|
||||
u8 **pprog)
|
||||
u8 **pprog, const struct bpf_prog_aux *aux)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
|
||||
|
@ -577,7 +584,7 @@ static inline void emit_ia32_alu_r64(const bool is64, const u8 op,
|
|||
if (is64)
|
||||
emit_ia32_alu_r(is64, true, op, dst_hi, src_hi, dstk, sstk,
|
||||
&prog);
|
||||
else
|
||||
else if (!aux->verifier_zext)
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
*pprog = prog;
|
||||
}
|
||||
|
@ -668,7 +675,8 @@ static inline void emit_ia32_alu_i(const bool is64, const bool hi, const u8 op,
|
|||
/* ALU operation (64 bit) */
|
||||
static inline void emit_ia32_alu_i64(const bool is64, const u8 op,
|
||||
const u8 dst[], const u32 val,
|
||||
bool dstk, u8 **pprog)
|
||||
bool dstk, u8 **pprog,
|
||||
const struct bpf_prog_aux *aux)
|
||||
{
|
||||
u8 *prog = *pprog;
|
||||
u32 hi = 0;
|
||||
|
@ -679,7 +687,7 @@ static inline void emit_ia32_alu_i64(const bool is64, const u8 op,
|
|||
emit_ia32_alu_i(is64, false, op, dst_lo, val, dstk, &prog);
|
||||
if (is64)
|
||||
emit_ia32_alu_i(is64, true, op, dst_hi, hi, dstk, &prog);
|
||||
else
|
||||
else if (!aux->verifier_zext)
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
|
||||
*pprog = prog;
|
||||
|
@ -1713,8 +1721,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||
case BPF_ALU64 | BPF_MOV | BPF_X:
|
||||
switch (BPF_SRC(code)) {
|
||||
case BPF_X:
|
||||
emit_ia32_mov_r64(is64, dst, src, dstk,
|
||||
sstk, &prog);
|
||||
if (imm32 == 1) {
|
||||
/* Special mov32 for zext. */
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
break;
|
||||
}
|
||||
emit_ia32_mov_r64(is64, dst, src, dstk, sstk,
|
||||
&prog, bpf_prog->aux);
|
||||
break;
|
||||
case BPF_K:
|
||||
/* Sign-extend immediate value to dst reg */
|
||||
|
@ -1754,11 +1767,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||
switch (BPF_SRC(code)) {
|
||||
case BPF_X:
|
||||
emit_ia32_alu_r64(is64, BPF_OP(code), dst,
|
||||
src, dstk, sstk, &prog);
|
||||
src, dstk, sstk, &prog,
|
||||
bpf_prog->aux);
|
||||
break;
|
||||
case BPF_K:
|
||||
emit_ia32_alu_i64(is64, BPF_OP(code), dst,
|
||||
imm32, dstk, &prog);
|
||||
imm32, dstk, &prog,
|
||||
bpf_prog->aux);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -1777,7 +1792,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||
false, &prog);
|
||||
break;
|
||||
}
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
if (!bpf_prog->aux->verifier_zext)
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
break;
|
||||
case BPF_ALU | BPF_LSH | BPF_X:
|
||||
case BPF_ALU | BPF_RSH | BPF_X:
|
||||
|
@ -1797,7 +1813,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||
&prog);
|
||||
break;
|
||||
}
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
if (!bpf_prog->aux->verifier_zext)
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
break;
|
||||
/* dst = dst / src(imm) */
|
||||
/* dst = dst % src(imm) */
|
||||
|
@ -1819,7 +1836,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||
&prog);
|
||||
break;
|
||||
}
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
if (!bpf_prog->aux->verifier_zext)
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
break;
|
||||
case BPF_ALU64 | BPF_DIV | BPF_K:
|
||||
case BPF_ALU64 | BPF_DIV | BPF_X:
|
||||
|
@ -1836,7 +1854,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||
EMIT2_off32(0xC7, add_1reg(0xC0, IA32_ECX), imm32);
|
||||
emit_ia32_shift_r(BPF_OP(code), dst_lo, IA32_ECX, dstk,
|
||||
false, &prog);
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
if (!bpf_prog->aux->verifier_zext)
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
break;
|
||||
/* dst = dst << imm */
|
||||
case BPF_ALU64 | BPF_LSH | BPF_K:
|
||||
|
@ -1872,7 +1891,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||
case BPF_ALU | BPF_NEG:
|
||||
emit_ia32_alu_i(is64, false, BPF_OP(code),
|
||||
dst_lo, 0, dstk, &prog);
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
if (!bpf_prog->aux->verifier_zext)
|
||||
emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
|
||||
break;
|
||||
/* dst = ~dst (64 bit) */
|
||||
case BPF_ALU64 | BPF_NEG:
|
||||
|
@ -1892,11 +1912,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||
break;
|
||||
/* dst = htole(dst) */
|
||||
case BPF_ALU | BPF_END | BPF_FROM_LE:
|
||||
emit_ia32_to_le_r64(dst, imm32, dstk, &prog);
|
||||
emit_ia32_to_le_r64(dst, imm32, dstk, &prog,
|
||||
bpf_prog->aux);
|
||||
break;
|
||||
/* dst = htobe(dst) */
|
||||
case BPF_ALU | BPF_END | BPF_FROM_BE:
|
||||
emit_ia32_to_be_r64(dst, imm32, dstk, &prog);
|
||||
emit_ia32_to_be_r64(dst, imm32, dstk, &prog,
|
||||
bpf_prog->aux);
|
||||
break;
|
||||
/* dst = imm64 */
|
||||
case BPF_LD | BPF_IMM | BPF_DW: {
|
||||
|
@ -2051,6 +2073,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
|
|||
case BPF_B:
|
||||
case BPF_H:
|
||||
case BPF_W:
|
||||
if (!bpf_prog->aux->verifier_zext)
|
||||
break;
|
||||
if (dstk) {
|
||||
EMIT3(0xC7, add_1reg(0x40, IA32_EBP),
|
||||
STACK_VAR(dst_hi));
|
||||
|
@ -2475,6 +2499,11 @@ notyet:
|
|||
return proglen;
|
||||
}
|
||||
|
||||
bool bpf_jit_needs_zext(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
|
||||
{
|
||||
struct bpf_binary_header *header = NULL;
|
||||
|
|
Loading…
Reference in New Issue