All of lore.kernel.org
 help / color / mirror / Atom feed
From: Saket Kumar Bhaskar <skb99@linux.ibm.com>
To: Hari Bathini <hbathini@linux.ibm.com>
Cc: linux-kernel@vger.kernel.org, bpf@vger.kernel.org,
	linuxppc-dev@lists.ozlabs.org, sachinpb@linux.ibm.com,
	venkat88@linux.ibm.com, andrii@kernel.org, eddyz87@gmail.com,
	ast@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev,
	song@kernel.org, yonghong.song@linux.dev,
	john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me,
	haoluo@google.com, jolsa@kernel.org, chleroy@kernel.org,
	maddy@linux.ibm.com, mpe@ellerman.id.au, adubey@linux.ibm.com
Subject: Re: [PATCH v2] powerpc64/bpf: Add powerpc64 JIT support for timed may_goto
Date: Fri, 3 Apr 2026 15:13:15 +0530	[thread overview]
Message-ID: <ac-Ls7nprZCVX-mr@linux.ibm.com> (raw)
In-Reply-To: <3a26c38b-b408-46f4-93d8-0a829e04fb02@linux.ibm.com>

On Fri, Apr 03, 2026 at 01:14:09AM +0530, Hari Bathini wrote:
> 
> 
> On 02/04/26 9:40 pm, Saket Kumar Bhaskar wrote:
> > When verifier sees a timed may_goto instruction, it emits a call to
> > arch_bpf_timed_may_goto() with a stack offset in BPF_REG_AX
> > (powerpc64 R12) and expects the refreshed count value to be returned
> > in the same register. The verifier doesn't save or restore any registers
> > before emitting this call.
> > 
> > arch_bpf_timed_may_goto() should act as a trampoline to call
> > bpf_check_timed_may_goto() with powerpc64 ELF ABI calling convention.
> > 
> > To support this custom calling convention, implement
> > arch_bpf_timed_may_goto() in assembly and make sure BPF caller saved
> > registers are preserved, then call bpf_check_timed_may_goto with
> > the powerpc64 ABI calling convention where first argument and return
> > value both are in R3. Finally, move the result back into BPF_REG_AX(R12)
> > before returning.
> > 
> > Also, introduce bpf_jit_emit_func_call() that computes the offset from
> > kernel_toc_addr(), validates that the target and emits the ADDIS/ADDI
> > sequence to load the function address before performing the indirect
> > branch via MTCTR/BCTRL. The existing code in bpf_jit_emit_func_call_rel()
> > is refactored to use this function.
> > 
> 
> Looks good to me.
> 
> Acked-by: Hari Bathini <hbathini@linux.ibm.com>
> 
> > Signed-off-by: Saket Kumar Bhaskar <skb99@linux.ibm.com>
> > ---
> > This patch has been rebased on top of these 3 patches on powerpc-next in
> > the following sequence:
> > 1. https://lore.kernel.org/bpf/20260401103215.104438-1-adubey@linux.ibm.com/
> > 2. https://lore.kernel.org/bpf/20260401141043.41513-1-adubey@linux.ibm.com/
> > 3. https://lore.kernel.org/bpf/20260401152133.42544-1-adubey@linux.ibm.com/
> > 
> > Changes since v1:
> > - Compile bpf_timed_may_goto.o conditionally for PPC64. (Hari)
> > - Moved reladdr at the beginning of the function. (Hari)
> > - Added error check for bpf_jit_emit_func_call() in
> >    bpf_jit_build_body(). (Hari)
> > - Save registers after 32 bytes as MIN_FRAME_SIZE is 32 bytes for
> >    powerpc ABIv2. (Hari)
> > ---
> >   arch/powerpc/net/Makefile             |  4 ++
> >   arch/powerpc/net/bpf_jit_comp.c       |  5 +++
> >   arch/powerpc/net/bpf_jit_comp64.c     | 62 ++++++++++++++++++++++-----
> >   arch/powerpc/net/bpf_timed_may_goto.S | 57 ++++++++++++++++++++++++
> >   4 files changed, 117 insertions(+), 11 deletions(-)
> >   create mode 100644 arch/powerpc/net/bpf_timed_may_goto.S
> > 
> > diff --git a/arch/powerpc/net/Makefile b/arch/powerpc/net/Makefile
> > index 8e60af32e51e..87395d7e2672 100644
> > --- a/arch/powerpc/net/Makefile
> > +++ b/arch/powerpc/net/Makefile
> > @@ -3,3 +3,7 @@
> >   # Arch-specific network modules
> >   #
> >   obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o bpf_jit_comp$(BITS).o
> > +
> > +ifdef CONFIG_PPC64
> > ++obj-$(CONFIG_BPF_JIT) += bpf_timed_may_goto.o
Apologies, a stray '+' slipped into the patch. I'll send a corrected respin shortly.

