Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

LoongArch: BPF: Enable trampoline-based tracing for module functions

Remove the previous restrictions that blocked the tracing of kernel
module functions. Fix the issue that previously caused kernel lockups
when attempting to trace module functions.

Before entering the trampoline code, the return address register ra
shall store the address of the next assembly instruction after the
'bl trampoline' instruction, which is the traced function address, and
the register t0 shall store the parent function return address. Refine
the trampoline return logic to ensure that register data remains correct
when returning to both the traced function and the parent function.

Before this patch was applied, the module_attach test in selftests/bpf
encountered a deadlock issue. This was caused by an incorrect jump
address after the trampoline execution, which resulted in an infinite
loop within the module function.

Cc: stable@vger.kernel.org
Fixes: 677e6123e3d2 ("LoongArch: BPF: Disable trampoline for kernel module function trace")
Signed-off-by: Chenghao Duan <duanchenghao@kylinos.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

authored by

Chenghao Duan and committed by
Huacai Chen
26138762 61319d15

+11 -9
+11 -9
arch/loongarch/net/bpf_jit.c
··· 1284 1284 return 0; 1285 1285 } 1286 1286 1287 - return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_T0 : LOONGARCH_GPR_ZERO, (u64)target); 1287 + return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_RA : LOONGARCH_GPR_ZERO, (u64)target); 1288 1288 } 1289 1289 1290 1290 static int emit_call(struct jit_ctx *ctx, u64 addr) ··· 1641 1641 1642 1642 /* To traced function */ 1643 1643 /* Ftrace jump skips 2 NOP instructions */ 1644 - if (is_kernel_text((unsigned long)orig_call)) 1644 + if (is_kernel_text((unsigned long)orig_call) || 1645 + is_module_text_address((unsigned long)orig_call)) 1645 1646 orig_call += LOONGARCH_FENTRY_NBYTES; 1646 1647 /* Direct jump skips 5 NOP instructions */ 1647 1648 else if (is_bpf_text_address((unsigned long)orig_call)) 1648 1649 orig_call += LOONGARCH_BPF_FENTRY_NBYTES; 1649 - /* Module tracing not supported - cause kernel lockups */ 1650 - else if (is_module_text_address((unsigned long)orig_call)) 1651 - return -ENOTSUPP; 1652 1650 1653 1651 if (flags & BPF_TRAMP_F_CALL_ORIG) { 1654 1652 move_addr(ctx, LOONGARCH_GPR_A0, (const u64)im); ··· 1739 1741 emit_insn(ctx, ldd, LOONGARCH_GPR_FP, LOONGARCH_GPR_SP, 0); 1740 1742 emit_insn(ctx, addid, LOONGARCH_GPR_SP, LOONGARCH_GPR_SP, 16); 1741 1743 1742 - if (flags & BPF_TRAMP_F_SKIP_FRAME) 1744 + if (flags & BPF_TRAMP_F_SKIP_FRAME) { 1743 1745 /* return to parent function */ 1744 - emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0); 1745 - else 1746 - /* return to traced function */ 1746 + move_reg(ctx, LOONGARCH_GPR_RA, LOONGARCH_GPR_T0); 1747 1747 emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T0, 0); 1748 + } else { 1749 + /* return to traced function */ 1750 + move_reg(ctx, LOONGARCH_GPR_T1, LOONGARCH_GPR_RA); 1751 + move_reg(ctx, LOONGARCH_GPR_RA, LOONGARCH_GPR_T0); 1752 + emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T1, 0); 1753 + } 1748 1754 } 1749 1755 1750 1756 ret = ctx->idx;