4.14-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Russell King <[email protected]>

commit e9062481824384f00299971f923fecf6b3668001 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: 39c13c204bb1 ("arm: eBPF JIT compiler")
Signed-off-by: Russell King <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
 arch/arm/net/bpf_jit_32.c |   18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

--- 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 r
                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)
                emit(ARM_BX(tgt_reg), ctx);
        else
                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
        emit(ARM_BLX_R(tgt_reg), ctx);
 #endif
@@ -997,7 +1001,7 @@ static int emit_bpf_tail_call(struct jit
        emit_a32_mov_i(tmp2[1], off, false, 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_BX(tmp[1]), ctx);
+       emit_bx_r(tmp[1], ctx);
 
        /* out: */
        if (out_offset == -1)
@@ -1166,7 +1170,7 @@ static void build_epilogue(struct jit_ct
        emit(ARM_POP(reg_set), ctx);
        /* Return back to the callee function */
        if (!(ctx->seen & SEEN_CALL))
-               emit(ARM_BX(ARM_LR), ctx);
+               emit_bx_r(ARM_LR, ctx);
 #endif
 }
 


Reply via email to