From 85b6a11252ba7f9631eedcbc6744c6450e6ae8c7 Mon Sep 17 00:00:00 2001 From: Alexei Starovoitov Date: Sat, 31 Oct 2026 21:55:39 +0000 Subject: [PATCH] s390/bpf: Support internal-only MOV instruction to resolve per-CPU addrs The verifier emits BPF_MOV64_PERCPU_REG to turn the address of a per-cpu variable into the address of the copy of this cpu. s390 keeps the per-cpu offset of the cpu in the lowcore. Add it to the register with one insn, the way the JIT reads cpu_nr and current_task for the helpers that it inlines. With bpf_jit_supports_percpu_insn() the verifier inlines the lookup in per-cpu array and per-cpu hash maps, and resolves the address of a value in a per-cpu array. Patch 7 needs the insn for may_goto. Signed-off-by: Alexei Starovoitov Link: https://patch.msgid.link/20261031215543.682284-6-alexei.starovoitov@gmail.com --- arch/s390/net/bpf_jit_comp.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 83da3a00db7e..b6224da9f6e8 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -1005,6 +1005,17 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp, (jit->prg - patch_brc) >> 1; break; } + if (insn_is_mov_percpu_addr(insn)) { + const u64 *percpu_offset = &get_lowcore()->percpu_offset; + + if (dst_reg != src_reg) + /* lgr %dst,%src */ + EMIT4(0xb9040000, dst_reg, src_reg); + /* ag %dst,percpu_offset */ + EMIT6_DISP_LH(0xe3000000, 0x0008, dst_reg, REG_0, REG_0, + (unsigned long)percpu_offset); + break; + } switch (insn->off) { case 0: /* DST = SRC */ /* lgr %dst,%src */ @@ -3114,6 +3125,11 @@ bool bpf_jit_supports_timed_may_goto(void) return true; } +bool bpf_jit_supports_percpu_insn(void) +{ + return true; +} + bool bpf_jit_inlines_helper_call(s32 imm) { switch (imm) {