On Wed, 23 Sep 2026 09:49:07 -0500
Danish Khateeb <[email protected]> wrote:
> A kprobe single-steps a copy of the probed instruction in
> p->ainsn.insn[]. When the copy is a taken PC-relative branch, its target
> is relative to the copy, and relbranch_fixup() moves it back to the
> probed code. It only recognizes call, BPcc and Bicc, though. For a taken
> BPr (brz, brnz, ...), FBfcc or FBPfcc it keeps the target as is, and the
> kernel continues at the copy's address plus the branch displacement.
>
> GCC often starts a function with a BPr on an argument. For example,
> __se_sys_getcpu() begins with "brz,pn %o0". With a kprobe on it
> ("p:kprobes/kgetcpu __se_sys_getcpu" in kprobe_events), the first
> getcpu(NULL, NULL, NULL) crashes the kernel in QEMU sun4u:
>
> init(1): Kernel illegal instruction [#1]
> TSTATE: 0000004411001603 TPC: fffff800048d63c0 TNPC: fffff8000492631c
> Kernel panic - not syncing: Fatal exception
>
> Add the missing branch formats. BPr is matched with bit 28 clear. The
> CBcond instructions of newer CPUs share its op2 value, but they have no
> delay slot, so a taken one never reaches the single-step breakpoint and
> this function.
>
Sounds reasonable. From kprobes maintainer point of view:
Acked-by: Masami Hiramatsu (Google) <[email protected]>
Thanks,
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: [email protected]
> Assisted-by: LLM
> Signed-off-by: Danish Khateeb <[email protected]>
> ---
> arch/sparc/kernel/kprobes.c | 13 ++++++++-----
> 1 file changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/arch/sparc/kernel/kprobes.c b/arch/sparc/kernel/kprobes.c
> index 191bbaca9921..9a26c57c8d33 100644
> --- a/arch/sparc/kernel/kprobes.c
> +++ b/arch/sparc/kernel/kprobes.c
> @@ -207,12 +207,15 @@ static unsigned long __kprobes relbranch_fixup(u32
> insn, struct kprobe *p,
> if (regs->tnpc == regs->tpc + 0x4UL)
> return real_pc + 0x8UL;
>
> - /* The three cases are call, branch w/prediction,
> - * and traditional branch.
> + /* The cases are call and the branches with a PC-relative
> + * displacement.
> */
> - if ((insn & 0xc0000000) == 0x40000000 ||
> - (insn & 0xc1c00000) == 0x00400000 ||
> - (insn & 0xc1c00000) == 0x00800000) {
> + if ((insn & 0xc0000000) == 0x40000000 || /* call */
> + (insn & 0xc1c00000) == 0x00400000 || /* BPcc */
> + (insn & 0xc1c00000) == 0x00800000 || /* Bicc */
> + (insn & 0xd1c00000) == 0x00c00000 || /* BPr */
> + (insn & 0xc1c00000) == 0x01400000 || /* FBPfcc */
> + (insn & 0xc1c00000) == 0x01800000) { /* FBfcc */
> unsigned long ainsn_addr;
>
> ainsn_addr = (unsigned long) &p->ainsn.insn[0];
> --
> 2.55.0
>
--
Masami Hiramatsu (Google) <[email protected]>