Commit 124047a8 authored by Russell King's avatar Russell King Committed by Greg Kroah-Hartman

ARM: net: bpf: avoid 'bx' instruction on non-Thumb capable CPUs

commit e9062481 upstream.

Avoid the 'bx' instruction on CPUs that have no support for Thumb and
thus do not implement this instruction by moving the generation of this
opcode to a separate function that selects between:

	bx	reg

and

	mov	pc, reg

according to the capabilities of the CPU.

Fixes: 39c13c20 ("arm: eBPF JIT compiler")
Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 326efb49
...@@ -285,16 +285,20 @@ static inline void emit_mov_i(const u8 rd, u32 val, struct jit_ctx *ctx) ...@@ -285,16 +285,20 @@ static inline void emit_mov_i(const u8 rd, u32 val, struct jit_ctx *ctx)
emit_mov_i_no8m(rd, val, ctx); emit_mov_i_no8m(rd, val, ctx);
} }
static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx) static void emit_bx_r(u8 tgt_reg, struct jit_ctx *ctx)
{ {
ctx->seen |= SEEN_CALL;
#if __LINUX_ARM_ARCH__ < 5
emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
if (elf_hwcap & HWCAP_THUMB) if (elf_hwcap & HWCAP_THUMB)
emit(ARM_BX(tgt_reg), ctx); emit(ARM_BX(tgt_reg), ctx);
else else
emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx); emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx);
}
static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
{
ctx->seen |= SEEN_CALL;
#if __LINUX_ARM_ARCH__ < 5
emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
emit_bx_r(tgt_reg, ctx);
#else #else
emit(ARM_BLX_R(tgt_reg), ctx); emit(ARM_BLX_R(tgt_reg), ctx);
#endif #endif
...@@ -997,7 +1001,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx) ...@@ -997,7 +1001,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
emit_a32_mov_i(tmp2[1], off, false, ctx); emit_a32_mov_i(tmp2[1], off, false, ctx);
emit(ARM_LDR_R(tmp[1], tmp[1], tmp2[1]), ctx); emit(ARM_LDR_R(tmp[1], tmp[1], tmp2[1]), ctx);
emit(ARM_ADD_I(tmp[1], tmp[1], ctx->prologue_bytes), ctx); emit(ARM_ADD_I(tmp[1], tmp[1], ctx->prologue_bytes), ctx);
emit(ARM_BX(tmp[1]), ctx); emit_bx_r(tmp[1], ctx);
/* out: */ /* out: */
if (out_offset == -1) if (out_offset == -1)
...@@ -1166,7 +1170,7 @@ static void build_epilogue(struct jit_ctx *ctx) ...@@ -1166,7 +1170,7 @@ static void build_epilogue(struct jit_ctx *ctx)
emit(ARM_POP(reg_set), ctx); emit(ARM_POP(reg_set), ctx);
/* Return back to the callee function */ /* Return back to the callee function */
if (!(ctx->seen & SEEN_CALL)) if (!(ctx->seen & SEEN_CALL))
emit(ARM_BX(ARM_LR), ctx); emit_bx_r(ARM_LR, ctx);
#endif #endif
} }
......
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