-Saket
> > +endif
> > diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> > index 50103b3794fb..9b2b456b0765 100644
> > --- a/arch/powerpc/net/bpf_jit_comp.c
> > +++ b/arch/powerpc/net/bpf_jit_comp.c
> > @@ -537,6 +537,11 @@ bool bpf_jit_supports_subprog_tailcalls(void)
> >   	return IS_ENABLED(CONFIG_PPC64);
> >   }
> > +bool bpf_jit_supports_timed_may_goto(void)
> > +{
> > +	return IS_ENABLED(CONFIG_PPC64);
> > +}
> > +
> >   bool bpf_jit_supports_kfunc_call(void)
> >   {
> >   	return IS_ENABLED(CONFIG_PPC64);
> > diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
> > index db364d9083e7..dab106cae22b 100644
> > --- a/arch/powerpc/net/bpf_jit_comp64.c
> > +++ b/arch/powerpc/net/bpf_jit_comp64.c
> > @@ -451,10 +451,28 @@ void arch_bpf_stack_walk(bool (*consume_fn)(void *, u64, u64, u64), void *cookie
> >   	}
> >   }
> > +static int bpf_jit_emit_func_call(u32 *image, struct codegen_context *ctx, u64 func_addr, int reg)
> > +{
> > +	long reladdr = func_addr - kernel_toc_addr();
> > +
> > +	if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
> > +		pr_err("eBPF: address of %ps out of range of kernel_toc.\n", (void *)func_addr);
> > +		return -ERANGE;
> > +	}
> > +
> > +	EMIT(PPC_RAW_ADDIS(reg, _R2, PPC_HA(reladdr)));
> > +	EMIT(PPC_RAW_ADDI(reg, reg, PPC_LO(reladdr)));
> > +	EMIT(PPC_RAW_MTCTR(reg));
> > +	EMIT(PPC_RAW_BCTRL());
> > +
> > +	return 0;
> > +}
> > +
> >   int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
> >   {
> >   	unsigned long func_addr = func ? ppc_function_entry((void *)func) : 0;
> > -	long reladdr;
> > +	long __maybe_unused reladdr;
> > +	int ret;
> >   	/* bpf to bpf call, func is not known in the initial pass. Emit 5 nops as a placeholder */
> >   	if (!func) {
> > @@ -507,16 +525,9 @@ int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *
> >   	EMIT(PPC_RAW_BCTRL());
> >   #else
> >   	if (core_kernel_text(func_addr)) {
> > -		reladdr = func_addr - kernel_toc_addr();
> > -		if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
> > -			pr_err("eBPF: address of %ps out of range of kernel_toc.\n", (void *)func);
> > -			return -ERANGE;
> > -		}
> > -
> > -		EMIT(PPC_RAW_ADDIS(_R12, _R2, PPC_HA(reladdr)));
> > -		EMIT(PPC_RAW_ADDI(_R12, _R12, PPC_LO(reladdr)));
> > -		EMIT(PPC_RAW_MTCTR(_R12));
> > -		EMIT(PPC_RAW_BCTRL());
> > +		ret = bpf_jit_emit_func_call(image, ctx, func_addr, _R12);
> > +		if (ret)
> > +			return ret;
> >   	} else {
> >   		if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1)) {
> >   			/* func points to the function descriptor */
> > @@ -1755,6 +1766,35 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
> >   			if (ret < 0)
> >   				return ret;
> > +			/*
> > +			 * Call to arch_bpf_timed_may_goto() is emitted by the
> > +			 * verifier and called with custom calling convention with
> > +			 * first argument and return value in BPF_REG_AX (_R12).
> > +			 *
> > +			 * The generic helper or bpf function call emission path
> > +			 * may use the same scratch register as BPF_REG_AX to
> > +			 * materialize the target address. This would clobber AX
> > +			 * and break timed may_goto semantics.
> > +			 *
> > +			 * Emit a minimal indirect call sequence here using a temp
> > +			 * register and skip the normal post-call return-value move.
> > +			 */
> > +
> > +			if (func_addr == (u64)arch_bpf_timed_may_goto) {
> > +				ret = 0;
> > +				if (!IS_ENABLED(CONFIG_PPC_KERNEL_PCREL))
> > +					ret = bpf_jit_emit_func_call(image, ctx, func_addr,
> > +								     tmp1_reg);
> > +
> > +				if (ret || IS_ENABLED(CONFIG_PPC_KERNEL_PCREL)) {
> > +					PPC_LI_ADDR(tmp1_reg, func_addr);
> > +					EMIT(PPC_RAW_MTCTR(tmp1_reg));
> > +					EMIT(PPC_RAW_BCTRL());
> > +				}
> > +
> > +				break;
> > +			}
> > +
> >   			/* Take care of powerpc ABI requirements before kfunc call */
> >   			if (insn[i].src_reg == BPF_PSEUDO_KFUNC_CALL) {
> >   				if (prepare_for_kfunc_call(fp, image, ctx, &insn[i]))
> > diff --git a/arch/powerpc/net/bpf_timed_may_goto.S b/arch/powerpc/net/bpf_timed_may_goto.S
> > new file mode 100644
> > index 000000000000..6fd8b1c9f4ac
> > --- /dev/null
> > +++ b/arch/powerpc/net/bpf_timed_may_goto.S
> > @@ -0,0 +1,57 @@
> > +/* SPDX-License-Identifier: GPL-2.0 */
> > +/* Copyright (c) 2025 IBM Corporation, Saket Kumar Bhaskar <skb99@linux.ibm.com> */
> > +
> > +#include <linux/linkage.h>
> > +#include <asm/ppc_asm.h>
> > +
> > +/*
> > + * arch_bpf_timed_may_goto() trampoline for powerpc64
> > + *
> > + * Custom BPF convention (verifier/JIT):
> > + *	- input:  stack offset in BPF_REG_AX (r12)
> > + *	- output: updated count in BPF_REG_AX (r12)
> > + *
> > + * Call bpf_check_timed_may_goto(ptr) with normal powerpc64 ABI:
> > + * 	- r3 = ptr, return in r3
> > + *
> > + * Preserve BPF regs R0-R5 (mapping: r8, r3-r7).
> > + */
> > +
> > +SYM_FUNC_START(arch_bpf_timed_may_goto)
> > +	/* Prologue: save LR, allocate frame */
> > +	mflr    r0
> > +	std     r0, 16(r1)
> > +	stdu    r1, -112(r1)
> > +
> > +	/* Save BPF registers R0 - R5 (r8, r3-r7) */
> > +	std     r3, 32(r1)
> > +	std     r4, 40(r1)
> > +	std     r5, 48(r1)
> > +	std     r6, 56(r1)
> > +	std     r7, 64(r1)
> > +	std     r8, 72(r1)
> > +
> > +	/*
> > +	 * r3 = BPF_REG_FP + BPF_REG_AX
> > +	 * BPF_REG_FP is r31; BPF_REG_AX is r12 (stack offset in bytes).
> > +	 */
> > +	add     r3, r31, r12
> > +	bl      bpf_check_timed_may_goto
> > +
> > +	/* Put return value back into AX */
> > +	mr      r12, r3
> > +
> > +	/* Restore BPF registers R0 - R5 (r8, r3-r7) */
> > +	ld      r3, 32(r1)
> > +	ld      r4, 40(r1)
> > +	ld      r5, 48(r1)
> > +	ld      r6, 56(r1)
> > +	ld      r7, 64(r1)
> > +	ld      r8, 72(r1)
> > +
> > +	/* Epilogue: pop frame, restore LR, return */
> > +	addi    r1, r1, 112
> > +	ld      r0, 16(r1)
> > +	mtlr    r0
> > +	blr
> > +SYM_FUNC_END(arch_bpf_timed_may_goto)
> 

      reply	other threads:[~2026-04-03  9:44 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-02 16:10 [PATCH v2] powerpc64/bpf: Add powerpc64 JIT support for timed may_goto Saket Kumar Bhaskar
2026-04-02 19:44 ` Hari Bathini
2026-04-03  9:43   ` Saket Kumar Bhaskar [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ac-Ls7nprZCVX-mr@linux.ibm.com \
    --to=skb99@linux.ibm.com \
    --cc=adubey@linux.ibm.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=chleroy@kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=haoluo@google.com \
    --cc=hbathini@linux.ibm.com \
    --cc=john.fastabend@gmail.com \
    --cc=jolsa@kernel.org \
    --cc=kpsingh@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=maddy@linux.ibm.com \
    --cc=martin.lau@linux.dev \
    --cc=mpe@ellerman.id.au \
    --cc=sachinpb@linux.ibm.com \
    --cc=sdf@fomichev.me \
    --cc=song@kernel.org \
    --cc=venkat88@linux.ibm.com \
    --cc=yonghong.song@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.