> In emit_bpf_tail_call(), the macro-based jmp_offset calculation relies > on a fragile prediction equation: "tc_ninsn - (ctx->idx - idx0)". This > calculation model utilizes tc_ninsn from the previous pass to estimate > the remaining stride of the active tail call code block. > > Given that the macro relies on stale layout data from a prior pass to > compute the active relative stride, the conditional branches end up > encoding wrong immediate offsets under extra JIT passes. Consequently, > the execution flow leaps into misaligned instruction boundaries, > triggering soft lockups or early loop collapse. > > To fix this issue, drop the pass-dependent macro and the intermediate > variable entirely. Instead, explicitly calculate "jmp_offset" using an > absolute target reference anchor: "ctx->offset[insn + 1] - ctx->idx". > > However, during the initial size-estimation pass, the target address > "ctx->offset[insn + 1]" is not yet populated and will evaluate to 0, > resulting in "jmp_offset = -ctx->idx". For large eBPF programs, this > inflated negative offset would overflow the 16-bit signed immediate > limit of LoongArch conditional branch instructions, causing the range > validation inside emit_tailcall_jmp() to abort the JIT compilation > prematurely. > > To bypass this initialization bottleneck cleanly without changing any > function signatures, leverage the "ctx->image" pointer to safely detect > the initial pass. Since conditional branch instructions on LoongArch > maintain a fixed 4-byte width regardless of the target displacement, > injecting a safe dummy offset (0) when "ctx->image == NULL" preserves > accurate size estimation while preventing 16-bit range check failures. > > Within this new deterministic arithmetic model: > 1) "ctx->offset[insn + 1]" maps directly to the absolute instruction > index of the immediate next eBPF business instruction, serving as > a rock-solid target label. > 2) "ctx->idx" tracks the real-time instruction index of the conditional > branch currently being emitted. > > This guarantees the generated immediate offsets always land precisely > on the next instruction boundary under all multi-pass compilation paths > and all code size dimensions. > > Signed-off-by: Tiezhu Yang This looks like a fix for wrong branch offsets in the tail call path. Should it carry a Fixes: tag? The tc_ninsn macro and the tc_ninsn = insn ? ctx->offset[insn+1] - ctx->offset[insn] : ctx->offset[0]; calculation being removed here were introduced by: Fixes: cd39d9e6b7e4 ("LoongArch: BPF: Fix jump offset calculation in tailcall") This isn't a bug, but could the changelog be tightened? Phrases such as "rock-solid target label", "deterministic arithmetic model", "initialization bottleneck", "eBPF business instruction" and "all code size dimensions" read as fairly ornate for an offset-formula refactor. Could it just state that the old macro derived jmp_offset from a stale prior-pass stride while the new form anchors on ctx->offset[insn + 1], with the ctx->image == NULL guard avoiding a false 16-bit range abort during size estimation? --- AI reviewed your patch. Please fix the bug or email reply why it's not a bug. See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md CI run summary: https://github.com/kernel-patches/bpf/actions/runs/28766636714