mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 08:43:31 +00:00
powerpc64/bpf: Fold bpf_jit_emit_func_call_hlp() into bpf_jit_emit_func_call_rel()
Commit 61688a82e0
("powerpc/bpf: enable kfunc call") enhanced
bpf_jit_emit_func_call_hlp() to handle calls out to module region, where
bpf progs are generated. The only difference now between
bpf_jit_emit_func_call_hlp() and bpf_jit_emit_func_call_rel() is in
handling of the initial pass where target function address is not known.
Fold that logic into bpf_jit_emit_func_call_hlp() and rename it to
bpf_jit_emit_func_call_rel() to simplify bpf function call JIT code.
We don't actually need to load/restore TOC across a call out to a
different kernel helper or to a different bpf program since they all
work with the kernel TOC. We only need to do it if we have to call out
to a module function. So, guard TOC load/restore with appropriate
conditions.
Signed-off-by: Naveen N Rao <naveen@kernel.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://patch.msgid.link/20241030070850.1361304-10-hbathini@linux.ibm.com
This commit is contained in:
parent
ed6144656b
commit
9670f6d209
1 changed files with 17 additions and 44 deletions
|
@ -202,14 +202,22 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
|
|||
EMIT(PPC_RAW_BLR());
|
||||
}
|
||||
|
||||
static int
|
||||
bpf_jit_emit_func_call_hlp(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
|
||||
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;
|
||||
|
||||
if (WARN_ON_ONCE(!kernel_text_address(func_addr)))
|
||||
return -EINVAL;
|
||||
/* bpf to bpf call, func is not known in the initial pass. Emit 5 nops as a placeholder */
|
||||
if (!func) {
|
||||
for (int i = 0; i < 5; i++)
|
||||
EMIT(PPC_RAW_NOP());
|
||||
/* elfv1 needs an additional instruction to load addr from descriptor */
|
||||
if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1))
|
||||
EMIT(PPC_RAW_NOP());
|
||||
EMIT(PPC_RAW_MTCTR(_R12));
|
||||
EMIT(PPC_RAW_BCTRL());
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_KERNEL_PCREL
|
||||
reladdr = func_addr - local_paca->kernelbase;
|
||||
|
@ -266,7 +274,8 @@ bpf_jit_emit_func_call_hlp(u32 *image, u32 *fimage, struct codegen_context *ctx,
|
|||
* We can clobber r2 since we get called through a
|
||||
* function pointer (so caller will save/restore r2).
|
||||
*/
|
||||
EMIT(PPC_RAW_LD(_R2, bpf_to_ppc(TMP_REG_2), 8));
|
||||
if (is_module_text_address(func_addr))
|
||||
EMIT(PPC_RAW_LD(_R2, bpf_to_ppc(TMP_REG_2), 8));
|
||||
} else {
|
||||
PPC_LI64(_R12, func);
|
||||
EMIT(PPC_RAW_MTCTR(_R12));
|
||||
|
@ -276,46 +285,14 @@ bpf_jit_emit_func_call_hlp(u32 *image, u32 *fimage, struct codegen_context *ctx,
|
|||
* Load r2 with kernel TOC as kernel TOC is used if function address falls
|
||||
* within core kernel text.
|
||||
*/
|
||||
EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc)));
|
||||
if (is_module_text_address(func_addr))
|
||||
EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc)));
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
|
||||
{
|
||||
unsigned int i, ctx_idx = ctx->idx;
|
||||
|
||||
if (WARN_ON_ONCE(func && is_module_text_address(func)))
|
||||
return -EINVAL;
|
||||
|
||||
/* skip past descriptor if elf v1 */
|
||||
func += FUNCTION_DESCR_SIZE;
|
||||
|
||||
/* Load function address into r12 */
|
||||
PPC_LI64(_R12, func);
|
||||
|
||||
/* For bpf-to-bpf function calls, the callee's address is unknown
|
||||
* until the last extra pass. As seen above, we use PPC_LI64() to
|
||||
* load the callee's address, but this may optimize the number of
|
||||
* instructions required based on the nature of the address.
|
||||
*
|
||||
* Since we don't want the number of instructions emitted to increase,
|
||||
* we pad the optimized PPC_LI64() call with NOPs to guarantee that
|
||||
* we always have a five-instruction sequence, which is the maximum
|
||||
* that PPC_LI64() can emit.
|
||||
*/
|
||||
if (!image)
|
||||
for (i = ctx->idx - ctx_idx; i < 5; i++)
|
||||
EMIT(PPC_RAW_NOP());
|
||||
|
||||
EMIT(PPC_RAW_MTCTR(_R12));
|
||||
EMIT(PPC_RAW_BCTRL());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out)
|
||||
{
|
||||
/*
|
||||
|
@ -1102,11 +1079,7 @@ emit_clear:
|
|||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (func_addr_fixed)
|
||||
ret = bpf_jit_emit_func_call_hlp(image, fimage, ctx, func_addr);
|
||||
else
|
||||
ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr);
|
||||
|
||||
ret = bpf_jit_emit_func_call_rel(image, fimage, ctx, func_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue