mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
powerpc64/bpf: Add support for bpf trampolines
Add support for bpf_arch_text_poke() and arch_prepare_bpf_trampoline() for 64-bit powerpc. While the code is generic, BPF trampolines are only enabled on 64-bit powerpc. 32-bit powerpc will need testing and some updates. BPF Trampolines adhere to the existing ftrace ABI utilizing a two-instruction profiling sequence, as well as the newer ABI utilizing a three-instruction profiling sequence enabling return with a 'blr'. The trampoline code itself closely follows x86 implementation. BPF prog JIT is extended to mimic 64-bit powerpc approach for ftrace having a single nop at function entry, followed by the function profiling sequence out-of-line and a separate long branch stub for calls to trampolines that are out of range. A dummy_tramp is provided to simplify synchronization similar to arm64. When attaching a bpf trampoline to a bpf prog, we can patch up to three things: - the nop at bpf prog entry to go to the out-of-line stub - the instruction in the out-of-line stub to either call the bpf trampoline directly, or to branch to the long_branch stub. - the trampoline address before the long_branch stub. We do not need any synchronization here since we always have a valid branch target regardless of the order in which the above stores are seen. dummy_tramp ensures that the long_branch stub goes to a valid destination on other cpus, even when the branch to the long_branch stub is seen before the updated trampoline address. However, when detaching a bpf trampoline from a bpf prog, or if changing the bpf trampoline address, we need synchronization to ensure that other cpus can no longer branch into the older trampoline so that it can be safely freed. bpf_tramp_image_put() uses rcu_tasks to ensure all cpus make forward progress, but we still need to ensure that other cpus execute isync (or some CSI) so that they don't go back into the trampoline again. While here, update the stale comment that describes the redzone usage in ppc64 BPF JIT. Signed-off-by: Naveen N Rao <naveen@kernel.org> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://patch.msgid.link/20241030070850.1361304-18-hbathini@linux.ibm.com
This commit is contained in:
committed by
Michael Ellerman
parent
71db948b9d
commit
d243b62b7b
@@ -587,12 +587,26 @@
|
||||
#define PPC_RAW_MTSPR(spr, d) (0x7c0003a6 | ___PPC_RS(d) | __PPC_SPR(spr))
|
||||
#define PPC_RAW_EIEIO() (0x7c0006ac)
|
||||
|
||||
/* bcl 20,31,$+4 */
|
||||
#define PPC_RAW_BCL4() (0x429f0005)
|
||||
#define PPC_RAW_BRANCH(offset) (0x48000000 | PPC_LI(offset))
|
||||
#define PPC_RAW_BL(offset) (0x48000001 | PPC_LI(offset))
|
||||
#define PPC_RAW_TW(t0, a, b) (0x7c000008 | ___PPC_RS(t0) | ___PPC_RA(a) | ___PPC_RB(b))
|
||||
#define PPC_RAW_TRAP() PPC_RAW_TW(31, 0, 0)
|
||||
#define PPC_RAW_SETB(t, bfa) (0x7c000100 | ___PPC_RT(t) | ___PPC_RA((bfa) << 2))
|
||||
|
||||
#ifdef CONFIG_PPC32
|
||||
#define PPC_RAW_STL PPC_RAW_STW
|
||||
#define PPC_RAW_STLU PPC_RAW_STWU
|
||||
#define PPC_RAW_LL PPC_RAW_LWZ
|
||||
#define PPC_RAW_CMPLI PPC_RAW_CMPWI
|
||||
#else
|
||||
#define PPC_RAW_STL PPC_RAW_STD
|
||||
#define PPC_RAW_STLU PPC_RAW_STDU
|
||||
#define PPC_RAW_LL PPC_RAW_LD
|
||||
#define PPC_RAW_CMPLI PPC_RAW_CMPDI
|
||||
#endif
|
||||
|
||||
/* Deal with instructions that older assemblers aren't aware of */
|
||||
#define PPC_BCCTR_FLUSH stringify_in_c(.long PPC_INST_BCCTR_FLUSH)
|
||||
#define PPC_CP_ABORT stringify_in_c(.long PPC_RAW_CP_ABORT)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <asm/types.h>
|
||||
#include <asm/ppc-opcode.h>
|
||||
#include <linux/build_bug.h>
|
||||
|
||||
#ifdef CONFIG_PPC64_ELF_ABI_V1
|
||||
#define FUNCTION_DESCR_SIZE 24
|
||||
@@ -21,6 +22,9 @@
|
||||
|
||||
#define CTX_NIA(ctx) ((unsigned long)ctx->idx * 4)
|
||||
|
||||
#define SZL sizeof(unsigned long)
|
||||
#define BPF_INSN_SAFETY 64
|
||||
|
||||
#define PLANT_INSTR(d, idx, instr) \
|
||||
do { if (d) { (d)[idx] = instr; } idx++; } while (0)
|
||||
#define EMIT(instr) PLANT_INSTR(image, ctx->idx, instr)
|
||||
@@ -81,6 +85,18 @@
|
||||
EMIT(PPC_RAW_ORI(d, d, (uintptr_t)(i) & \
|
||||
0xffff)); \
|
||||
} } while (0)
|
||||
#define PPC_LI_ADDR PPC_LI64
|
||||
|
||||
#ifndef CONFIG_PPC_KERNEL_PCREL
|
||||
#define PPC64_LOAD_PACA() \
|
||||
EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc)))
|
||||
#else
|
||||
#define PPC64_LOAD_PACA() do {} while (0)
|
||||
#endif
|
||||
#else
|
||||
#define PPC_LI64(d, i) BUILD_BUG()
|
||||
#define PPC_LI_ADDR PPC_LI32
|
||||
#define PPC64_LOAD_PACA() BUILD_BUG()
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -165,6 +181,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code
|
||||
u32 *addrs, int pass, bool extra_pass);
|
||||
void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx);
|
||||
void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx);
|
||||
void bpf_jit_build_fentry_stubs(u32 *image, struct codegen_context *ctx);
|
||||
void bpf_jit_realloc_regs(struct codegen_context *ctx);
|
||||
int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -127,13 +127,16 @@ void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Instruction for trampoline attach */
|
||||
EMIT(PPC_RAW_NOP());
|
||||
|
||||
/* Initialize tail_call_cnt, to be skipped if we do tail calls. */
|
||||
if (ctx->seen & SEEN_TAILCALL)
|
||||
EMIT(PPC_RAW_LI(_R4, 0));
|
||||
else
|
||||
EMIT(PPC_RAW_NOP());
|
||||
|
||||
#define BPF_TAILCALL_PROLOGUE_SIZE 4
|
||||
#define BPF_TAILCALL_PROLOGUE_SIZE 8
|
||||
|
||||
if (bpf_has_stack_frame(ctx))
|
||||
EMIT(PPC_RAW_STWU(_R1, _R1, -BPF_PPC_STACKFRAME(ctx)));
|
||||
@@ -198,6 +201,8 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
|
||||
bpf_jit_emit_common_epilogue(image, ctx);
|
||||
|
||||
EMIT(PPC_RAW_BLR());
|
||||
|
||||
bpf_jit_build_fentry_stubs(image, ctx);
|
||||
}
|
||||
|
||||
/* Relative offset needs to be calculated based on final image location */
|
||||
|
||||
@@ -84,7 +84,7 @@ static inline bool bpf_has_stack_frame(struct codegen_context *ctx)
|
||||
}
|
||||
|
||||
/*
|
||||
* When not setting up our own stackframe, the redzone usage is:
|
||||
* When not setting up our own stackframe, the redzone (288 bytes) usage is:
|
||||
*
|
||||
* [ prev sp ] <-------------
|
||||
* [ ... ] |
|
||||
@@ -92,7 +92,7 @@ static inline bool bpf_has_stack_frame(struct codegen_context *ctx)
|
||||
* [ nv gpr save area ] 5*8
|
||||
* [ tail_call_cnt ] 8
|
||||
* [ local_tmp_var ] 16
|
||||
* [ unused red zone ] 208 bytes protected
|
||||
* [ unused red zone ] 224
|
||||
*/
|
||||
static int bpf_jit_stack_local(struct codegen_context *ctx)
|
||||
{
|
||||
@@ -126,6 +126,9 @@ void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Instruction for trampoline attach */
|
||||
EMIT(PPC_RAW_NOP());
|
||||
|
||||
#ifndef CONFIG_PPC_KERNEL_PCREL
|
||||
if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2))
|
||||
EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc)));
|
||||
@@ -200,6 +203,8 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
|
||||
EMIT(PPC_RAW_MR(_R3, bpf_to_ppc(BPF_REG_0)));
|
||||
|
||||
EMIT(PPC_RAW_BLR());
|
||||
|
||||
bpf_jit_build_fentry_stubs(image, ctx);
|
||||
}
|
||||
|
||||
int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
|
||||
@@ -303,7 +308,7 @@ static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 o
|
||||
*/
|
||||
int b2p_bpf_array = bpf_to_ppc(BPF_REG_2);
|
||||
int b2p_index = bpf_to_ppc(BPF_REG_3);
|
||||
int bpf_tailcall_prologue_size = 8;
|
||||
int bpf_tailcall_prologue_size = 12;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_PPC_KERNEL_PCREL) && IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2))
|
||||
bpf_tailcall_prologue_size += 4; /* skip past the toc load */
|
||||
|
||||
Reference in New Issue
Block a user