On Wed, Jul 16, 2025 at 08:21:59PM +0800, Hengqi Chen wrote: > On Wed, Jul 9, 2025 at 1:50 PM Chenghao Duan <duanchenghao@xxxxxxxxxx> wrote: > > > > Implement the functions of bpf_arch_text_poke, bpf_arch_text_copy, and > > bpf_arch_text_invalidate on the LoongArch architecture. > > > > On LoongArch, since symbol addresses in the direct mapping > > region cannot be reached via relative jump instructions from the paged > > mapping region, we use the move_imm+jirl instruction pair as absolute > > jump instructions. These require 2-5 instructions, so we reserve 5 NOP > > instructions in the program as placeholders for function jumps. > > > > Co-developed-by: George Guo <guodongtai@xxxxxxxxxx> > > Signed-off-by: George Guo <guodongtai@xxxxxxxxxx> > > Signed-off-by: Chenghao Duan <duanchenghao@xxxxxxxxxx> > > --- > > arch/loongarch/include/asm/inst.h | 1 + > > arch/loongarch/kernel/inst.c | 32 +++++++++++ > > arch/loongarch/net/bpf_jit.c | 90 +++++++++++++++++++++++++++++++ > > 3 files changed, 123 insertions(+) > > > > diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h > > index 2ae96a35d..88bb73e46 100644 > > --- a/arch/loongarch/include/asm/inst.h > > +++ b/arch/loongarch/include/asm/inst.h > > @@ -497,6 +497,7 @@ void arch_simulate_insn(union loongarch_instruction insn, struct pt_regs *regs); > > int larch_insn_read(void *addr, u32 *insnp); > > int larch_insn_write(void *addr, u32 insn); > > int larch_insn_patch_text(void *addr, u32 insn); > > +int larch_insn_text_copy(void *dst, void *src, size_t len); > > > > u32 larch_insn_gen_nop(void); > > u32 larch_insn_gen_b(unsigned long pc, unsigned long dest); > > diff --git a/arch/loongarch/kernel/inst.c b/arch/loongarch/kernel/inst.c > > index 674e3b322..8d6594968 100644 > > --- a/arch/loongarch/kernel/inst.c > > +++ b/arch/loongarch/kernel/inst.c > > @@ -4,6 +4,7 @@ > > */ > > #include <linux/sizes.h> > > #include <linux/uaccess.h> > > +#include <linux/set_memory.h> > > > > #include <asm/cacheflush.h> > > #include <asm/inst.h> > > @@ -218,6 +219,37 @@ int larch_insn_patch_text(void *addr, u32 insn) > > return ret; > > } > > > > +int larch_insn_text_copy(void *dst, void *src, size_t len) > > +{ > > + unsigned long flags; > > + size_t wlen = 0; > > + size_t size; > > + void *ptr; > > + int ret = 0; > > + > > + set_memory_rw((unsigned long)dst, round_up(len, PAGE_SIZE) / PAGE_SIZE); > > + raw_spin_lock_irqsave(&patch_lock, flags); > > + while (wlen < len) { > > + ptr = dst + wlen; > > + size = min_t(size_t, PAGE_SIZE - offset_in_page(ptr), > > + len - wlen); > > + > > + ret = copy_to_kernel_nofault(ptr, src + wlen, size); > > + if (ret) { > > + pr_err("%s: operation failed\n", __func__); > > + break; > > + } > > + wlen += size; > > + } > > Again, why do you do copy_to_kernel_nofault() in a loop ? The while loop processes all sizes. I referred to how ARM64 and RISC-V64 handle this using loops as well. > This larch_insn_text_copy() can be part of the first patch like > larch_insn_gen_{beq,bne}. WDYT ?