summaryrefslogtreecommitdiff
path: root/arch/arm64
diff options
context:
space:
mode:
authorZi Shen Lim <zlim.lnx@gmail.com>2014-09-16 21:29:23 +0100
committerCatalin Marinas <catalin.marinas@arm.com>2014-10-20 17:47:03 +0100
commit30d3d94cc3d507a23dcb09e5c365464e4aa9f580 (patch)
tree61915f1797c20cb0c0cca32d97cf81d1734298a5 /arch/arm64
parentd65a634a0acefd6b6e8718e2399b6771ccb17b24 (diff)
arm64: bpf: add 'load 64-bit immediate' instruction
Commit 02ab695bb37e (net: filter: add "load 64-bit immediate" eBPF instruction) introduced a new eBPF instruction. Let's add support for this for arm64 as well. Our arm64 eBPF JIT compiler now passes the new "load 64-bit immediate" test case introduced in the same commit 02ab695bb37e. Signed-off-by: Zi Shen Lim <zlim.lnx@gmail.com> Cc: Will Deacon <will.deacon@arm.com> Cc: David S. Miller <davem@davemloft.net> Cc: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch/arm64')
-rw-r--r--arch/arm64/net/bpf_jit_comp.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/arch/arm64/net/bpf_jit_comp.c b/arch/arm64/net/bpf_jit_comp.c
index 80cc76972798..618d2cdc2f1b 100644
--- a/arch/arm64/net/bpf_jit_comp.c
+++ b/arch/arm64/net/bpf_jit_comp.c
@@ -205,6 +205,12 @@ static void build_epilogue(struct jit_ctx *ctx)
emit(A64_RET(A64_LR), ctx);
}
+/* JITs an eBPF instruction.
+ * Returns:
+ * 0 - successfully JITed an 8-byte eBPF instruction.
+ * >0 - successfully JITed a 16-byte eBPF instruction.
+ * <0 - failed to JIT.
+ */
static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
{
const u8 code = insn->code;
@@ -464,6 +470,27 @@ emit_cond_jmp:
emit(A64_B(jmp_offset), ctx);
break;
+ /* dst = imm64 */
+ case BPF_LD | BPF_IMM | BPF_DW:
+ {
+ const struct bpf_insn insn1 = insn[1];
+ u64 imm64;
+
+ if (insn1.code != 0 || insn1.src_reg != 0 ||
+ insn1.dst_reg != 0 || insn1.off != 0) {
+ /* Note: verifier in BPF core must catch invalid
+ * instructions.
+ */
+ pr_err_once("Invalid BPF_LD_IMM64 instruction\n");
+ return -EINVAL;
+ }
+
+ imm64 = (u64)insn1.imm << 32 | imm;
+ emit_a64_mov_i64(dst, imm64, ctx);
+
+ return 1;
+ }
+
/* LDX: dst = *(size *)(src + off) */
case BPF_LDX | BPF_MEM | BPF_W:
case BPF_LDX | BPF_MEM | BPF_H:
@@ -615,6 +642,10 @@ static int build_body(struct jit_ctx *ctx)
ctx->offset[i] = ctx->idx;
ret = build_insn(insn, ctx);
+ if (ret > 0) {
+ i++;
+ continue;
+ }
if (ret)
return ret;
}