* [PATCH v3 1/2] LoongArch: BPF: Support internal-only MOV to resolve per-CPU addrs
2026-08-04 15:39 [PATCH v3 0/2] LoongArch: BPF: per-CPU address resolution and timed may_goto George Guo
@ 2026-08-04 15:39 ` George Guo
2026-08-04 15:39 ` [PATCH v3 2/2] LoongArch: BPF: Add timed may_goto support George Guo
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: George Guo @ 2026-08-04 15:39 UTC (permalink / raw)
To: chenhuacai, yangtiezhu, hengqi.chen, ast, daniel, andrii
Cc: kernel, martin.lau, eddyz87, memxor, song, yonghong.song, jolsa,
guodongtai, bpf, loongarch, linux-kernel
From: George Guo <guodongtai@kylinos.cn>
Support the internal-only BPF_MOV instruction that resolves the absolute
address of per-CPU data from its per-CPU offset. This instruction is used
only for internal inlining optimizations between the BPF verifier and the
JITs (e.g. inlining bpf_get_smp_processor_id() and per-CPU map lookups).
LoongArch keeps the per-CPU offset of the current CPU in $r21
(__my_cpu_offset), so resolving a per-CPU address only requires adding
$r21 to the source register holding the per-CPU offset. Advertise the
capability via bpf_jit_supports_percpu_insn().
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
arch/loongarch/include/asm/inst.h | 1 +
arch/loongarch/net/bpf_jit.c | 14 ++++++++++++++
2 files changed, 15 insertions(+)
diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h
index 54f35bcd0f66..585667e361c2 100644
--- a/arch/loongarch/include/asm/inst.h
+++ b/arch/loongarch/include/asm/inst.h
@@ -411,6 +411,7 @@ enum loongarch_gpr {
LOONGARCH_GPR_T6,
LOONGARCH_GPR_T7,
LOONGARCH_GPR_T8,
+ LOONGARCH_GPR_U0 = 21, /* Kernel per-CPU base register ($r21) */
LOONGARCH_GPR_FP = 22,
LOONGARCH_GPR_S0 = 23,
LOONGARCH_GPR_S1,
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index aa88f904a5ca..b8dd956d46bd 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -722,6 +722,15 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
move_reg(ctx, dst, t1);
break;
}
+ if (insn_is_mov_percpu_addr(insn)) {
+ if (dst != src)
+ move_reg(ctx, dst, src);
+#ifdef CONFIG_SMP
+ /* dst += __my_cpu_offset, held in $r21 */
+ emit_insn(ctx, addd, dst, dst, LOONGARCH_GPR_U0);
+#endif
+ break;
+ }
switch (off) {
case 0:
move_reg(ctx, dst, src);
@@ -2376,6 +2385,11 @@ bool bpf_jit_supports_ptr_xchg(void)
return true;
}
+bool bpf_jit_supports_percpu_insn(void)
+{
+ return true;
+}
+
/* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */
bool bpf_jit_supports_subprog_tailcalls(void)
{
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH v3 2/2] LoongArch: BPF: Add timed may_goto support
2026-08-04 15:39 [PATCH v3 0/2] LoongArch: BPF: per-CPU address resolution and timed may_goto George Guo
2026-08-04 15:39 ` [PATCH v3 1/2] LoongArch: BPF: Support internal-only MOV to resolve per-CPU addrs George Guo
@ 2026-08-04 15:39 ` George Guo
2026-08-05 7:11 ` [PATCH v3 0/2] LoongArch: BPF: per-CPU address resolution and timed may_goto Huacai Chen
2026-08-06 12:22 ` Tiezhu Yang
3 siblings, 0 replies; 6+ messages in thread
From: George Guo @ 2026-08-04 15:39 UTC (permalink / raw)
To: chenhuacai, yangtiezhu, hengqi.chen, ast, daniel, andrii
Cc: kernel, martin.lau, eddyz87, memxor, song, yonghong.song, jolsa,
guodongtai, bpf, loongarch, linux-kernel
From: George Guo <guodongtai@kylinos.cn>
Implement arch_bpf_timed_may_goto() and advertise it through
bpf_jit_supports_timed_may_goto() so the verifier lowers may_goto into
the timed variant: instead of a fixed iteration counter, the loop is
bounded by a wall-clock timeout maintained in a per-loop stack slot.
arch_bpf_timed_may_goto() uses a custom calling convention: the verifier
passes the count/timestamp stack offset in BPF_REG_AX and expects the
updated count back in the same register. The JIT call path therefore skips
the usual 'BPF_REG_0 = C return value' move for this helper.
Signed-off-by: George Guo <guodongtai@kylinos.cn>
---
arch/loongarch/net/Makefile | 2 +-
arch/loongarch/net/bpf_jit.c | 13 ++++++-
arch/loongarch/net/bpf_timed_may_goto.S | 47 +++++++++++++++++++++++++
3 files changed, 60 insertions(+), 2 deletions(-)
create mode 100644 arch/loongarch/net/bpf_timed_may_goto.S
diff --git a/arch/loongarch/net/Makefile b/arch/loongarch/net/Makefile
index 1ec12a0c324a..8d9ddb48f9ea 100644
--- a/arch/loongarch/net/Makefile
+++ b/arch/loongarch/net/Makefile
@@ -4,4 +4,4 @@
#
# Copyright (C) 2022 Loongson Technology Corporation Limited
#
-obj-$(CONFIG_BPF_JIT) += bpf_jit.o
+obj-$(CONFIG_BPF_JIT) += bpf_jit.o bpf_timed_may_goto.o
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index b8dd956d46bd..004a139e0f49 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -1192,7 +1192,13 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
move_addr(ctx, t1, func_addr);
emit_insn(ctx, jirl, LOONGARCH_GPR_RA, t1, 0);
- if (insn->src_reg != BPF_PSEUDO_CALL)
+ /*
+ * Call to arch_bpf_timed_may_goto() uses a custom calling
+ * convention with the argument and return value in BPF_REG_AX,
+ * so skip moving the C return value into BPF_REG_0.
+ */
+ if (insn->src_reg != BPF_PSEUDO_CALL &&
+ func_addr != (u64)arch_bpf_timed_may_goto)
move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_A0);
break;
@@ -2390,6 +2396,11 @@ bool bpf_jit_supports_percpu_insn(void)
return true;
}
+bool bpf_jit_supports_timed_may_goto(void)
+{
+ return true;
+}
+
/* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */
bool bpf_jit_supports_subprog_tailcalls(void)
{
diff --git a/arch/loongarch/net/bpf_timed_may_goto.S b/arch/loongarch/net/bpf_timed_may_goto.S
new file mode 100644
index 000000000000..8a4c15418998
--- /dev/null
+++ b/arch/loongarch/net/bpf_timed_may_goto.S
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Author: George Guo <guodongtai@kylinos.cn>
+ * Copyright (C) 2026 KylinSoft Corporation.
+ */
+
+#include <asm/asmmacro.h>
+#include <asm/regdef.h>
+#include <linux/export.h>
+#include <linux/linkage.h>
+
+SYM_FUNC_START(arch_bpf_timed_may_goto)
+ addi.d sp, sp, -64
+ st.d ra, sp, 56
+
+ /* Save BPF registers R0 - R5 (a5, a0 - a4) */
+ st.d a5, sp, 8
+ st.d a0, sp, 16
+ st.d a1, sp, 24
+ st.d a2, sp, 32
+ st.d a3, sp, 40
+ st.d a4, sp, 48
+
+ /*
+ * BPF_REG_AX (t0) holds the offset passed in by the verifier; add it
+ * to BPF_REG_FP (s4) to get the pointer to the count and timestamp,
+ * then pass it as the first argument in a0.
+ *
+ * The verifier emits a load using FP right before this call, so
+ * BPF_REG_FP (s4) is always set up by the JIT in this case.
+ */
+ add.d a0, t0, s4
+ bl bpf_check_timed_may_goto
+ /* BPF_REG_AX (t0) will be stored into count, so move the return value to it. */
+ move t0, a0
+
+ ld.d ra, sp, 56
+ ld.d a5, sp, 8
+ ld.d a0, sp, 16
+ ld.d a1, sp, 24
+ ld.d a2, sp, 32
+ ld.d a3, sp, 40
+ ld.d a4, sp, 48
+ addi.d sp, sp, 64
+
+ jr ra
+SYM_FUNC_END(arch_bpf_timed_may_goto)
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH v3 0/2] LoongArch: BPF: per-CPU address resolution and timed may_goto
2026-08-04 15:39 [PATCH v3 0/2] LoongArch: BPF: per-CPU address resolution and timed may_goto George Guo
2026-08-04 15:39 ` [PATCH v3 1/2] LoongArch: BPF: Support internal-only MOV to resolve per-CPU addrs George Guo
2026-08-04 15:39 ` [PATCH v3 2/2] LoongArch: BPF: Add timed may_goto support George Guo
@ 2026-08-05 7:11 ` Huacai Chen
2026-08-05 9:10 ` George Guo
2026-08-06 12:22 ` Tiezhu Yang
3 siblings, 1 reply; 6+ messages in thread
From: Huacai Chen @ 2026-08-05 7:11 UTC (permalink / raw)
To: George Guo
Cc: yangtiezhu, hengqi.chen, ast, daniel, andrii, kernel, martin.lau,
eddyz87, memxor, song, yonghong.song, jolsa, guodongtai, bpf,
loongarch, linux-kernel
Hi, George,
In V1 it is independent,
In V2 it is part of
https://lore.kernel.org/loongarch/20260702022322.51033-1-dongtai.guo@linux.dev/T/#t
In V3 it is independent again.
What do you want? You can ask Tiezhu and Hengqi to review your
patches, but don't do such confusing things.
Huacai
On Tue, Aug 4, 2026 at 11:46 PM George Guo <dongtai.guo@linux.dev> wrote:
>
> These are the first two patches of the LoongArch BPF JIT feature work,
> sent on their own to make review easier. The remaining pieces
> (per-program private stacks, exceptions/bpf_throw, sign-extending loads
> and atomics on arena pointers, and the matching selftests) will follow in
> a later series.
>
> Both patches are independent of each other. They apply on top of Chenguang
> Zhao's "LoongArch bpf kptr xchg inline support" v4 series:
>
> https://lore.kernel.org/all/20260729022837.355549-1-chenguang.zhao@linux.dev/
>
> Patch 1 adds the internal-only BPF MOV that resolves a per-CPU offset to
> the current CPU's address, advertised through
> bpf_jit_supports_percpu_insn(). LoongArch keeps the current CPU's per-CPU
> base in $r21 (__my_cpu_offset), so the resolution is a single add.
> Exercised by the cpumask and percpu_alloc selftests.
>
> Patch 2 implements arch_bpf_timed_may_goto() and advertises it, so the
> verifier lowers may_goto to its timed variant, which bounds the loop by a
> wall-clock timeout kept in a per-loop stack slot. It uses a custom calling
> convention: the count/timestamp stack offset is passed in BPF_REG_AX and
> returned there, so the JIT call path skips the usual "BPF_REG_0 = return
> value" move for this helper. Exercised by the iters selftests.
>
> Selftest results (all PASS):
>
> Feature Test(s)
> --------------------------------------------------------------
> 1 internal-only MOV (percpu) cpumask, percpu_alloc
> 2 timed may_goto iters
>
> $ sudo ./test_progs -t cpumask
> ...
> Summary: 1/35 PASSED, 0 SKIPPED, 0 FAILED
>
> $ sudo ./test_progs -t percpu_alloc
> ...
> Summary: 1/18 PASSED, 0 SKIPPED, 0 FAILED
>
> $ sudo ./test_progs -t iters
> ...
> Summary: 1/93 PASSED, 0 SKIPPED, 0 FAILED
>
> Based on loongarch-next:
> https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson.git/log/?h=loongarch-next
>
> These two patches are split from the full v2 series (11 patches):
> https://lore.kernel.org/all/20260702022322.51033-1-dongtai.guo@linux.dev/
>
> George Guo (2):
> LoongArch: BPF: Support internal-only MOV to resolve per-CPU addrs
> LoongArch: BPF: Add timed may_goto support
>
> arch/loongarch/include/asm/inst.h | 1 +
> arch/loongarch/net/Makefile | 2 +-
> arch/loongarch/net/bpf_jit.c | 27 +++++++++++++-
> arch/loongarch/net/bpf_timed_may_goto.S | 47 +++++++++++++++++++++++++
> 4 files changed, 75 insertions(+), 2 deletions(-)
> create mode 100644 arch/loongarch/net/bpf_timed_may_goto.S
>
> --
> 2.53.0
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 0/2] LoongArch: BPF: per-CPU address resolution and timed may_goto
2026-08-05 7:11 ` [PATCH v3 0/2] LoongArch: BPF: per-CPU address resolution and timed may_goto Huacai Chen
@ 2026-08-05 9:10 ` George Guo
0 siblings, 0 replies; 6+ messages in thread
From: George Guo @ 2026-08-05 9:10 UTC (permalink / raw)
To: chenhuacai
Cc: yangtiezhu, hengqi.chen, ast, daniel, andrii, kernel, martin.lau,
eddyz87, memxor, song, yonghong.song, jolsa, guodongtai, bpf,
loongarch, linux-kernel
Hi Huacai,
On Wed, Aug 5, 2026 at 3:11 PM, Huacai Chen <chenhuacai@kernel.org> wrote:
> In V1 it is independent,
> In V2 it is part of [...] the 11-patch series
> In V3 it is independent again.
>
> What do you want?
You are right that the v1 -> v2 -> v3 shape looks inconsistent. The plan
has always been incremental: Tiezhu suggested sending this work as small,
stacked series -- A first, then B rebased on A, then C on B -- so each
round stays small enough to review carefully. My v2 bundled all 11 patches
to show the full picture, but that was too large to review effectively, so
v3 goes back to the incremental approach.
Concretely, this 2-patch series (per-CPU MOV + timed may_goto) is A. The
remaining pieces -- private stack, exceptions/bpf_throw, arena LDSX and
atomics, and the matching selftests -- will follow as separate series
stacked on top of it. The structure stays incremental from here.
> You can ask Tiezhu and Hengqi to review your patches, but don't do such
> confusing things.
Understood. I will keep the split stable and ask Tiezhu and Hengqi to
review this batch.
Thanks,
George
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v3 0/2] LoongArch: BPF: per-CPU address resolution and timed may_goto
2026-08-04 15:39 [PATCH v3 0/2] LoongArch: BPF: per-CPU address resolution and timed may_goto George Guo
` (2 preceding siblings ...)
2026-08-05 7:11 ` [PATCH v3 0/2] LoongArch: BPF: per-CPU address resolution and timed may_goto Huacai Chen
@ 2026-08-06 12:22 ` Tiezhu Yang
3 siblings, 0 replies; 6+ messages in thread
From: Tiezhu Yang @ 2026-08-06 12:22 UTC (permalink / raw)
To: George Guo, chenhuacai, hengqi.chen, ast, daniel, andrii
Cc: kernel, martin.lau, eddyz87, memxor, song, yonghong.song, jolsa,
guodongtai, bpf, loongarch, linux-kernel
On 2026/8/4 下午11:39, George Guo wrote:
> These are the first two patches of the LoongArch BPF JIT feature work,
> sent on their own to make review easier. The remaining pieces
> (per-program private stacks, exceptions/bpf_throw, sign-extending loads
> and atomics on arena pointers, and the matching selftests) will follow in
> a later series.
The patches apply cleanly on top of Chenguang's series.
The following selftests passed on LoongArch:
# ./test_progs -t cpumask
# ./test_progs -t percpu_alloc
# ./test_progs -t iters
Acked-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Tested-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Thanks,
Tiezhu
^ permalink raw reply [flat|nested] 6+ messages in thread