Implement the bpf_arch_text_poke function for 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.
Signed-off-by: George Guo <guodongtai@kylinos.cn>
Signed-off-by: Chenghao Duan <duanchenghao@kylinos.cn>
---
arch/loongarch/net/bpf_jit.c | 64 ++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index ea357a3ed..0e31d4d66 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -4,6 +4,7 @@
*
* Copyright (C) 2022 Loongson Technology Corporation Limited
*/
+#include <linux/memory.h>
#include "bpf_jit.h"
#define REG_TCC LOONGARCH_GPR_A6
@@ -1351,3 +1352,66 @@ bool bpf_jit_supports_subprog_tailcalls(void)
{
return true;
}
+
+static int emit_jump_and_link(struct jit_ctx *ctx, u8 rd, u64 ip, u64 target)
+{
+ s64 offset = (s64)(target - ip);
+
+ if (offset && (offset >= -SZ_128M && offset < SZ_128M)) {
+ emit_insn(ctx, bl, offset >> 2);
+ } else {
+ move_imm(ctx, LOONGARCH_GPR_T1, target, false);
+ emit_insn(ctx, jirl, rd, LOONGARCH_GPR_T1, 0);
+ }
+
+ return 0;
+}
+
+static int gen_jump_or_nops(void *target, void *ip, u32 *insns, bool is_call)
+{
+ s64 off = 0;
+ struct jit_ctx ctx;
+
+ ctx.idx = 0;
+ ctx.image = (union loongarch_instruction *)insns;
+
+ if (!target) {
+ emit_insn((&ctx), NOP);
+ emit_insn((&ctx), NOP);
+ return 0;
+ }
+
+ off = (s64)(target - ip);
+ return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_T0 : LOONGARCH_GPR_ZERO,
+ (unsigned long)ip, (unsigned long)target);
+}
+
+int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
+ void *old_addr, void *new_addr)
+{
+ u32 old_insns[5] = {[0 ... 4] = INSN_NOP};
+ u32 new_insns[5] = {[0 ... 4] = INSN_NOP};
+ bool is_call = poke_type == BPF_MOD_CALL;
+ int ret;
+
+ if (!is_kernel_text((unsigned long)ip) &&
+ !is_bpf_text_address((unsigned long)ip))
+ return -ENOTSUPP;
+
+ ret = gen_jump_or_nops(old_addr, ip, old_insns, is_call);
+ if (ret)
+ return ret;
+
+ if (memcmp(ip, old_insns, 5 * 4))
+ return -EFAULT;
+
+ ret = gen_jump_or_nops(new_addr, ip, new_insns, is_call);
+ if (ret)
+ return ret;
+
+ mutex_lock(&text_mutex);
+ if (memcmp(ip, new_insns, 5 * 4))
+ ret = larch_insn_text_copy(ip, new_insns, 5 * 4);
+ mutex_unlock(&text_mutex);
+ return ret;
+}
--
2.25.1
Hi Chenghao, kernel test robot noticed the following build warnings: [auto build test WARNING on bpf-next/net] [also build test WARNING on bpf-next/master bpf/master linus/master v6.16-rc1 next-20250611] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Chenghao-Duan/LoongArch-Support-fixmap/20250611-133843 base: https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git net patch link: https://lore.kernel.org/r/20250611053625.352091-4-duanchenghao%40kylinos.cn patch subject: [PATCH v1 3/5] LoongArch: BPF: Add bpf_arch_text_poke support for Loongarch config: loongarch-randconfig-002-20250612 (https://download.01.org/0day-ci/archive/20250612/202506120407.Dqc4kJYr-lkp@intel.com/config) compiler: loongarch64-linux-gcc (GCC) 12.4.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250612/202506120407.Dqc4kJYr-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202506120407.Dqc4kJYr-lkp@intel.com/ All warnings (new ones prefixed by >>): arch/loongarch/net/bpf_jit.c: In function 'gen_jump_or_nops': >> arch/loongarch/net/bpf_jit.c:1380:13: warning: variable 'off' set but not used [-Wunused-but-set-variable] 1380 | s64 off = 0; | ^~~ vim +/off +1380 arch/loongarch/net/bpf_jit.c 1377 1378 static int gen_jump_or_nops(void *target, void *ip, u32 *insns, bool is_call) 1379 { > 1380 s64 off = 0; 1381 struct jit_ctx ctx; 1382 1383 ctx.idx = 0; 1384 ctx.image = (union loongarch_instruction *)insns; 1385 1386 if (!target) { 1387 emit_insn((&ctx), NOP); 1388 emit_insn((&ctx), NOP); 1389 return 0; 1390 } 1391 1392 off = (s64)(target - ip); 1393 return emit_jump_and_link(&ctx, is_call ? LOONGARCH_GPR_T0 : LOONGARCH_GPR_ZERO, 1394 (unsigned long)ip, (unsigned long)target); 1395 } 1396 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
© 2016 - 2025 Red Hat, Inc.