On Fri, Sep 8, 2023 at 6:28 AM Hari Bathini <hbathini@xxxxxxxxxxxxx> wrote: > > bpf_arch_text_copy is used to dump JITed binary to RX page, allowing > multiple BPF programs to share the same page. Use patch_instruction() > to implement it. > > Signed-off-by: Hari Bathini <hbathini@xxxxxxxxxxxxx> > --- > arch/powerpc/net/bpf_jit_comp.c | 41 ++++++++++++++++++++++++++++++++- > 1 file changed, 40 insertions(+), 1 deletion(-) > > diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c > index 37043dfc1add..4f896222c579 100644 > --- a/arch/powerpc/net/bpf_jit_comp.c > +++ b/arch/powerpc/net/bpf_jit_comp.c > @@ -13,9 +13,12 @@ > #include <linux/netdevice.h> > #include <linux/filter.h> > #include <linux/if_vlan.h> > -#include <asm/kprobes.h> > +#include <linux/memory.h> > #include <linux/bpf.h> > > +#include <asm/kprobes.h> > +#include <asm/code-patching.h> > + > #include "bpf_jit.h" > > static void bpf_jit_fill_ill_insns(void *area, unsigned int size) > @@ -23,6 +26,28 @@ static void bpf_jit_fill_ill_insns(void *area, unsigned int size) > memset32(area, BREAKPOINT_INSTRUCTION, size / 4); > } > > +/* > + * Patch 'len' bytes of instructions from opcode to addr, one instruction > + * at a time. Returns addr on success. ERR_PTR(-EINVAL), otherwise. > + */ > +static void *bpf_patch_instructions(void *addr, void *opcode, size_t len, bool fill_insn) > +{ > + while (len > 0) { > + ppc_inst_t insn = ppc_inst_read(opcode); > + int ilen = ppc_inst_len(insn); > + > + if (patch_instruction(addr, insn)) > + return ERR_PTR(-EINVAL); Is there any reason we have to do this one instruction at a time? I believe Christophe Leroy pointed out the same in an earlier version? Thanks, Song > + > + len -= ilen; > + addr = addr + ilen; > + if (!fill_insn) > + opcode = opcode + ilen; > + } > + > + return addr; > +} > + > int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr) > { > if (!exit_addr || is_offset_in_branch_range(exit_addr - (ctx->idx * 4))) { > @@ -274,3 +299,17 @@ int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct code > ctx->exentry_idx++; > return 0; > } > + > +void *bpf_arch_text_copy(void *dst, void *src, size_t len) > +{ > + void *ret; > + > + if (WARN_ON_ONCE(core_kernel_text((unsigned long)dst))) > + return ERR_PTR(-EINVAL); > + > + mutex_lock(&text_mutex); > + ret = bpf_patch_instructions(dst, src, len, false); > + mutex_unlock(&text_mutex); > + > + return ret; > +}