Commit 836256bf authored by Jiong Wang's avatar Jiong Wang Committed by Alexei Starovoitov

x32: bpf: eliminate zero extension code-gen

Cc: Wang YanQing <udknight@gmail.com>
Tested-by: default avatarWang YanQing <udknight@gmail.com>
Signed-off-by: default avatarJiong Wang <jiong.wang@netronome.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 3e2a33cf
...@@ -253,13 +253,14 @@ static inline void emit_ia32_mov_r(const u8 dst, const u8 src, bool dstk, ...@@ -253,13 +253,14 @@ static inline void emit_ia32_mov_r(const u8 dst, const u8 src, bool dstk,
/* dst = src */ /* dst = src */
static inline void emit_ia32_mov_r64(const bool is64, const u8 dst[], static inline void emit_ia32_mov_r64(const bool is64, const u8 dst[],
const u8 src[], bool dstk, 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); emit_ia32_mov_r(dst_lo, src_lo, dstk, sstk, pprog);
if (is64) if (is64)
/* complete 8 byte move */ /* complete 8 byte move */
emit_ia32_mov_r(dst_hi, src_hi, dstk, sstk, pprog); emit_ia32_mov_r(dst_hi, src_hi, dstk, sstk, pprog);
else else if (!aux->verifier_zext)
/* zero out high 4 bytes */ /* zero out high 4 bytes */
emit_ia32_mov_i(dst_hi, 0, dstk, pprog); 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, ...@@ -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, 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; u8 *prog = *pprog;
int cnt = 0; int cnt = 0;
...@@ -334,12 +336,14 @@ static inline void emit_ia32_to_le_r64(const u8 dst[], s32 val, ...@@ -334,12 +336,14 @@ static inline void emit_ia32_to_le_r64(const u8 dst[], s32 val,
*/ */
EMIT2(0x0F, 0xB7); EMIT2(0x0F, 0xB7);
EMIT1(add_2reg(0xC0, dreg_lo, dreg_lo)); EMIT1(add_2reg(0xC0, dreg_lo, dreg_lo));
/* xor dreg_hi,dreg_hi */ if (!aux->verifier_zext)
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); /* xor dreg_hi,dreg_hi */
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
break; break;
case 32: case 32:
/* xor dreg_hi,dreg_hi */ if (!aux->verifier_zext)
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); /* xor dreg_hi,dreg_hi */
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
break; break;
case 64: case 64:
/* nop */ /* nop */
...@@ -358,7 +362,8 @@ static inline void emit_ia32_to_le_r64(const u8 dst[], s32 val, ...@@ -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, 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; u8 *prog = *pprog;
int cnt = 0; int cnt = 0;
...@@ -380,16 +385,18 @@ static inline void emit_ia32_to_be_r64(const u8 dst[], s32 val, ...@@ -380,16 +385,18 @@ static inline void emit_ia32_to_be_r64(const u8 dst[], s32 val,
EMIT2(0x0F, 0xB7); EMIT2(0x0F, 0xB7);
EMIT1(add_2reg(0xC0, dreg_lo, dreg_lo)); EMIT1(add_2reg(0xC0, dreg_lo, dreg_lo));
/* xor dreg_hi,dreg_hi */ if (!aux->verifier_zext)
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); /* xor dreg_hi,dreg_hi */
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
break; break;
case 32: case 32:
/* Emit 'bswap eax' to swap lower 4 bytes */ /* Emit 'bswap eax' to swap lower 4 bytes */
EMIT1(0x0F); EMIT1(0x0F);
EMIT1(add_1reg(0xC8, dreg_lo)); EMIT1(add_1reg(0xC8, dreg_lo));
/* xor dreg_hi,dreg_hi */ if (!aux->verifier_zext)
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi)); /* xor dreg_hi,dreg_hi */
EMIT2(0x33, add_2reg(0xC0, dreg_hi, dreg_hi));
break; break;
case 64: case 64:
/* Emit 'bswap eax' to swap lower 4 bytes */ /* 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, ...@@ -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, static inline void emit_ia32_alu_r64(const bool is64, const u8 op,
const u8 dst[], const u8 src[], const u8 dst[], const u8 src[],
bool dstk, bool sstk, bool dstk, bool sstk,
u8 **pprog) u8 **pprog, const struct bpf_prog_aux *aux)
{ {
u8 *prog = *pprog; u8 *prog = *pprog;
...@@ -577,7 +584,7 @@ static inline void emit_ia32_alu_r64(const bool is64, const u8 op, ...@@ -577,7 +584,7 @@ static inline void emit_ia32_alu_r64(const bool is64, const u8 op,
if (is64) if (is64)
emit_ia32_alu_r(is64, true, op, dst_hi, src_hi, dstk, sstk, emit_ia32_alu_r(is64, true, op, dst_hi, src_hi, dstk, sstk,
&prog); &prog);
else else if (!aux->verifier_zext)
emit_ia32_mov_i(dst_hi, 0, dstk, &prog); emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
*pprog = prog; *pprog = prog;
} }
...@@ -668,7 +675,8 @@ static inline void emit_ia32_alu_i(const bool is64, const bool hi, const u8 op, ...@@ -668,7 +675,8 @@ static inline void emit_ia32_alu_i(const bool is64, const bool hi, const u8 op,
/* ALU operation (64 bit) */ /* ALU operation (64 bit) */
static inline void emit_ia32_alu_i64(const bool is64, const u8 op, static inline void emit_ia32_alu_i64(const bool is64, const u8 op,
const u8 dst[], const u32 val, const u8 dst[], const u32 val,
bool dstk, u8 **pprog) bool dstk, u8 **pprog,
const struct bpf_prog_aux *aux)
{ {
u8 *prog = *pprog; u8 *prog = *pprog;
u32 hi = 0; u32 hi = 0;
...@@ -679,7 +687,7 @@ static inline void emit_ia32_alu_i64(const bool is64, const u8 op, ...@@ -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); emit_ia32_alu_i(is64, false, op, dst_lo, val, dstk, &prog);
if (is64) if (is64)
emit_ia32_alu_i(is64, true, op, dst_hi, hi, dstk, &prog); 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); emit_ia32_mov_i(dst_hi, 0, dstk, &prog);
*pprog = prog; *pprog = prog;
...@@ -1713,8 +1721,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, ...@@ -1713,8 +1721,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
case BPF_ALU64 | BPF_MOV | BPF_X: case BPF_ALU64 | BPF_MOV | BPF_X:
switch (BPF_SRC(code)) { switch (BPF_SRC(code)) {
case BPF_X: case BPF_X:
emit_ia32_mov_r64(is64, dst, src, dstk, if (imm32 == 1) {
sstk, &prog); /* 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; break;
case BPF_K: case BPF_K:
/* Sign-extend immediate value to dst reg */ /* Sign-extend immediate value to dst reg */
...@@ -1754,11 +1767,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, ...@@ -1754,11 +1767,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
switch (BPF_SRC(code)) { switch (BPF_SRC(code)) {
case BPF_X: case BPF_X:
emit_ia32_alu_r64(is64, BPF_OP(code), dst, emit_ia32_alu_r64(is64, BPF_OP(code), dst,
src, dstk, sstk, &prog); src, dstk, sstk, &prog,
bpf_prog->aux);
break; break;
case BPF_K: case BPF_K:
emit_ia32_alu_i64(is64, BPF_OP(code), dst, emit_ia32_alu_i64(is64, BPF_OP(code), dst,
imm32, dstk, &prog); imm32, dstk, &prog,
bpf_prog->aux);
break; break;
} }
break; break;
...@@ -1777,7 +1792,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, ...@@ -1777,7 +1792,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
false, &prog); false, &prog);
break; 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; break;
case BPF_ALU | BPF_LSH | BPF_X: case BPF_ALU | BPF_LSH | BPF_X:
case BPF_ALU | BPF_RSH | 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, ...@@ -1797,7 +1813,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
&prog); &prog);
break; 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; break;
/* dst = dst / src(imm) */ /* dst = dst / src(imm) */
/* 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, ...@@ -1819,7 +1836,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
&prog); &prog);
break; 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; break;
case BPF_ALU64 | BPF_DIV | BPF_K: case BPF_ALU64 | BPF_DIV | BPF_K:
case BPF_ALU64 | BPF_DIV | BPF_X: case BPF_ALU64 | BPF_DIV | BPF_X:
...@@ -1836,7 +1854,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, ...@@ -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); EMIT2_off32(0xC7, add_1reg(0xC0, IA32_ECX), imm32);
emit_ia32_shift_r(BPF_OP(code), dst_lo, IA32_ECX, dstk, emit_ia32_shift_r(BPF_OP(code), dst_lo, IA32_ECX, dstk,
false, &prog); 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; break;
/* dst = dst << imm */ /* dst = dst << imm */
case BPF_ALU64 | BPF_LSH | BPF_K: case BPF_ALU64 | BPF_LSH | BPF_K:
...@@ -1872,7 +1891,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, ...@@ -1872,7 +1891,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
case BPF_ALU | BPF_NEG: case BPF_ALU | BPF_NEG:
emit_ia32_alu_i(is64, false, BPF_OP(code), emit_ia32_alu_i(is64, false, BPF_OP(code),
dst_lo, 0, dstk, &prog); 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; break;
/* dst = ~dst (64 bit) */ /* dst = ~dst (64 bit) */
case BPF_ALU64 | BPF_NEG: case BPF_ALU64 | BPF_NEG:
...@@ -1892,11 +1912,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, ...@@ -1892,11 +1912,13 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
break; break;
/* dst = htole(dst) */ /* dst = htole(dst) */
case BPF_ALU | BPF_END | BPF_FROM_LE: 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; break;
/* dst = htobe(dst) */ /* dst = htobe(dst) */
case BPF_ALU | BPF_END | BPF_FROM_BE: 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; break;
/* dst = imm64 */ /* dst = imm64 */
case BPF_LD | BPF_IMM | BPF_DW: { case BPF_LD | BPF_IMM | BPF_DW: {
...@@ -2051,6 +2073,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, ...@@ -2051,6 +2073,8 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
case BPF_B: case BPF_B:
case BPF_H: case BPF_H:
case BPF_W: case BPF_W:
if (!bpf_prog->aux->verifier_zext)
break;
if (dstk) { if (dstk) {
EMIT3(0xC7, add_1reg(0x40, IA32_EBP), EMIT3(0xC7, add_1reg(0x40, IA32_EBP),
STACK_VAR(dst_hi)); STACK_VAR(dst_hi));
...@@ -2475,6 +2499,11 @@ emit_cond_jmp: jmp_cond = get_cond_jmp_opcode(BPF_OP(code), false); ...@@ -2475,6 +2499,11 @@ emit_cond_jmp: jmp_cond = get_cond_jmp_opcode(BPF_OP(code), false);
return proglen; return proglen;
} }
bool bpf_jit_needs_zext(void)
{
return true;
}
struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
{ {
struct bpf_binary_header *header = NULL; struct bpf_binary_header *header = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment