@@ -3,6 +3,8 @@
# Arch-specific network modules
#
+obj-$(CONFIG_BPF_JIT) += bpf_jit_core.o
+
ifeq ($(CONFIG_X86_32),y)
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp32.o
else
@@ -76,6 +76,10 @@ static inline int bpf_size_to_x86_bytes(int bpf_size)
#define X86_JLE 0x7E
#define X86_JG 0x7F
+#define COND_JMP_OPCODE_INVALID (0xFF)
+
+u8 get_cond_jmp_opcode(const u8 op, bool is_cmp_lo);
+
/* Maximum number of bytes emitted while JITing one eBPF insn */
#define BPF_MAX_INSN_SIZE 128
#define BPF_INSN_SAFETY 64
@@ -62,8 +62,6 @@
#define IA32_EBP (0x5)
#define IA32_ESP (0x4)
-#define COND_JMP_OPCODE_INVALID (0xFF)
-
/*
* Map eBPF registers to IA32 32bit registers or stack scratch space.
*
@@ -1307,75 +1305,6 @@ static inline void emit_push_r64(const u8 src[], u8 **pprog)
*pprog = prog;
}
-static u8 get_cond_jmp_opcode(const u8 op, bool is_cmp_lo)
-{
- u8 jmp_cond;
-
- /* Convert BPF opcode to x86 */
- switch (op) {
- case BPF_JEQ:
- jmp_cond = X86_JE;
- break;
- case BPF_JSET:
- case BPF_JNE:
- jmp_cond = X86_JNE;
- break;
- case BPF_JGT:
- /* GT is unsigned '>', JA in x86 */
- jmp_cond = X86_JA;
- break;
- case BPF_JLT:
- /* LT is unsigned '<', JB in x86 */
- jmp_cond = X86_JB;
- break;
- case BPF_JGE:
- /* GE is unsigned '>=', JAE in x86 */
- jmp_cond = X86_JAE;
- break;
- case BPF_JLE:
- /* LE is unsigned '<=', JBE in x86 */
- jmp_cond = X86_JBE;
- break;
- case BPF_JSGT:
- if (!is_cmp_lo)
- /* Signed '>', GT in x86 */
- jmp_cond = X86_JG;
- else
- /* GT is unsigned '>', JA in x86 */
- jmp_cond = X86_JA;
- break;
- case BPF_JSLT:
- if (!is_cmp_lo)
- /* Signed '<', LT in x86 */
- jmp_cond = X86_JL;
- else
- /* LT is unsigned '<', JB in x86 */
- jmp_cond = X86_JB;
- break;
- case BPF_JSGE:
- if (!is_cmp_lo)
- /* Signed '>=', GE in x86 */
- jmp_cond = X86_JGE;
- else
- /* GE is unsigned '>=', JAE in x86 */
- jmp_cond = X86_JAE;
- break;
- case BPF_JSLE:
- if (!is_cmp_lo)
- /* Signed '<=', LE in x86 */
- jmp_cond = X86_JLE;
- else
- /* LE is unsigned '<=', JBE in x86 */
- jmp_cond = X86_JBE;
- break;
- default: /* to silence GCC warning */
- jmp_cond = COND_JMP_OPCODE_INVALID;
- break;
- }
-
- return jmp_cond;
-}
-
static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image,
int oldproglen, struct jit_context *ctx)
{
@@ -1122,50 +1122,10 @@ xadd: if (is_imm8(insn->off))
else
EMIT2_off32(0x81, add_1reg(0xF8, dst_reg), imm32);
-emit_cond_jmp: /* Convert BPF opcode to x86 */
- switch (BPF_OP(insn->code)) {
- case BPF_JEQ:
- jmp_cond = X86_JE;
- break;
- case BPF_JSET:
- case BPF_JNE:
- jmp_cond = X86_JNE;
- break;
- case BPF_JGT:
- /* GT is unsigned '>', JA in x86 */
- jmp_cond = X86_JA;
- break;
- case BPF_JLT:
- /* LT is unsigned '<', JB in x86 */
- jmp_cond = X86_JB;
- break;
- case BPF_JGE:
- /* GE is unsigned '>=', JAE in x86 */
- jmp_cond = X86_JAE;
- break;
- case BPF_JLE:
- /* LE is unsigned '<=', JBE in x86 */
- jmp_cond = X86_JBE;
- break;
- case BPF_JSGT:
- /* Signed '>', GT in x86 */
- jmp_cond = X86_JG;
- break;
- case BPF_JSLT:
- /* Signed '<', LT in x86 */
- jmp_cond = X86_JL;
- break;
- case BPF_JSGE:
- /* Signed '>=', GE in x86 */
- jmp_cond = X86_JGE;
- break;
- case BPF_JSLE:
- /* Signed '<=', LE in x86 */
- jmp_cond = X86_JLE;
- break;
- default: /* to silence GCC warning */
+emit_cond_jmp:
+ jmp_cond = get_cond_jmp_opcode(BPF_OP(insn->code), false);
+ if (jmp_cond == COND_JMP_OPCODE_INVALID)
return -EFAULT;
- }
jmp_offset = addrs[i + insn->off] - addrs[i];
if (is_imm8(jmp_offset)) {
EMIT2(jmp_cond, jmp_offset);
new file mode 100644
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Common functionality for x86 32bit and 64bit BPF JIT compilers
+ */
+
+#include <linux/bpf.h>
+#include "bpf_jit.h"
+
+u8 get_cond_jmp_opcode(const u8 op, bool is_cmp_lo)
+{
+ u8 jmp_cond;
+
+ /* Convert BPF opcode to x86 */
+ switch (op) {
+ case BPF_JEQ:
+ jmp_cond = X86_JE;
+ break;
+ case BPF_JSET:
+ case BPF_JNE:
+ jmp_cond = X86_JNE;
+ break;
+ case BPF_JGT:
+ /* GT is unsigned '>', JA in x86 */
+ jmp_cond = X86_JA;
+ break;
+ case BPF_JLT:
+ /* LT is unsigned '<', JB in x86 */
+ jmp_cond = X86_JB;
+ break;
+ case BPF_JGE:
+ /* GE is unsigned '>=', JAE in x86 */
+ jmp_cond = X86_JAE;
+ break;
+ case BPF_JLE:
+ /* LE is unsigned '<=', JBE in x86 */
+ jmp_cond = X86_JBE;
+ break;
+ case BPF_JSGT:
+ if (!is_cmp_lo)
+ /* Signed '>', GT in x86 */
+ jmp_cond = X86_JG;
+ else
+ /* GT is unsigned '>', JA in x86 */
+ jmp_cond = X86_JA;
+ break;
+ case BPF_JSLT:
+ if (!is_cmp_lo)
+ /* Signed '<', LT in x86 */
+ jmp_cond = X86_JL;
+ else
+ /* LT is unsigned '<', JB in x86 */
+ jmp_cond = X86_JB;
+ break;
+ case BPF_JSGE:
+ if (!is_cmp_lo)
+ /* Signed '>=', GE in x86 */
+ jmp_cond = X86_JGE;
+ else
+ /* GE is unsigned '>=', JAE in x86 */
+ jmp_cond = X86_JAE;
+ break;
+ case BPF_JSLE:
+ if (!is_cmp_lo)
+ /* Signed '<=', LE in x86 */
+ jmp_cond = X86_JLE;
+ else
+ /* LE is unsigned '<=', JBE in x86 */
+ jmp_cond = X86_JBE;
+ break;
+ default: /* to silence GCC warning */
+ jmp_cond = COND_JMP_OPCODE_INVALID;
+ break;
+ }
+
+ return jmp_cond;
+}
Factor out get_cond_jmp_opcode from bpf_jit_comp64.c and use it in bpf_jit_comp64.c instead of open-coding it. Signed-off-by: Tobias Klauser <tklauser@distanz.ch> --- arch/x86/net/Makefile | 2 + arch/x86/net/bpf_jit.h | 4 ++ arch/x86/net/bpf_jit_comp32.c | 71 -------------------------------- arch/x86/net/bpf_jit_comp64.c | 46 ++------------------- arch/x86/net/bpf_jit_core.c | 76 +++++++++++++++++++++++++++++++++++ 5 files changed, 85 insertions(+), 114 deletions(-) create mode 100644 arch/x86/net/bpf_jit_core.c