aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2018-01-13 06:35:15 -0500
committerRussell King <rmk+kernel@armlinux.org.uk>2018-01-17 14:35:22 -0500
commite9062481824384f00299971f923fecf6b3668001 (patch)
tree9eb1a903130c504a325c754051c6be9c27c8088c
parent36b0cb84ee858f02c256d26f0cb4229c78e3399e (diff)
ARM: net: bpf: avoid 'bx' instruction on non-Thumb capable CPUs
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: 39c13c204bb1 ("arm: eBPF JIT compiler") Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--arch/arm/net/bpf_jit_32.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index c199990e12b6..4efb3743a89e 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -285,16 +285,20 @@ static inline void emit_mov_i(const u8 rd, u32 val, struct jit_ctx *ctx)
285 emit_mov_i_no8m(rd, val, ctx); 285 emit_mov_i_no8m(rd, val, ctx);
286} 286}
287 287
288static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx) 288static void emit_bx_r(u8 tgt_reg, struct jit_ctx *ctx)
289{ 289{
290 ctx->seen |= SEEN_CALL;
291#if __LINUX_ARM_ARCH__ < 5
292 emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
293
294 if (elf_hwcap & HWCAP_THUMB) 290 if (elf_hwcap & HWCAP_THUMB)
295 emit(ARM_BX(tgt_reg), ctx); 291 emit(ARM_BX(tgt_reg), ctx);
296 else 292 else
297 emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx); 293 emit(ARM_MOV_R(ARM_PC, tgt_reg), ctx);
294}
295
296static inline void emit_blx_r(u8 tgt_reg, struct jit_ctx *ctx)
297{
298 ctx->seen |= SEEN_CALL;
299#if __LINUX_ARM_ARCH__ < 5
300 emit(ARM_MOV_R(ARM_LR, ARM_PC), ctx);
301 emit_bx_r(tgt_reg, ctx);
298#else 302#else
299 emit(ARM_BLX_R(tgt_reg), ctx); 303 emit(ARM_BLX_R(tgt_reg), ctx);
300#endif 304#endif
@@ -997,7 +1001,7 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
997 emit_a32_mov_i(tmp2[1], off, false, ctx); 1001 emit_a32_mov_i(tmp2[1], off, false, ctx);
998 emit(ARM_LDR_R(tmp[1], tmp[1], tmp2[1]), ctx); 1002 emit(ARM_LDR_R(tmp[1], tmp[1], tmp2[1]), ctx);
999 emit(ARM_ADD_I(tmp[1], tmp[1], ctx->prologue_bytes), ctx); 1003 emit(ARM_ADD_I(tmp[1], tmp[1], ctx->prologue_bytes), ctx);
1000 emit(ARM_BX(tmp[1]), ctx); 1004 emit_bx_r(tmp[1], ctx);
1001 1005
1002 /* out: */ 1006 /* out: */
1003 if (out_offset == -1) 1007 if (out_offset == -1)
@@ -1166,7 +1170,7 @@ static void build_epilogue(struct jit_ctx *ctx)
1166 emit(ARM_POP(reg_set), ctx); 1170 emit(ARM_POP(reg_set), ctx);
1167 /* Return back to the callee function */ 1171 /* Return back to the callee function */
1168 if (!(ctx->seen & SEEN_CALL)) 1172 if (!(ctx->seen & SEEN_CALL))
1169 emit(ARM_BX(ARM_LR), ctx); 1173 emit_bx_r(ARM_LR, ctx);
1170#endif 1174#endif
1171} 1175}
1172 1176