From nobody Sat Jun 27 16:57:08 2026 Received: from out-174.mta0.migadu.com (out-174.mta0.migadu.com [91.218.175.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C3205371D15 for ; Mon, 22 Jun 2026 14:36:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139020; cv=none; b=S0mJqT7+S30WvZOp/0zuiUn5+QH29bUFKcT7KS4nnsMs3PRrFZ9J5FbvXV1vBEyR6ZlaesNczM7DCoOXRuE4w4MFn7IdZRSsY5VirmsCBoeAI6TDncf0sJ+ZUX5NNbZ2lSDH9oSdmTEh+nJTBujO1m0jZFcaJNh9RD8z9Hia3qY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139020; c=relaxed/simple; bh=fjZudWesO1UlAp53hzZRyS8evEAa3LCYMqIqufGTmHk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FUkWJAvQVeP0oN9Xka398ynL6MNw2gqi2EmikFG1bNoRj97wyc6Aa5tjpfEEo2ZTJTMuWu+UqXbQGPuXW/2VAYF6u3fJt1gklkDpz4XQ6GKT/ME48IlrdcuxhBk32BjTwut54riVcnqpD3psWaWASc6olid8Yhxxj2X89LPFSFA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=iGYd0Gup; arc=none smtp.client-ip=91.218.175.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="iGYd0Gup" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139016; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=E68CDBhjchU1RM2SbBPGlwnnz5USBgSAl5d6YNwvDtE=; b=iGYd0Gupushm0yTVKwvuAdUg8r8ex6U8KwseQ2zvQ6KsNTOgSPMkZcZytIznluxRd25yaU uzrK+XIQvCBHWoykrvBtyFVa6kxcrl80JVhIi+eKuZ4gILxEPdmIeQcl/AI/sS5qMuNViK pq/FzEs3/R5uwzC8bvUUPtPVCSQz5hM= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 01/11] bpf: Drop duplicate blank lines in verifier Date: Mon, 22 Jun 2026 22:35:47 +0800 Message-ID: <20260622143557.22955-2-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" There are many adjacent blank lines in the verifier that have accumulated over time. Drop them for cleanup. No functional changes intended. Signed-off-by: Leon Hwang --- kernel/bpf/verifier.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 2abc79dbf281..721f883bf640 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -652,7 +652,6 @@ static void __mark_dynptr_reg(struct bpf_reg_state *reg, enum bpf_dynptr_type type, bool first_slot, int id, int parent_id); =20 - static void mark_dynptr_stack_regs(struct bpf_verifier_env *env, struct bpf_reg_state *sreg1, struct bpf_reg_state *sreg2, @@ -1689,7 +1688,6 @@ static bool same_callsites(struct bpf_verifier_state = *a, struct bpf_verifier_sta return true; } =20 - void bpf_free_backedges(struct bpf_scc_visit *visit) { struct bpf_scc_backedge *backedge, *next; @@ -2309,7 +2307,6 @@ static struct bpf_verifier_state *push_async_cb(struc= t bpf_verifier_env *env, return &elem->st; } =20 - static int cmp_subprogs(const void *a, const void *b) { return ((struct bpf_subprog_info *)a)->start - @@ -3331,7 +3328,6 @@ static bool is_spillable_regtype(enum bpf_reg_type ty= pe) } } =20 - /* check if register is a constant scalar value */ static bool is_reg_const(struct bpf_reg_state *reg, bool subreg32) { @@ -3993,7 +3989,6 @@ static int check_stack_read(struct bpf_verifier_env *= env, return err; } =20 - /* check_stack_write dispatches to check_stack_write_fixed_off or * check_stack_write_var_off. * @@ -4788,7 +4783,6 @@ static int check_sock_access(struct bpf_verifier_env = *env, int insn_idx, valid =3D false; } =20 - if (valid) { env->insn_aux_data[insn_idx].ctx_field_size =3D info.ctx_field_size; @@ -6608,7 +6602,6 @@ static int check_stack_range_initialized( if (err) return err; =20 - if (tnum_is_const(reg->var_off)) { min_off =3D max_off =3D reg->var_off.value + off; } else { @@ -7322,7 +7315,6 @@ static bool is_iter_new_kfunc(struct bpf_kfunc_call_a= rg_meta *meta) return meta->kfunc_flags & KF_ITER_NEW; } =20 - static bool is_iter_destroy_kfunc(struct bpf_kfunc_call_arg_meta *meta) { return meta->kfunc_flags & KF_ITER_DESTROY; @@ -11465,7 +11457,6 @@ static int process_irq_flag(struct bpf_verifier_env= *env, struct bpf_reg_state * return 0; } =20 - static int ref_set_non_owning(struct bpf_verifier_env *env, struct bpf_reg= _state *reg) { struct btf_record *rec =3D reg_btf_record(reg); @@ -16357,7 +16348,6 @@ static int check_ld_abs(struct bpf_verifier_env *en= v, struct bpf_insn *insn) return 0; } =20 - static bool return_retval_range(struct bpf_verifier_env *env, struct bpf_r= etval_range *range) { enum bpf_prog_type prog_type =3D resolve_prog_type(env->prog); @@ -18251,8 +18241,6 @@ static void release_insn_arrays(struct bpf_verifier= _env *env) bpf_insn_array_release(env->insn_array_maps[i]); } =20 - - /* The verifier does more data flow analysis than llvm and will not * explore branches that are dead at run time. Malicious programs can * have dead code too. Therefore replace all dead at-run-time code @@ -18280,8 +18268,6 @@ static void sanitize_dead_code(struct bpf_verifier_= env *env) } } =20 - - static void free_states(struct bpf_verifier_env *env) { struct bpf_verifier_state_list *sl; @@ -18563,7 +18549,6 @@ static int do_check_main(struct bpf_verifier_env *e= nv) return ret; } =20 - static void print_verification_stats(struct bpf_verifier_env *env) { /* Skip over hidden subprogs which are not verified. */ --=20 2.54.0 From nobody Sat Jun 27 16:57:08 2026 Received: from out-189.mta0.migadu.com (out-189.mta0.migadu.com [91.218.175.189]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 22A3C3BB131 for ; Mon, 22 Jun 2026 14:37:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.189 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139027; cv=none; b=V1Ts55qq5yl0WDmivzgRrWOh+6zEY4jMNy1H2s1+ZWJgL18amNSC+Lb5Q/9SXt9EDzg2D+A2id5c6nDOipQv+i/1ExnEdt4Z07NUZaNgY91CjpjCC4YHtzmQYqvpBtBNBjWct281m1aEDbHwBAeMSrVSv7r9OiD+ZA1HrvfUjrM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139027; c=relaxed/simple; bh=Fq3WYTnSqZS5zJK7JL8kP38nBrMaU9mMaFvCQOx9saI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JSyOMYX+be6O3etRD3e6jpVSzhLLzYQ89h5h3oI1cGsEhwk9nMmz1bcx6YUOovKKB5AFTx9dI32Qkm0UR3wJDuLkhpSdlTDe5ZrX90b0rjWSZcRihq0cQ1w5IW2U+AGQ7WKbUf302hYox+eqCUUMcFEbM74ExZutVyDxfqjQjTk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=ID4pRR07; arc=none smtp.client-ip=91.218.175.189 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="ID4pRR07" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139022; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=yCMiiSAWxWBXgCBfZXqftEZxdWrpCAJoKV6Pf7Wc5UA=; b=ID4pRR07awIdlZljgbBCNhQC8LQXSLSRcfBttXFVF8QUp13Y3VlDUd4WC39YU+Ls+I6eQs V+iqNG5LK+P+QrjS38B/DnkGcYFx/NJzmJ+YpQkw9VCTZmhNdnT6DCiLJoiFVz2I6ZSPdT bHSIlsDBgX8zjSk0OGx0iL41efOZPqA= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 02/11] bpf: Disallow interpreter fallback for user BPF_ADDR_SPACE_CAST insn Date: Mon, 22 Jun 2026 22:35:48 +0800 Message-ID: <20260622143557.22955-3-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Since interpreter is unable to handle the 'insn_is_cast_user()' insn, require JIT in __bpf_prog_select_runtime() when the prog has the insn. Fixes: 142fd4d2dcf5 ("bpf: Add x86-64 JIT support for bpf_addr_space_cast i= nstruction.") Signed-off-by: Leon Hwang --- include/linux/bpf.h | 1 + kernel/bpf/core.c | 1 + kernel/bpf/fixups.c | 2 ++ 3 files changed, 4 insertions(+) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 7719f6528445..5e1843d2859e 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1781,6 +1781,7 @@ struct bpf_prog_aux { bool changes_pkt_data; bool might_sleep; bool kprobe_write_ctx; + bool has_addr_space_cast_insn; struct { s32 keyring_serial; u8 keyring_type; diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 649cce41e13f..49398b5bd172 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -2620,6 +2620,7 @@ struct bpf_prog *__bpf_prog_select_runtime(struct bpf= _verifier_env *env, struct goto finalize; =20 if (IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON) || + fp->aux->has_addr_space_cast_insn || bpf_prog_has_kfunc_call(fp)) jit_needed =3D true; =20 diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c index 3cf2cc6e3ab6..2d5958774b61 100644 --- a/kernel/bpf/fixups.c +++ b/kernel/bpf/fixups.c @@ -1523,6 +1523,8 @@ int bpf_do_misc_fixups(struct bpf_verifier_env *env) insn->off =3D 0; insn->imm =3D 0; } /* cast from as(0) to as(1) should be handled by JIT */ + if (insn_is_cast_user(insn)) + prog->aux->has_addr_space_cast_insn =3D true; goto next_insn; } =20 --=20 2.54.0 From nobody Sat Jun 27 16:57:08 2026 Received: from out-185.mta0.migadu.com (out-185.mta0.migadu.com [91.218.175.185]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61DF03BB122 for ; Mon, 22 Jun 2026 14:37:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.185 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139034; cv=none; b=hwyI4i9uKSPQ96rQkbqw5X73wU6mLMSDMVEKete11KKSGepMbPehlKot6gJJmmlIsp3Ro3NglKDS/vngEXA/xWSPMNLAIOjXQ8Nx+Bfy8nMDgUWwwFtXIPZGdxUF5k4cXfYcUAeesFU50bW9DMEEojnIDajDgyTzBe5rZRXnxqk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139034; c=relaxed/simple; bh=XRdaxU9N7j1KAXQfNqe1kJXr5PDGUqIVm+gHVv7994k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s/DGvnJ02F4We53ol340hRGIdsDUQKFldQKv/q4g/BqRwVb5L8ulDHTA/NUNVjjZ/cx7ni3KtW6zXkeYijJdj7SmUbMq5C0w+C/6vggWVmz210Drqd3WWxE2VR/sXmb9qH0dOcB7jB7vObYxHSctnna5DEs3Cz+qwC1aN3piiB8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=MohMmFeF; arc=none smtp.client-ip=91.218.175.185 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="MohMmFeF" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139029; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2xKLc/VpD5w8rcK4oOI5MMeOf2bCaOl8dM0h4XZdcLc=; b=MohMmFeFFLZo2g0INVPqHNPOj6Y64mEhVY6skwfYLnFAFehmme1SlZvktnLQ0RZJRrjNnc qrK5K8DSdtPLRCUHFDFJ29AWbCgc8j/VQa4PtfbRoBm1Fjg8laiG2AF1KJVLGQAyE0O8h4 kgN7NrAKnJY92DUPxbdDvacJYX4Winw= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 03/11] bpf: Disallow interpreter fallback for BPF_ADDR_PERCPU insn Date: Mon, 22 Jun 2026 22:35:49 +0800 Message-ID: <20260622143557.22955-4-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Since interpreter is unable to handle the 'insn_is_mov_percpu_addr()' insn, require JIT in __bpf_prog_select_runtime() when the prog has the insn. BTW, rename the helper bpf_map_supports_cpu_flags() to bpf_map_is_percpu_map(). Fixes: 7bdbf7446305 ("bpf: add special internal-only MOV instruction to res= olve per-CPU addrs") Signed-off-by: Leon Hwang --- include/linux/bpf.h | 5 +++-- kernel/bpf/core.c | 1 + kernel/bpf/fixups.c | 5 +++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 5e1843d2859e..87b8d1928a06 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1782,6 +1782,7 @@ struct bpf_prog_aux { bool might_sleep; bool kprobe_write_ctx; bool has_addr_space_cast_insn; + bool has_addr_percpu_insn; struct { s32 keyring_serial; u8 keyring_type; @@ -4170,7 +4171,7 @@ bpf_prog_update_insn_ptrs(struct bpf_prog *prog, u32 = *offsets, void *image) } #endif =20 -static inline bool bpf_map_supports_cpu_flags(enum bpf_map_type map_type) +static inline bool bpf_map_is_percpu_map(enum bpf_map_type map_type) { switch (map_type) { case BPF_MAP_TYPE_PERCPU_ARRAY: @@ -4197,7 +4198,7 @@ static inline int bpf_map_check_op_flags(struct bpf_m= ap *map, u64 flags, u64 all return -EINVAL; =20 if (flags & (BPF_F_CPU | BPF_F_ALL_CPUS)) { - if (!bpf_map_supports_cpu_flags(map->map_type)) + if (!bpf_map_is_percpu_map(map->map_type)) return -EINVAL; if ((flags & BPF_F_CPU) && (flags & BPF_F_ALL_CPUS)) return -EINVAL; diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 49398b5bd172..69203d58e0ad 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -2621,6 +2621,7 @@ struct bpf_prog *__bpf_prog_select_runtime(struct bpf= _verifier_env *env, struct =20 if (IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON) || fp->aux->has_addr_space_cast_insn || + fp->aux->has_addr_percpu_insn || bpf_prog_has_kfunc_call(fp)) jit_needed =3D true; =20 diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c index 2d5958774b61..9552ddcf6936 100644 --- a/kernel/bpf/fixups.c +++ b/kernel/bpf/fixups.c @@ -2009,6 +2009,9 @@ int bpf_do_misc_fixups(struct bpf_verifier_env *env) return -EFAULT; } =20 + if (bpf_map_is_percpu_map(map_ptr->map_type)) + prog->aux->has_addr_percpu_insn =3D true; + new_prog =3D bpf_patch_insn_data(env, i + delta, insn_buf, cnt); if (!new_prog) @@ -2113,6 +2116,7 @@ int bpf_do_misc_fixups(struct bpf_verifier_env *env) * way, it's fine to back out this inlining logic */ #ifdef CONFIG_SMP + prog->aux->has_addr_percpu_insn =3D true; insn_buf[0] =3D BPF_MOV64_IMM(BPF_REG_0, (u32)(unsigned long)&cpu_numbe= r); insn_buf[1] =3D BPF_MOV64_PERCPU_REG(BPF_REG_0, BPF_REG_0); insn_buf[2] =3D BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, 0); @@ -2134,6 +2138,7 @@ int bpf_do_misc_fixups(struct bpf_verifier_env *env) /* Implement bpf_get_current_task() and bpf_get_current_task_btf() inlin= e. */ if ((insn->imm =3D=3D BPF_FUNC_get_current_task || insn->imm =3D=3D BPF_= FUNC_get_current_task_btf) && bpf_verifier_inlines_helper_call(env, insn->imm)) { + prog->aux->has_addr_percpu_insn =3D true; insn_buf[0] =3D BPF_MOV64_IMM(BPF_REG_0, (u32)(unsigned long)¤t_t= ask); insn_buf[1] =3D BPF_MOV64_PERCPU_REG(BPF_REG_0, BPF_REG_0); insn_buf[2] =3D BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0); --=20 2.54.0 From nobody Sat Jun 27 16:57:08 2026 Received: from out-179.mta0.migadu.com (out-179.mta0.migadu.com [91.218.175.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2675A399352 for ; Mon, 22 Jun 2026 14:37:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139040; cv=none; b=H+fn+7bJz1I3aDBiHj5dZdyOrxf5byXrOPXDDddU8ft5pdDKrOPNU9q8U0kjYZBNY4zg4af6J4jC73SOtbvzYNtYkNCxTQw+1n+eLvtv1iDity5gmnG6qwDMrfCENZpgFDNuC935pU0TRRmkaZvh18RHBluZhdLC7zZxYojOIi8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139040; c=relaxed/simple; bh=lHTJqBzevZ6TUqAbpgpMhSICAQFOtocMu+9NWU1ocVI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=h6UNcFzaiGIDTWTFqqICTnHFHv1iFBKeu8S/mrsRCqatepH35l9oX9hNffiFJPnelgvjLDgZ2VDLiTdSnVV63vzFZrYXwPTaMMbJaGbNJ7iZlUKq20Kr6VmJwQARz4mYFYc40OI6KbZZW/foXu0/6dA80FhWpnlJo4rFfX/KGqE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=UPIu44rG; arc=none smtp.client-ip=91.218.175.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="UPIu44rG" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139035; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=a88s3b0CEYLHjFN3iV3D0kERQEQN+cq3GzgSBuvSDZk=; b=UPIu44rGS5iAjpU0d9VBu1p+SzC5IIvXQBXdnom5FFKEIt6sSijwcrgovqysJURunt09nU my/xs3T5d5TY7IMX/a7xwXzZ1MB2twOZP+UlC8LwN0nDBxisRZspo6HW7o/NT8IK/ZKKwl aR4Tln+rW8NmHZpTQuKzbfnerKiWFMk= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 04/11] bpf: Introduce global percpu data Date: Mon, 22 Jun 2026 22:35:50 +0800 Message-ID: <20260622143557.22955-5-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Introduce global percpu data, inspired by the commit 6316f78306c1 ("Merge branch 'support-global-data'"). It enables the definition of global percpu variables in BPF, similar to the include/linux/percpu-defs.h::DEFINE_PER_CPU() macro. For example, in BPF, it is able to define a global percpu variable like: int data SEC(".percpu"); With this patch, tools like retsnoop [1] and bpfsnoop [2] can simplify their BPF code for handling LBRs. The code can be updated from static struct perf_branch_entry lbrs[1][MAX_LBR_ENTRIES] SEC(".data.lbrs"); to static struct perf_branch_entry lbrs[MAX_LBR_ENTRIES] SEC(".percpu.lbrs"); This eliminates the need to retrieve the CPU ID using the bpf_get_smp_processor_id() helper. Additionally, by reusing global percpu data map, sharing information between tail callers and callees or freplace callers and callees becomes simpler compared to reusing percpu_array maps. Links: [1] https://github.com/anakryiko/retsnoop [2] https://github.com/bpfsnoop/bpfsnoop Signed-off-by: Leon Hwang --- kernel/bpf/arraymap.c | 39 +++++++++++++++++++++++++++++++++++++-- kernel/bpf/const_fold.c | 1 - kernel/bpf/fixups.c | 34 ++++++++++++++++++++++++++++++++++ kernel/bpf/verifier.c | 15 +++++++++++++++ 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c index 248b4818178c..876aa2604f41 100644 --- a/kernel/bpf/arraymap.c +++ b/kernel/bpf/arraymap.c @@ -259,6 +259,38 @@ static void *percpu_array_map_lookup_elem(struct bpf_m= ap *map, void *key) return this_cpu_ptr(array->pptrs[index & array->index_mask]); } =20 +static int percpu_array_map_direct_value_addr(const struct bpf_map *map, u= 64 *imm, u32 off) +{ + struct bpf_array *array =3D container_of(map, struct bpf_array, map); + + if (map->max_entries !=3D 1) + return -EOPNOTSUPP; + if (off >=3D map->value_size) + return -EINVAL; + if (!bpf_jit_supports_percpu_insn()) + return -EOPNOTSUPP; + + *imm =3D (u64)(__force unsigned long) array->pptrs[0]; + return 0; +} + +static int percpu_array_map_direct_value_meta(const struct bpf_map *map, u= 64 imm, u32 *off) +{ + struct bpf_array *array =3D container_of(map, struct bpf_array, map); + u64 base =3D (u64)(__force unsigned long) array->pptrs[0]; + u64 range =3D array->elem_size; + + if (map->max_entries !=3D 1) + return -EOPNOTSUPP; + if (imm < base || imm >=3D base + range) + return -ENOENT; + if (!bpf_jit_supports_percpu_insn()) + return -EOPNOTSUPP; + + *off =3D imm - base; + return 0; +} + /* emit BPF instructions equivalent to C code of percpu_array_map_lookup_e= lem() */ static int percpu_array_map_gen_lookup(struct bpf_map *map, struct bpf_ins= n *insn_buf) { @@ -551,9 +583,10 @@ static int array_map_check_btf(struct bpf_map *map, const struct btf_type *key_type, const struct btf_type *value_type) { - /* One exception for keyless BTF: .bss/.data/.rodata map */ + /* One exception for keyless BTF: .bss/.data/.rodata/.percpu map */ if (btf_type_is_void(key_type)) { - if (map->map_type !=3D BPF_MAP_TYPE_ARRAY || + if ((map->map_type !=3D BPF_MAP_TYPE_ARRAY && + map->map_type !=3D BPF_MAP_TYPE_PERCPU_ARRAY) || map->max_entries !=3D 1) return -EINVAL; =20 @@ -832,6 +865,8 @@ const struct bpf_map_ops percpu_array_map_ops =3D { .map_get_next_key =3D bpf_array_get_next_key, .map_lookup_elem =3D percpu_array_map_lookup_elem, .map_gen_lookup =3D percpu_array_map_gen_lookup, + .map_direct_value_addr =3D percpu_array_map_direct_value_addr, + .map_direct_value_meta =3D percpu_array_map_direct_value_meta, .map_update_elem =3D array_map_update_elem, .map_delete_elem =3D array_map_delete_elem, .map_lookup_percpu_elem =3D percpu_array_map_lookup_percpu_elem, diff --git a/kernel/bpf/const_fold.c b/kernel/bpf/const_fold.c index b2a19acadb91..5787246bef30 100644 --- a/kernel/bpf/const_fold.c +++ b/kernel/bpf/const_fold.c @@ -182,7 +182,6 @@ static void const_reg_xfer(struct bpf_verifier_env *env= , struct const_arg_info * u64 val =3D 0; =20 if (!bpf_map_is_rdonly(map) || !map->ops->map_direct_value_addr || - map->map_type =3D=3D BPF_MAP_TYPE_INSN_ARRAY || off < 0 || off + size > map->value_size || bpf_map_direct_read(map, off, size, &val, is_ldsx)) { *dst =3D unknown; diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c index 9552ddcf6936..802d49e4a643 100644 --- a/kernel/bpf/fixups.c +++ b/kernel/bpf/fixups.c @@ -1821,6 +1821,40 @@ int bpf_do_misc_fixups(struct bpf_verifier_env *env) goto next_insn; } =20 + if (env->prog->jit_requested && + bpf_jit_supports_percpu_insn() && + insn->code =3D=3D (BPF_LD | BPF_IMM | BPF_DW) && + (insn->src_reg =3D=3D BPF_PSEUDO_MAP_VALUE || + insn->src_reg =3D=3D BPF_PSEUDO_MAP_IDX_VALUE)) { + struct bpf_map *map; + + aux =3D &env->insn_aux_data[i + delta]; + map =3D env->used_maps[aux->map_index]; + if (map->map_type !=3D BPF_MAP_TYPE_PERCPU_ARRAY) + goto next_insn; + + prog->aux->has_addr_percpu_insn =3D true; + + /* + * Reuse the original ld_imm64 insn, and add one + * mov64_percpu_reg insn. + */ + + insn_buf[0] =3D insn[1]; + insn_buf[1] =3D BPF_MOV64_PERCPU_REG(insn->dst_reg, insn->dst_reg); + cnt =3D 2; + + i++; + new_prog =3D bpf_patch_insn_data(env, i + delta, insn_buf, cnt); + if (!new_prog) + return -ENOMEM; + + delta +=3D cnt - 1; + env->prog =3D prog =3D new_prog; + insn =3D new_prog->insnsi + i + delta; + goto next_insn; + } + if (insn->code !=3D (BPF_JMP | BPF_CALL)) goto next_insn; if (insn->src_reg =3D=3D BPF_PSEUDO_CALL) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 721f883bf640..9a2ae6a10e90 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5562,6 +5562,8 @@ int bpf_map_direct_read(struct bpf_map *map, int off,= int size, u64 *val, u64 addr; int err; =20 + if (map->map_type =3D=3D BPF_MAP_TYPE_INSN_ARRAY || map->map_type =3D=3D = BPF_MAP_TYPE_PERCPU_ARRAY) + return -EINVAL; err =3D map->ops->map_direct_value_addr(map, &addr, off); if (err) return err; @@ -6113,6 +6115,7 @@ static int check_mem_access(struct bpf_verifier_env *= env, int insn_idx, struct b if (tnum_is_const(reg->var_off) && bpf_map_is_rdonly(map) && map->ops->map_direct_value_addr && + map->map_type !=3D BPF_MAP_TYPE_PERCPU_ARRAY && map->map_type !=3D BPF_MAP_TYPE_INSN_ARRAY) { int map_off =3D off + reg->var_off.value; u64 val =3D 0; @@ -8080,6 +8083,12 @@ static int check_arg_const_str(struct bpf_verifier_e= nv *env, return -EACCES; } =20 + if (map->map_type =3D=3D BPF_MAP_TYPE_PERCPU_ARRAY) { + verbose(env, "%s points to percpu_array map which cannot be used as cons= t string\n", + reg_arg_name(env, argno)); + return -EACCES; + } + if (!bpf_map_is_rdonly(map)) { verbose(env, "%s does not point to a readonly map'\n", reg_arg_name(env,= argno)); return -EACCES; @@ -18166,6 +18175,12 @@ static int check_and_resolve_insns(struct bpf_veri= fier_env *env) return -EINVAL; } =20 + if (map->map_type =3D=3D BPF_MAP_TYPE_PERCPU_ARRAY && + !env->prog->jit_requested) { + verbose(env, "JIT is required to use global percpu data\n"); + return -EOPNOTSUPP; + } + err =3D map->ops->map_direct_value_addr(map, &addr, off); if (err) { verbose(env, "invalid access to map value pointer, value_size=3D%u of= f=3D%u\n", --=20 2.54.0 From nobody Sat Jun 27 16:57:08 2026 Received: from out-171.mta0.migadu.com (out-171.mta0.migadu.com [91.218.175.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8663B3BB109 for ; Mon, 22 Jun 2026 14:37:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139060; cv=none; b=TV4Vqv5kpBJxeUUW4kO+vU1sDWA1g0NmXxUtjFPf9bL37MTlE/DkYnD472AHTuJAGPaxGNFZ8q+lcKwpGDmvJ6aanHBX9Naq/4RTg7U3M7YLWw2bJjb2IpoG7S0/EuiE0eVc7ZXzvYFGU7iSj8fxT65HpwCIadtiqKjpb+fWBvs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139060; c=relaxed/simple; bh=7aWGOqFvUnRxxrWYZPjboUZxRj4atw89cz1TG+Q+fX8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Mbls9wz3St8gIeU8E3/dvn1TPJEyEYIhkXsfc5NLMBYXEOQayMyCyuKYrMvg8UDHi0i/uPrGXUbqq2ezEfUmYWpD15GFs7lVwYZTkcTum7lavkTsj/4lNgZDz352SYLLk3RT0daWK4RiqzI4a3h8XITK5qgNtiyoc0HEgQbeev4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=fiFaxj5T; arc=none smtp.client-ip=91.218.175.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="fiFaxj5T" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139055; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=23qEzaaxzUNRoSfo0B6KLO62rkW4jKGMY8uCiIhS1BQ=; b=fiFaxj5T2vEt10ujHW2d8ObXgDtmhbA1BvEpr92qtBJhvyAUawAkwDiA1wk7MRTN4rFwjV rxwb7RtES8s6pVbpZ3HhALI2R31pV9bQJCFYjAa1mbPlkG6f8I8nYJpc30BM866lXEJtML UGgwzl1Npc7TZVjQXkxWjR8Xtty7PHc= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 05/11] libbpf: Probe percpu data feature Date: Mon, 22 Jun 2026 22:35:51 +0800 Message-ID: <20260622143557.22955-6-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" libbpf needs a reliable way to distinguish kernels that can support global percpu data from those that cannot. Add a dedicated feature probe, so libbpf can make capability decisions early and fail predictably when global percpu data is unavailable. Signed-off-by: Leon Hwang Acked-by: Andrii Nakryiko --- tools/lib/bpf/features.c | 35 +++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf_internal.h | 2 ++ 2 files changed, 37 insertions(+) diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c index b7e388f99d0b..ef9581c11303 100644 --- a/tools/lib/bpf/features.c +++ b/tools/lib/bpf/features.c @@ -620,6 +620,38 @@ static int probe_bpf_syscall_common_attrs(int token_fd) return probe_sys_bpf_ext(); } =20 +static int probe_kern_percpu_data(int token_fd) +{ + struct bpf_insn insns[] =3D { + BPF_LD_MAP_VALUE(BPF_REG_1, 0, 0), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, 0), + BPF_EXIT_INSN(), + }; + LIBBPF_OPTS(bpf_map_create_opts, map_opts, + .token_fd =3D token_fd, + .map_flags =3D token_fd ? BPF_F_TOKEN_FD : 0, + ); + LIBBPF_OPTS(bpf_prog_load_opts, prog_opts, + .token_fd =3D token_fd, + .prog_flags =3D token_fd ? BPF_F_TOKEN_FD : 0, + ); + int ret, map, insn_cnt =3D ARRAY_SIZE(insns); + + map =3D bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, "libbpf_percpu", sizeof= (int), 8, 1, + &map_opts); + if (map < 0) { + pr_warn("Error in %s(): %s. Couldn't create simple percpu_array map.\n", + __func__, errstr(map)); + return map; + } + + insns[0].imm =3D map; + + ret =3D bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, in= sn_cnt, &prog_opts); + close(map); + return probe_fd(ret); +} + typedef int (*feature_probe_fn)(int /* token_fd */); =20 static struct kern_feature_cache feature_cache; @@ -707,6 +739,9 @@ static struct kern_feature_desc { [FEAT_BPF_SYSCALL_COMMON_ATTRS] =3D { "BPF syscall common attributes support", probe_bpf_syscall_common_attrs, }, + [FEAT_PERCPU_DATA] =3D { + "kernel supports percpu data", probe_kern_percpu_data, + }, }; =20 bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id= feat_id) diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_interna= l.h index 04cd303fb5a8..47ae39125f68 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -401,6 +401,8 @@ enum kern_feature_id { FEAT_BTF_LAYOUT, /* Kernel supports BPF syscall common attributes */ FEAT_BPF_SYSCALL_COMMON_ATTRS, + /* Kernel supports percpu data */ + FEAT_PERCPU_DATA, __FEAT_CNT, }; =20 --=20 2.54.0 From nobody Sat Jun 27 16:57:08 2026 Received: from out-188.mta0.migadu.com (out-188.mta0.migadu.com [91.218.175.188]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9C9FA3AFD16 for ; Mon, 22 Jun 2026 14:37:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.188 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139068; cv=none; b=ogwGKDYWkH4iJC4Mfl5J+vnMKmSMsQff9JA7vRyn62qyuxKRUCW+nZ7mTEPWrSdPCUWUi5BXigIeK9g/OtVOwYgw/BkFkVTDZ2e2pZOw/vntHn/3fqKt8EjwSpr/qJnA3j7l3fkFSpOibLBy0RqHlfohA1qK2h3nmx9Zb/+kQC4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139068; c=relaxed/simple; bh=AwM+7eZfze8RdJZoWS7iZkxFUNLdIeSDOmcx6TcopTM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rGppbU1upi/mAkkP1Wd2W4jWpjMMMvcB0128BHB4SD1I66+NpEDYLBFJGsPEtr4IHqWw5YuWZw2GMIE8L0I8wHYuvBIOxajZXSc28rq68u01d/x+b6tktLv3ZhhwLg9JVLuWl7paAKtDsBy5YQ8srRf6SM5sGQ6L0/i9JmcY+P0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=SByJLg1i; arc=none smtp.client-ip=91.218.175.188 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="SByJLg1i" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139062; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RXsK6zbjlxu38B+2bCWwOlNkgS1G64IMR919Qym6HbE=; b=SByJLg1is5EzVhI3ChlU/Qb2HFahW1u2l/WoZqWl54pg5lQibJnno6TBGAPBOhVxKm02UQ IDR4lrSqH8xzGr4tJIjn/AGD3dDVBJfy6lFcssWVA6bjaKaFUNeny0AibtNgKTUl89x8Zs 4twcQ1TmB0S3zYvc0rJK/uzDX7posBw= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 06/11] libbpf: Add support for global percpu data Date: Mon, 22 Jun 2026 22:35:52 +0800 Message-ID: <20260622143557.22955-7-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Add support for global percpu data in libbpf by adding a new ".percpu" section, similar to ".data". It enables efficient handling of percpu global variables in bpf programs. When generating loader for lightweight skeleton, update the percpu_array map used for global percpu data using BPF_F_ALL_CPUS, in order to update values across all CPUs using one value slot. Unlike global data, the mmaped data for global percpu data will be marked as read-only after populating the percpu_array map. Thereafter, users can read those initialized percpu data after loading prog. If they want to update the percpu data after loading prog, they have to update the percpu_array map using key=3D0 instead. Signed-off-by: Leon Hwang --- tools/lib/bpf/bpf_gen_internal.h | 3 +- tools/lib/bpf/gen_loader.c | 3 +- tools/lib/bpf/libbpf.c | 68 ++++++++++++++++++++++++++------ 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/tools/lib/bpf/bpf_gen_internal.h b/tools/lib/bpf/bpf_gen_inter= nal.h index 49af4260b8e6..5ea8383805d3 100644 --- a/tools/lib/bpf/bpf_gen_internal.h +++ b/tools/lib/bpf/bpf_gen_internal.h @@ -66,7 +66,8 @@ void bpf_gen__prog_load(struct bpf_gen *gen, enum bpf_prog_type prog_type, const char *prog_name, const char *license, struct bpf_insn *insns, size_t insn_cnt, struct bpf_prog_load_opts *load_attr, int prog_idx); -void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *valu= e, __u32 value_size); +void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *valu= e, __u32 value_size, + __u64 flags); void bpf_gen__map_freeze(struct bpf_gen *gen, int map_idx); void bpf_gen__record_attach_target(struct bpf_gen *gen, const char *name, = enum bpf_attach_type type); void bpf_gen__record_extern(struct bpf_gen *gen, const char *name, bool is= _weak, diff --git a/tools/lib/bpf/gen_loader.c b/tools/lib/bpf/gen_loader.c index d79695f01c87..efc480af70c3 100644 --- a/tools/lib/bpf/gen_loader.c +++ b/tools/lib/bpf/gen_loader.c @@ -1190,7 +1190,7 @@ void bpf_gen__prog_load(struct bpf_gen *gen, } =20 void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *pval= ue, - __u32 value_size) + __u32 value_size, __u64 flags) { int attr_size =3D offsetofend(union bpf_attr, flags); int map_update_attr, value, key; @@ -1198,6 +1198,7 @@ void bpf_gen__map_update_elem(struct bpf_gen *gen, in= t map_idx, void *pvalue, int zero =3D 0; =20 memset(&attr, 0, attr_size); + attr.flags =3D tgt_endian(flags); =20 value =3D add_data(gen, pvalue, value_size); key =3D add_data(gen, &zero, sizeof(zero)); diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 1368752aa13c..199d08d3cdcd 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -541,6 +541,7 @@ struct bpf_struct_ops { }; =20 #define DATA_SEC ".data" +#define PERCPU_SEC ".percpu" #define BSS_SEC ".bss" #define RODATA_SEC ".rodata" #define KCONFIG_SEC ".kconfig" @@ -555,6 +556,7 @@ enum libbpf_map_type { LIBBPF_MAP_BSS, LIBBPF_MAP_RODATA, LIBBPF_MAP_KCONFIG, + LIBBPF_MAP_PERCPU, }; =20 struct bpf_map_def { @@ -666,6 +668,7 @@ enum sec_type { SEC_DATA, SEC_RODATA, SEC_ST_OPS, + SEC_PERCPU, }; =20 struct elf_sec_desc { @@ -1839,6 +1842,8 @@ static size_t bpf_map_mmap_sz(const struct bpf_map *m= ap) switch (map->def.type) { case BPF_MAP_TYPE_ARRAY: return array_map_mmap_sz(map->def.value_size, map->def.max_entries); + case BPF_MAP_TYPE_PERCPU_ARRAY: + return map->def.value_size; case BPF_MAP_TYPE_ARENA: return page_sz * map->def.max_entries; default: @@ -1938,7 +1943,7 @@ static bool map_is_mmapable(struct bpf_object *obj, s= truct bpf_map *map) struct btf_var_secinfo *vsi; int i, n; =20 - if (!map->btf_value_type_id) + if (!map->btf_value_type_id || map->libbpf_type =3D=3D LIBBPF_MAP_PERCPU) return false; =20 t =3D btf__type_by_id(obj->btf, map->btf_value_type_id); @@ -1962,6 +1967,7 @@ static int bpf_object__init_internal_map(struct bpf_object *obj, enum libbpf_map_type= type, const char *real_name, int sec_idx, void *data, size_t data_sz) { + bool is_percpu =3D type =3D=3D LIBBPF_MAP_PERCPU; struct bpf_map_def *def; struct bpf_map *map; size_t mmap_sz; @@ -1983,7 +1989,7 @@ bpf_object__init_internal_map(struct bpf_object *obj,= enum libbpf_map_type type, } =20 def =3D &map->def; - def->type =3D BPF_MAP_TYPE_ARRAY; + def->type =3D is_percpu ? BPF_MAP_TYPE_PERCPU_ARRAY : BPF_MAP_TYPE_ARRAY; def->key_size =3D sizeof(int); def->value_size =3D data_sz; def->max_entries =3D 1; @@ -1996,8 +2002,9 @@ bpf_object__init_internal_map(struct bpf_object *obj,= enum libbpf_map_type type, if (map_is_mmapable(obj, map)) def->map_flags |=3D BPF_F_MMAPABLE; =20 - pr_debug("map '%s' (global data): at sec_idx %d, offset %zu, flags %x.\n", - map->name, map->sec_idx, map->sec_offset, def->map_flags); + pr_debug("map '%s' (global %sdata): at sec_idx %d, offset %zu, flags %x.\= n", + map->name, is_percpu ? "percpu " : "", map->sec_idx, + map->sec_offset, def->map_flags); =20 mmap_sz =3D bpf_map_mmap_sz(map); map->mmaped =3D mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE, @@ -2057,6 +2064,13 @@ static int bpf_object__init_global_data_maps(struct = bpf_object *obj) NULL, sec_desc->data->d_size); break; + case SEC_PERCPU: + sec_name =3D elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx)); + err =3D bpf_object__init_internal_map(obj, LIBBPF_MAP_PERCPU, + sec_name, sec_idx, + sec_desc->data->d_buf, + sec_desc->data->d_size); + break; default: /* skip */ break; @@ -4016,6 +4030,11 @@ static int bpf_object__elf_collect(struct bpf_object= *obj) sec_desc->sec_type =3D SEC_RODATA; sec_desc->shdr =3D sh; sec_desc->data =3D data; + } else if (strcmp(name, PERCPU_SEC) =3D=3D 0 || + str_has_pfx(name, PERCPU_SEC ".")) { + sec_desc->sec_type =3D SEC_PERCPU; + sec_desc->shdr =3D sh; + sec_desc->data =3D data; } else if (strcmp(name, STRUCT_OPS_SEC) =3D=3D 0 || strcmp(name, STRUCT_OPS_LINK_SEC) =3D=3D 0 || strcmp(name, "?" STRUCT_OPS_SEC) =3D=3D 0 || @@ -4544,6 +4563,7 @@ static bool bpf_object__shndx_is_data(const struct bp= f_object *obj, case SEC_BSS: case SEC_DATA: case SEC_RODATA: + case SEC_PERCPU: return true; default: return false; @@ -4569,6 +4589,8 @@ bpf_object__section_to_libbpf_map_type(const struct b= pf_object *obj, int shndx) return LIBBPF_MAP_DATA; case SEC_RODATA: return LIBBPF_MAP_RODATA; + case SEC_PERCPU: + return LIBBPF_MAP_PERCPU; default: return LIBBPF_MAP_UNSPEC; } @@ -4944,7 +4966,7 @@ static int map_fill_btf_type_info(struct bpf_object *= obj, struct bpf_map *map) =20 /* * LLVM annotates global data differently in BTF, that is, - * only as '.data', '.bss' or '.rodata'. + * only as '.data', '.bss', '.percpu' or '.rodata'. */ if (!bpf_map__is_internal(map)) return -ENOENT; @@ -5297,18 +5319,30 @@ static int bpf_object__populate_internal_map(struct bpf_object *obj, struct bpf_map *= map) { enum libbpf_map_type map_type =3D map->libbpf_type; + bool is_percpu =3D map_type =3D=3D LIBBPF_MAP_PERCPU; + __u64 update_flags =3D 0; int err, zero =3D 0; size_t mmap_sz; =20 + if (is_percpu) { + if (!obj->gen_loader && !kernel_supports(obj, FEAT_PERCPU_DATA)) { + pr_warn("map '%s': kernel does not support percpu data.\n", + bpf_map__name(map)); + return -EOPNOTSUPP; + } + + update_flags =3D BPF_F_ALL_CPUS; + } + if (obj->gen_loader) { bpf_gen__map_update_elem(obj->gen_loader, map - obj->maps, - map->mmaped, map->def.value_size); + map->mmaped, map->def.value_size, update_flags); if (map_type =3D=3D LIBBPF_MAP_RODATA || map_type =3D=3D LIBBPF_MAP_KCON= FIG) bpf_gen__map_freeze(obj->gen_loader, map - obj->maps); return 0; } =20 - err =3D bpf_map_update_elem(map->fd, &zero, map->mmaped, 0); + err =3D bpf_map_update_elem(map->fd, &zero, map->mmaped, update_flags); if (err) { err =3D -errno; pr_warn("map '%s': failed to set initial contents: %s\n", @@ -5353,6 +5387,13 @@ bpf_object__populate_internal_map(struct bpf_object = *obj, struct bpf_map *map) return err; } map->mmaped =3D mmaped; + } else if (is_percpu) { + if (mprotect(map->mmaped, mmap_sz, PROT_READ)) { + err =3D -errno; + pr_warn("map '%s': failed to mprotect() contents: %s\n", + bpf_map__name(map), errstr(err)); + return err; + } } else if (map->mmaped) { munmap(map->mmaped, mmap_sz); map->mmaped =3D NULL; @@ -10806,16 +10847,19 @@ int bpf_map__fd(const struct bpf_map *map) =20 static bool map_uses_real_name(const struct bpf_map *map) { - /* Since libbpf started to support custom .data.* and .rodata.* maps, - * their user-visible name differs from kernel-visible name. Users see - * such map's corresponding ELF section name as a map name. - * This check distinguishes .data/.rodata from .data.* and .rodata.* - * maps to know which name has to be returned to the user. + /* + * Since libbpf started to support custom .data.*, .rodata.* and + * .percpu.* maps, their user-visible name differs from + * kernel-visible name. Users see such map's corresponding ELF section + * name as a map name. This check distinguishes plain .data/.rodata/.perc= pu + * from .data.*, .rodata.* and .percpu.* to choose which name to return. */ if (map->libbpf_type =3D=3D LIBBPF_MAP_DATA && strcmp(map->real_name, DAT= A_SEC) !=3D 0) return true; if (map->libbpf_type =3D=3D LIBBPF_MAP_RODATA && strcmp(map->real_name, R= ODATA_SEC) !=3D 0) return true; + if (map->libbpf_type =3D=3D LIBBPF_MAP_PERCPU && strcmp(map->real_name, P= ERCPU_SEC) !=3D 0) + return true; return false; } =20 --=20 2.54.0 From nobody Sat Jun 27 16:57:08 2026 Received: from out-173.mta0.migadu.com (out-173.mta0.migadu.com [91.218.175.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A562C3BB109 for ; Mon, 22 Jun 2026 14:37:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139074; cv=none; b=L3/zzInFWMpoXYa34CbKIjGz+7qTHMMAtoqjnD+EFboT4JUtVt0TucDJoRw2pMRWvVw5IE8gW751FjMIknPoixKUbS4cB7xZgprUhUQDsqyFxc491gkJ8qiUqdak7ByxeRYnvWCXupKYOvrU3NP+JFXfU4VGy0rfLpNKM3bavkY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139074; c=relaxed/simple; bh=721RJucMZVja3f2/78SJ3YsiNxGl6KFT8QrGf/fap40=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ai4OF7tXlN4dImR/8o1mwEXiaykjQ42UqWGfJByG9YDBmSTQSSze5TQ6nsxJEXeNL20ukvz7Vyih07kZkb8TOQb+0YN3gJ56c5T+DVBOrXIjO+SoTLR7CZeHlFdNnXo3kcjGTnQQFvz3/jrRJ15LceXir9cZndQpWT5+75mEjPk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=qXc1CsDK; arc=none smtp.client-ip=91.218.175.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="qXc1CsDK" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139069; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=6QP46oDj+m3aNlLwfNzDDE050nCPuj8E/Khl3XbBbK0=; b=qXc1CsDKQfVa+665uiOLb+vys6qRZHGPxoCNgusQtgS6F3r53BpQMb1IMZbopPd/MnXBWB XLJhvCuUhqp/iEjfRpMFq3j0G5sXcgeiSv7EuRkuK2NRDTJVFFmPIwFRVIFqQLwzTpJ2vO QCh0xWSworUc/8yX8NRvPilQXVhbZlU= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 07/11] bpftool: Generate skeleton for global percpu data Date: Mon, 22 Jun 2026 22:35:53 +0800 Message-ID: <20260622143557.22955-8-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Enhance bpftool to generate skeletons that properly handle global percpu variables. The generated skeleton now includes a dedicated structure for percpu data, allowing users to initialize and access percpu variables more efficiently. For global percpu variables, the skeleton now includes a nested structure, e.g.: struct test_global_percpu_data { struct bpf_object_skeleton *skeleton; struct bpf_object *obj; struct { struct bpf_map *percpu; } maps; // ... struct test_global_percpu_data__percpu { int data; char run; struct { char set; int i; int nums[7]; } struct_data; int nums[7]; } *percpu; // ... }; * The "struct test_global_percpu_data__percpu *percpu" points to initialized data, which is actually "maps.percpu->mmaped". * Before loading the skeleton, updating the "struct test_global_percpu_data__percpu *percpu" modifies the initial value of the corresponding global percpu variables. * After loading the skeleton, "maps.percpu->mmaped" has been marked as read-only in libbpf. If users want to update the global percpu variables, they have to update the "maps.percpu" map instead. * For lightweight skeleton, "lskel->percpu" will be protected by "mprotect(p, sz, PROT_READ)". * For subskeleton, those variables of global percpu data will be skipped. Assisted-by: Codex:gpt-5.5-xhigh Signed-off-by: Leon Hwang --- tools/bpf/bpftool/gen.c | 43 +++++++++++++++++++++++++++-------- tools/lib/bpf/skel_internal.h | 24 +++++++++++++++++-- 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c index 6ae7262ebe0c..2200ab004d2b 100644 --- a/tools/bpf/bpftool/gen.c +++ b/tools/bpf/bpftool/gen.c @@ -92,7 +92,7 @@ static void get_header_guard(char *guard, const char *obj= _name, const char *suff =20 static bool get_map_ident(const struct bpf_map *map, char *buf, size_t buf= _sz) { - static const char *sfxs[] =3D { ".data", ".rodata", ".bss", ".kconfig" }; + static const char *sfxs[] =3D { ".data", ".rodata", ".bss", ".percpu", ".= kconfig" }; const char *name =3D bpf_map__name(map); int i, n; =20 @@ -117,7 +117,7 @@ static bool get_map_ident(const struct bpf_map *map, ch= ar *buf, size_t buf_sz) =20 static bool get_datasec_ident(const char *sec_name, char *buf, size_t buf_= sz) { - static const char *pfxs[] =3D { ".data", ".rodata", ".bss", ".kconfig" }; + static const char *pfxs[] =3D { ".data", ".rodata", ".bss", ".percpu", ".= kconfig" }; int i, n; =20 /* recognize hard coded LLVM section name */ @@ -254,6 +254,11 @@ static const struct btf_type *find_type_for_map(struct= btf *btf, const char *map return NULL; } =20 +static bool bpf_map_is_percpu_data(const struct bpf_map *map) +{ + return bpf_map__is_internal(map) && bpf_map__type(map) =3D=3D BPF_MAP_TYP= E_PERCPU_ARRAY; +} + static bool is_mmapable_map(const struct bpf_map *map, char *buf, size_t s= z) { size_t tmp_sz; @@ -263,13 +268,12 @@ static bool is_mmapable_map(const struct bpf_map *map= , char *buf, size_t sz) return true; } =20 - if (!bpf_map__is_internal(map) || !(bpf_map__map_flags(map) & BPF_F_MMAPA= BLE)) - return false; - - if (!get_map_ident(map, buf, sz)) - return false; + if (bpf_map__is_internal(map) && + ((bpf_map__map_flags(map) & BPF_F_MMAPABLE) || bpf_map_is_percpu_data= (map)) && + get_map_ident(map, buf, sz)) + return true; =20 - return true; + return false; } =20 static int codegen_datasecs(struct bpf_object *obj, const char *obj_name) @@ -343,6 +347,9 @@ static int codegen_subskel_datasecs(struct bpf_object *= obj, const char *obj_name if (!is_mmapable_map(map, map_ident, sizeof(map_ident))) continue; =20 + if (bpf_map_is_percpu_data(map)) + continue; + sec =3D find_type_for_map(btf, map_ident); if (!sec) continue; @@ -669,7 +676,7 @@ static void codegen_destroy(struct bpf_object *obj, con= st char *obj_name) if (!get_map_ident(map, ident, sizeof(ident))) continue; if (bpf_map__is_internal(map) && - (bpf_map__map_flags(map) & BPF_F_MMAPABLE)) + ((bpf_map__map_flags(map) & BPF_F_MMAPABLE) || bpf_map_is_percpu_dat= a(map))) printf("\tskel_free_map_data(skel->%1$s, skel->maps.%1$s.initial_value,= %2$zu);\n", ident, bpf_map_mmap_sz(map)); codegen("\ @@ -850,6 +857,20 @@ static int gen_trace(struct bpf_object *obj, const cha= r *obj_name, const char *h if (!is_mmapable_map(map, ident, sizeof(ident))) continue; =20 + if (bpf_map_is_percpu_data(map)) { + codegen("\ + \n\ + err =3D skel_protect_map_data(skel->%1$s, &skel->maps.%1$s.initial_valu= e, %2$zd);\n\ + if (err) \n\ + return err; \n\ + #ifdef __KERNEL__ \n\ + skel->%1$s =3D NULL; \n\ + #endif \n\ + ", + ident, bpf_map_mmap_sz(map)); + continue; + } + if (bpf_map__map_flags(map) & BPF_F_RDONLY_PROG) mmap_flags =3D "PROT_READ"; else @@ -1740,6 +1761,8 @@ static int do_subskeleton(int argc, char **argv) =20 if (!is_mmapable_map(map, ident, sizeof(ident))) continue; + if (bpf_map_is_percpu_data(map)) + continue; =20 map_type_id =3D bpf_map__btf_value_type_id(map); if (map_type_id <=3D 0) { @@ -1863,6 +1886,8 @@ static int do_subskeleton(int argc, char **argv) bpf_object__for_each_map(map, obj) { if (!is_mmapable_map(map, ident, sizeof(ident))) continue; + if (bpf_map_is_percpu_data(map)) + continue; =20 map_type_id =3D bpf_map__btf_value_type_id(map); if (map_type_id <=3D 0) diff --git a/tools/lib/bpf/skel_internal.h b/tools/lib/bpf/skel_internal.h index 74503d358bc8..485b0cd17017 100644 --- a/tools/lib/bpf/skel_internal.h +++ b/tools/lib/bpf/skel_internal.h @@ -135,8 +135,10 @@ static inline void skel_free_map_data(void *p, __u64 a= ddr, size_t sz) { if (addr !=3D ~0ULL) kvfree(p); - /* When addr =3D=3D ~0ULL the 'p' points to - * ((struct bpf_array *)map)->value. See skel_finalize_map_data. + /* + * When addr =3D=3D ~0ULL the init buffer has already been released. + * For skel_finalize_map_data(), 'p' points to + * ((struct bpf_array *)map)->value. */ } =20 @@ -174,6 +176,15 @@ static inline void *skel_finalize_map_data(__u64 *init= _val, size_t mmap_sz, int return addr; } =20 +static inline int skel_protect_map_data(void *p, __u64 *init_val, size_t s= z) +{ + (void)sz; + + kvfree(p); + *init_val =3D ~0ULL; + return 0; +} + #else =20 static inline void *skel_alloc(size_t size) @@ -212,6 +223,15 @@ static inline void *skel_finalize_map_data(__u64 *init= _val, size_t mmap_sz, int return NULL; return addr; } + +static inline int skel_protect_map_data(void *p, __u64 *init_val, size_t s= z) +{ + (void)init_val; + + if (mprotect(p, sz, PROT_READ)) + return -errno; + return 0; +} #endif =20 static inline int skel_closenz(int fd) --=20 2.54.0 From nobody Sat Jun 27 16:57:08 2026 Received: from out-178.mta0.migadu.com (out-178.mta0.migadu.com [91.218.175.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B55B73BB11C for ; Mon, 22 Jun 2026 14:37:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139080; cv=none; b=aeZVfH9IA20Bbl7J7A6Su9EmhEFIsmmyACeegkdJy3QFf1uz+YlHoG2lHxW3vsk7nXKnH7saVZxg6lywfNNK7QinxSebI9fB0WtH+EdIzSHQUYeGcIoAKPPqwqWoVje8E7gp+CO2wJxyBBDBd4FpcwWGkpbgXKbodhBjtNhtDks= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139080; c=relaxed/simple; bh=5HzHEar9SmF2RRrjnz2132bB01L+5FV4T5EKcdHKqOs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CX08VdYeCesEi48S01XXRktDXaiOG35EKe0Q8VTPbXKgzk96fhaHqJVuRtvcDmFr9uyW/rxTmEnJcNy+g6hUoGpoNzYcYJNCOsEdGU976yWrlsH0M393LgS5Ta3+QHQqMGMwz7sTpsiIv4e7KD08EexlxogD4mwNv3Hvw9HN4bY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=unBudzTB; arc=none smtp.client-ip=91.218.175.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="unBudzTB" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139076; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3DY9CrDkr+7m0SRCYEDRtRofB1sBYjpCEa/BedRHMrQ=; b=unBudzTBwK2DvDF0CQuFICt/v9kwbHzYGXIeRgiHIEMeM/T7AKZEvgpnTfJLfiFJjoHH+4 MdXbOB/NICOH0We5pPvqhX2F+w4KX4D+xbVo0ew80JKg0+7l1d3VYEtQFZdNKc1Mkr1215 jEVGrssBf3HNtjzQP1u5dqtN3V3iKlI= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 08/11] selftests/bpf: Add tests to verify global percpu data Date: Mon, 22 Jun 2026 22:35:54 +0800 Message-ID: <20260622143557.22955-9-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" If the arch, like s390x, does not support percpu insn, these cases won't test global percpu data by checking FEAT_PERCPU_DATA support. The following APIs have been tested for global percpu data: 1. bpf_map__set_initial_value() 2. bpf_map__initial_value() 3. generated percpu struct pointer pointing to internal map's mmaped data 4. bpf_map__lookup_elem() for global percpu data map At the same time, the case is also tested with 'bpftool gen skeleton -L'. Add a test to verify that the live vars of subskel won't include the vars for global percpu data. Assisted-by: Codex:gpt-5.5-xhigh Signed-off-by: Leon Hwang --- tools/testing/selftests/bpf/Makefile | 2 +- .../bpf/prog_tests/global_data_init.c | 184 ++++++++++++++++++ .../bpf/prog_tests/global_percpu_subskel.c | 37 ++++ .../bpf/progs/test_global_percpu_data.c | 31 +++ 4 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/global_percpu_su= bskel.c create mode 100644 tools/testing/selftests/bpf/progs/test_global_percpu_da= ta.c diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests= /bpf/Makefile index b642ee489ea6..c37ed9e7b97c 100644 --- a/tools/testing/selftests/bpf/Makefile +++ b/tools/testing/selftests/bpf/Makefile @@ -533,7 +533,7 @@ LSKELS_SIGNED :=3D fentry_test.c fexit_test.c atomics.c =20 # Generate both light skeleton and libbpf skeleton for these LSKELS_EXTRA :=3D test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \ - kfunc_call_test_subprog.c + kfunc_call_test_subprog.c test_global_percpu_data.c SKEL_BLACKLIST +=3D $$(LSKELS) $$(LSKELS_SIGNED) =20 test_static_linked.skel.h-deps :=3D test_static_linked1.bpf.o test_static_= linked2.bpf.o diff --git a/tools/testing/selftests/bpf/prog_tests/global_data_init.c b/to= ols/testing/selftests/bpf/prog_tests/global_data_init.c index 8466332d7406..ea7e4e3d91cf 100644 --- a/tools/testing/selftests/bpf/prog_tests/global_data_init.c +++ b/tools/testing/selftests/bpf/prog_tests/global_data_init.c @@ -1,5 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 #include +#include "bpf/libbpf_internal.h" +#include "test_global_percpu_data.skel.h" +#include "test_global_percpu_data.lskel.h" =20 void test_global_data_init(void) { @@ -60,3 +63,184 @@ void test_global_data_init(void) free(newval); bpf_object__close(obj); } + +static void test_global_percpu_data_init(void) +{ + struct test_global_percpu_data__percpu init_value =3D {}; + struct test_global_percpu_data__percpu *init_data; + int key, prog_fd, err, num_cpus, num_online, i; + struct test_global_percpu_data *skel =3D NULL; + __u64 args[2] =3D {0x1234ULL, 0x5678ULL}; + size_t init_data_sz; + struct bpf_map *map; + bool *online; + LIBBPF_OPTS(bpf_test_run_opts, topts, + .ctx_in =3D args, + .ctx_size_in =3D sizeof(args), + .flags =3D BPF_F_TEST_RUN_ON_CPU, + ); + + num_cpus =3D libbpf_num_possible_cpus(); + if (!ASSERT_GT(num_cpus, 0, "libbpf_num_possible_cpus")) + return; + + err =3D parse_cpu_mask_file("/sys/devices/system/cpu/online", &online, &n= um_online); + if (!ASSERT_OK(err, "parse_cpu_mask_file")) + return; + + skel =3D test_global_percpu_data__open(); + if (!ASSERT_OK_PTR(skel, "test_global_percpu_data__open")) + goto out; + if (!ASSERT_OK_PTR(skel->percpu, "skel->percpu")) + goto out; + + ASSERT_EQ(skel->percpu->data, -1, "skel->percpu->data"); + ASSERT_FALSE(skel->percpu->run, "skel->percpu->run"); + ASSERT_EQ(skel->percpu->nums[6], 0, "skel->percpu->nums[6]"); + ASSERT_EQ(skel->percpu->struct_data.i, -1, "struct_data.i"); + ASSERT_FALSE(skel->percpu->struct_data.set, "struct_data.set"); + ASSERT_EQ(skel->percpu->struct_data.nums[6], 0, "struct_data.nums[6]"); + + map =3D skel->maps.percpu; + if (!ASSERT_EQ(bpf_map__type(map), BPF_MAP_TYPE_PERCPU_ARRAY, "bpf_map__t= ype")) + goto out; + + init_value.data =3D 2; + init_value.nums[6] =3D -1; + init_value.struct_data.i =3D 2; + init_value.struct_data.nums[6] =3D -1; + err =3D bpf_map__set_initial_value(map, &init_value, sizeof(init_value)); + if (!ASSERT_OK(err, "bpf_map__set_initial_value")) + goto out; + + init_data =3D bpf_map__initial_value(map, &init_data_sz); + if (!ASSERT_OK_PTR(init_data, "bpf_map__initial_value")) + goto out; + + ASSERT_EQ(init_data->data, init_value.data, "init_value data"); + ASSERT_EQ(init_data->run, init_value.run, "init_value run"); + ASSERT_EQ(init_data->struct_data.i, init_value.struct_data.i, "init_value= struct_data.i"); + ASSERT_EQ(init_data->struct_data.nums[6], init_value.struct_data.nums[6], + "init_value struct_data.nums[6]"); + ASSERT_EQ(init_data_sz, sizeof(init_value), "init_value size"); + ASSERT_EQ((void *) init_data, (void *) skel->percpu, "skel->percpu eq ini= t_data"); + ASSERT_EQ(skel->percpu->data, init_value.data, "skel->percpu->data"); + ASSERT_EQ(skel->percpu->run, init_value.run, "skel->percpu->run"); + ASSERT_EQ(skel->percpu->struct_data.i, init_value.struct_data.i, + "skel->percpu->struct_data.i"); + ASSERT_EQ(skel->percpu->struct_data.nums[6], init_value.struct_data.nums[= 6], + "skel->percpu->struct_data.nums[6]"); + + err =3D test_global_percpu_data__load(skel); + if (!ASSERT_OK(err, "test_global_percpu_data__load")) + goto out; + + ASSERT_OK_PTR(skel->percpu, "skel->percpu"); + + key =3D 0; + prog_fd =3D bpf_program__fd(skel->progs.update_percpu_data); + + /* run on every CPU */ + for (i =3D 0; i < num_online; i++) { + struct test_global_percpu_data__percpu data =3D {}; + __u64 flags; + + if (!online[i]) + continue; + + topts.cpu =3D i; + topts.retval =3D -1; + err =3D bpf_prog_test_run_opts(prog_fd, &topts); + ASSERT_OK(err, "bpf_prog_test_run_opts"); + ASSERT_EQ(topts.retval, 0, "bpf_prog_test_run_opts retval"); + + flags =3D ((__u64) i << 32) | BPF_F_CPU; + err =3D bpf_map__lookup_elem(map, &key, sizeof(key), &data, sizeof(data)= , flags); + if (!ASSERT_OK(err, "bpf_map__lookup_elem")) + goto out; + + ASSERT_EQ(data.data, 1, "data.data"); + ASSERT_TRUE(data.run, "data.run"); + ASSERT_EQ(data.nums[6], 0xc0de, "data.nums[6]"); + ASSERT_EQ(data.struct_data.i, 1, "struct_data.i"); + ASSERT_TRUE(data.struct_data.set, "struct_data.set"); + ASSERT_EQ(data.struct_data.nums[6], 0xc0de, "struct_data.nums[6]"); + } + +out: + test_global_percpu_data__destroy(skel); + free(online); +} + +static void test_global_percpu_data_lskel(void) +{ + int key, prog_fd, map_fd, err, num_cpus, num_online, i; + struct test_global_percpu_data_lskel *lskel =3D NULL; + __u64 args[2] =3D {0x1234ULL, 0x5678ULL}; + bool *online; + LIBBPF_OPTS(bpf_test_run_opts, topts, + .ctx_in =3D args, + .ctx_size_in =3D sizeof(args), + .flags =3D BPF_F_TEST_RUN_ON_CPU, + ); + + num_cpus =3D libbpf_num_possible_cpus(); + if (!ASSERT_GT(num_cpus, 0, "libbpf_num_possible_cpus")) + return; + + err =3D parse_cpu_mask_file("/sys/devices/system/cpu/online", &online, &n= um_online); + if (!ASSERT_OK(err, "parse_cpu_mask_file")) + return; + + lskel =3D test_global_percpu_data_lskel__open_and_load(); + if (!ASSERT_OK_PTR(lskel, "test_global_percpu_data_lskel__open_and_load")) + goto out; + + key =3D 0; + map_fd =3D lskel->maps.percpu.map_fd; + prog_fd =3D lskel->progs.update_percpu_data.prog_fd; + + /* run on every CPU */ + for (i =3D 0; i < num_online; i++) { + struct test_global_percpu_data__percpu data =3D {}; + __u64 flags; + + if (!online[i]) + continue; + + topts.cpu =3D i; + topts.retval =3D -1; + err =3D bpf_prog_test_run_opts(prog_fd, &topts); + ASSERT_OK(err, "bpf_prog_test_run_opts"); + ASSERT_EQ(topts.retval, 0, "bpf_prog_test_run_opts retval"); + + flags =3D ((__u64) i << 32) | BPF_F_CPU; + err =3D bpf_map_lookup_elem_flags(map_fd, &key, &data, flags); + if (!ASSERT_OK(err, "bpf_map_lookup_elem_flags")) + goto out; + + ASSERT_EQ(data.data, 1, "data.data"); + ASSERT_TRUE(data.run, "data.run"); + ASSERT_EQ(data.nums[6], 0xc0de, "data.nums[6]"); + ASSERT_EQ(data.struct_data.i, 1, "struct_data.i"); + ASSERT_TRUE(data.struct_data.set, "struct_data.set"); + ASSERT_EQ(data.struct_data.nums[6], 0xc0de, "struct_data.nums[6]"); + } + +out: + test_global_percpu_data_lskel__destroy(lskel); + free(online); +} + +void test_global_percpu_data(void) +{ + if (!feat_supported(NULL, FEAT_PERCPU_DATA)) { + test__skip(); + return; + } + + if (test__start_subtest("init")) + test_global_percpu_data_init(); + if (test__start_subtest("lskel")) + test_global_percpu_data_lskel(); +} diff --git a/tools/testing/selftests/bpf/prog_tests/global_percpu_subskel.c= b/tools/testing/selftests/bpf/prog_tests/global_percpu_subskel.c new file mode 100644 index 000000000000..8aebd533d86b --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/global_percpu_subskel.c @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include "test_global_percpu_data.subskel.h" + +void test_global_percpu_data_subskel(void) +{ + struct test_global_percpu_data *subskel =3D NULL; + struct bpf_object *obj; + int i; + + obj =3D bpf_object__open_file("./test_global_percpu_data.bpf.o", NULL); + if (!ASSERT_OK_PTR(obj, "bpf_object__open_file")) + return; + + subskel =3D test_global_percpu_data__open(obj); + if (!ASSERT_OK_PTR(subskel, "test_global_percpu_data__open")) + goto out; + + if (!ASSERT_OK_PTR(subskel->subskel, "subskel")) + goto out; + if (!ASSERT_OK_PTR(subskel->maps.percpu, "maps.percpu")) + goto out; + ASSERT_EQ(bpf_map__type(subskel->maps.percpu), BPF_MAP_TYPE_PERCPU_ARRAY, + "percpu_map_type"); + ASSERT_GT(subskel->subskel->var_cnt, 0, "var_cnt"); + + for (i =3D 0; i < subskel->subskel->var_cnt; i++) { + const struct bpf_var_skeleton *var; + + var =3D (void *) subskel->subskel->vars + i * subskel->subskel->var_skel= _sz; + ASSERT_NEQ(var->map, &subskel->maps.percpu, "var"); + } + +out: + test_global_percpu_data__destroy(subskel); + bpf_object__close(obj); +} diff --git a/tools/testing/selftests/bpf/progs/test_global_percpu_data.c b/= tools/testing/selftests/bpf/progs/test_global_percpu_data.c new file mode 100644 index 000000000000..ba92ffb0ca49 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_global_percpu_data.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include "bpf_misc.h" + +int data SEC(".percpu") =3D -1; +int nums[7] SEC(".percpu"); +char run SEC(".percpu") =3D 0; +struct { + char set; + int i; + int nums[7]; +} struct_data SEC(".percpu") =3D { + .set =3D 0, + .i =3D -1, +}; + +SEC("raw_tp/task_rename") +__auxiliary +int update_percpu_data(void *ctx) +{ + struct_data.nums[6] =3D 0xc0de; + struct_data.set =3D 1; + struct_data.i =3D 1; + nums[6] =3D 0xc0de; + data =3D 1; + run =3D 1; + return 0; +} + +char _license[] SEC("license") =3D "GPL"; --=20 2.54.0 From nobody Sat Jun 27 16:57:08 2026 Received: from out-173.mta0.migadu.com (out-173.mta0.migadu.com [91.218.175.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A6C853BB690 for ; Mon, 22 Jun 2026 14:38:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139087; cv=none; b=GImo2e2bvJWnCDdiUtoayvLStoPJELrVpHqoKWvovzaF1BStEkGNR5OPBDLCXRLizNhdBgZhYf1fRD/YwNGhEMRfOsSqgBP/oJie6XDJBVrpvZcYKHGcVAcPusnb5SaWuxdkRNUshy+BrOeuTgUX0nkM1A7JQR7HyWqmZdO1CTY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139087; c=relaxed/simple; bh=+iVnkSjrUALapW3rs8Y6CctC8RqrBVxpwHvXo41etLM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gBgiZAhzlPC4e2aD6kfuUWCxQW+GnFYH/2/ezu6LCZJQLe26ECkWaiBXEHkaFwA3DsdpVHuru1smTwssNPkqkNVcNNP3efMaXWiT0/6QTv/rJeNpX3C8UkCl3jX+QMpo7PAraUNvmKENFZzUFEakekSTuBGkJHjI/2WmvTrsw5Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=iattQpyr; arc=none smtp.client-ip=91.218.175.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="iattQpyr" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139083; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OsR3j4bPeNB81J31xotlVNAUKQzKW+YGnaUCPQ++dcw=; b=iattQpyrhQFtPR+j6RWrmunE5UX8DN+VRxIrDSR8jpCCaFR22/o1jgIGcsyFUbX+xUrPSN KE/Wm7Yzs1uquR1n6q/wqGHqs6eb9BIrNE5GNXNIXFkhW8tww6hwzTFMbQnRE/T0mj/3YC vqgUbCxtIB0oqXA6lrKEkiSu8BKSuFc= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 09/11] selftests/bpf: Add test to verify accessing rdonly percpu_array Date: Mon, 22 Jun 2026 22:35:55 +0800 Message-ID: <20260622143557.22955-10-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Since percpu_array supports direct-read, it should not break accessing rdonly percpu_array. Add a test to verify that adding '.map_direct_value_addr' to percpu_array won't break the case. Assisted-by: Codex:gpt-5.5-xhigh Signed-off-by: Leon Hwang --- .../bpf/prog_tests/global_data_init.c | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/global_data_init.c b/to= ols/testing/selftests/bpf/prog_tests/global_data_init.c index ea7e4e3d91cf..f59d83919058 100644 --- a/tools/testing/selftests/bpf/prog_tests/global_data_init.c +++ b/tools/testing/selftests/bpf/prog_tests/global_data_init.c @@ -232,6 +232,48 @@ static void test_global_percpu_data_lskel(void) free(online); } =20 +static void test_global_percpu_data_rdonly_direct_read(void) +{ + LIBBPF_OPTS(bpf_map_create_opts, map_opts, + .map_flags =3D BPF_F_RDONLY_PROG, + ); + struct bpf_insn insns[] =3D { + BPF_ST_MEM(BPF_W, BPF_REG_10, -8, 0), + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), + BPF_LD_MAP_FD(BPF_REG_1, 0), + BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), + BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_0, 0), + BPF_EXIT_INSN(), + }; + int key =3D 0, map_fd, prog_fd =3D -1, err; + __u64 value =3D 0; + + map_fd =3D bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, "percpu_ro_map", siz= eof(int), + sizeof(__u64), 1, &map_opts); + if (!ASSERT_GE(map_fd, 0, "bpf_map_create")) + return; + + err =3D bpf_map_update_elem(map_fd, &key, &value, BPF_F_ALL_CPUS); + if (!ASSERT_OK(err, "bpf_map_update_elem")) + goto out; + + err =3D bpf_map_freeze(map_fd); + if (!ASSERT_OK(err, "bpf_map_freeze")) + goto out; + + insns[3].imm =3D map_fd; + prog_fd =3D bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, "percpu_ro_prog", = "GPL", insns, + ARRAY_SIZE(insns), NULL); + ASSERT_GE(prog_fd, 0, "bpf_prog_load"); + +out: + if (prog_fd >=3D 0) + close(prog_fd); + close(map_fd); +} + void test_global_percpu_data(void) { if (!feat_supported(NULL, FEAT_PERCPU_DATA)) { @@ -243,4 +285,6 @@ void test_global_percpu_data(void) test_global_percpu_data_init(); if (test__start_subtest("lskel")) test_global_percpu_data_lskel(); + if (test__start_subtest("rdonly_direct_read")) + test_global_percpu_data_rdonly_direct_read(); } --=20 2.54.0 From nobody Sat Jun 27 16:57:08 2026 Received: from out-182.mta0.migadu.com (out-182.mta0.migadu.com [91.218.175.182]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0CED83BB11C for ; Mon, 22 Jun 2026 14:38:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139107; cv=none; b=ieli2G81c3IS5jxPCevaol0iAMz0o2lPvO6eXTuyAeBM0wd6GiBmiSpJl8IdhQGaL1t9aULjdNPbA4PyoaZxjbYz6RdAkMt3n1S6pNJIQcs8zQSctAU0EHDA8e4T8fDFuuFsaPSa7kvQLlDFiFe6g3oKcVC1inF55WqGHSiWfZA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139107; c=relaxed/simple; bh=k5ztgXjyH2GDbXXyA2xUsORRkWUozVJfGvu0SpgqIl4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DhOU4i1arKw+hsC2GdyycNoA4G9fQm4/VtKSM1zEFvKfmVZURSna/Yn8jtMIR/OUqzcJT33jeF/CBrni/N13i9X52oJJlT1pEALiWj7whvE4XlgiNa8/wUH0FQsNVSvZ0iEFaEUUt+Ges6hPJ0gGjHlwGYnNPOFhL2MtQNQvalA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=gG+8UUkb; arc=none smtp.client-ip=91.218.175.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="gG+8UUkb" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139103; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=30dXQAh3Rbv5muJHoTPKyMD8bLBAM+/VUDQA6uzCiDA=; b=gG+8UUkbJncXHfUcgAA4ImouzqoQ2EDe/nB3Wbyv2JbAwDX+3sH/RZhO+THP+1AwO8T/3x 8UqpS/n0iRoC9/bLtBqvwd3y3IT/NrcS31J8SCLMngLck0pa/m+MCYZlGV5BXgob0hhIVT /ypASjqDangEPAX+Zn8XamKg9YRvgdI= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 10/11] selftests/bpf: Add tests to verify verifier log for global percpu data Date: Mon, 22 Jun 2026 22:35:56 +0800 Message-ID: <20260622143557.22955-11-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Add two tests to verify the verifier log "R%d points to percpu_array map which cannot be used as const string\n". Signed-off-by: Leon Hwang --- .../bpf/prog_tests/global_data_init.c | 6 +++++ .../bpf/progs/test_global_percpu_data.c | 23 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/global_data_init.c b/to= ols/testing/selftests/bpf/prog_tests/global_data_init.c index f59d83919058..e4c290492ff8 100644 --- a/tools/testing/selftests/bpf/prog_tests/global_data_init.c +++ b/tools/testing/selftests/bpf/prog_tests/global_data_init.c @@ -274,6 +274,11 @@ static void test_global_percpu_data_rdonly_direct_read= (void) close(map_fd); } =20 +static void test_global_percpu_data_verifier_log(void) +{ + RUN_TESTS(test_global_percpu_data); +} + void test_global_percpu_data(void) { if (!feat_supported(NULL, FEAT_PERCPU_DATA)) { @@ -287,4 +292,5 @@ void test_global_percpu_data(void) test_global_percpu_data_lskel(); if (test__start_subtest("rdonly_direct_read")) test_global_percpu_data_rdonly_direct_read(); + test_global_percpu_data_verifier_log(); } diff --git a/tools/testing/selftests/bpf/progs/test_global_percpu_data.c b/= tools/testing/selftests/bpf/progs/test_global_percpu_data.c index ba92ffb0ca49..a6109e835948 100644 --- a/tools/testing/selftests/bpf/progs/test_global_percpu_data.c +++ b/tools/testing/selftests/bpf/progs/test_global_percpu_data.c @@ -28,4 +28,27 @@ int update_percpu_data(void *ctx) return 0; } =20 +static const char fmt[] SEC(".percpu.fmt") =3D "data %d\n"; + +SEC("?kprobe") +__failure __msg("R{{[0-9]+}} points to percpu_array map which cannot be us= ed as const string") +int verifier_strncmp(void *ctx) +{ + return bpf_strncmp("test", 5, fmt); +} + +SEC("?kprobe") +__failure __msg("R{{[0-9]+}} points to percpu_array map which cannot be us= ed as const string") +int verifier_snprintf(void *ctx) +{ + u64 args[] =3D { data }; + char buf[128]; + int len; + + len =3D bpf_snprintf(buf, sizeof(buf), fmt, args, sizeof(args)); + if (len > 0) + bpf_printk("snprintf: %s\n", buf); + return 0; +} + char _license[] SEC("license") =3D "GPL"; --=20 2.54.0 From nobody Sat Jun 27 16:57:08 2026 Received: from out-180.mta0.migadu.com (out-180.mta0.migadu.com [91.218.175.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2B7B53BB11C for ; Mon, 22 Jun 2026 14:38:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139113; cv=none; b=SxifGqq2JH07ohCP5dOAJ3b7aIhpHY/Ac7d2EABPoPtJoJCxcS1D0dyGSA07lfFWmx2/2Y89a4+Ikq9WMbPsQjRihxGKlrXROPpXrCcEnD0TT9RD2ymldrm+vo1rAMPdeHEbDT/flkYf78RFzkJslRdVxqkUkGd586ZX1LOwi2w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1782139113; c=relaxed/simple; bh=fUlHDhqMND/+L5o8UANvRTu5cPuiJV9GP64c+IU43TU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=M0+MhrSksL+oG3m0ZyA7bwCERw2RAGWpR+th5BGtuZPbWDak5Uf9TZsbrjYlgcAntdRt5/BtXpObSSe4GendrIrYysmWDo/K62NfUX0kZFE3TJRXDP7GpKTUFFiLBrlnbBZlX2oTfJA0OTdtfttLzeNUSrdz1P9tHBhjeKWFBs4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=PS1b7DfH; arc=none smtp.client-ip=91.218.175.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="PS1b7DfH" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1782139110; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=oL91VbNPZmNAnrvPuLt4rbdhEqEsR9yfGCAnPPhy9Oc=; b=PS1b7DfHY5caMB7qEPJvwqkCXQIL9KW4nbMR0TJT2ENDj/Zb24jv4MdztkvXNvpHcV6sh8 S9m28zUbPLRGh3LACxB47M5CiYGWgj4PWtnAPTeB5YUU83zW+rDM1ficwjPQK+ixVaKl6m CVAbpUKFQF/OH5+ytaOjeYzUsKFV5+I= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Quentin Monnet , Shuah Khan , Leon Hwang , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v7 11/11] selftests/bpf: Add test to verify bpf_iter for global percpu data Date: Mon, 22 Jun 2026 22:35:57 +0800 Message-ID: <20260622143557.22955-12-leon.hwang@linux.dev> In-Reply-To: <20260622143557.22955-1-leon.hwang@linux.dev> References: <20260622143557.22955-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Add a test to verify that it is OK to iter the percpu_array map used for global percpu data. Signed-off-by: Leon Hwang --- .../bpf/prog_tests/global_data_init.c | 52 +++++++++++++++++++ .../bpf/progs/test_global_percpu_data.c | 25 +++++++++ 2 files changed, 77 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/global_data_init.c b/to= ols/testing/selftests/bpf/prog_tests/global_data_init.c index e4c290492ff8..32734e1dbfb0 100644 --- a/tools/testing/selftests/bpf/prog_tests/global_data_init.c +++ b/tools/testing/selftests/bpf/prog_tests/global_data_init.c @@ -279,6 +279,56 @@ static void test_global_percpu_data_verifier_log(void) RUN_TESTS(test_global_percpu_data); } =20 +static void test_global_percpu_data_iter(void) +{ + DECLARE_LIBBPF_OPTS(bpf_iter_attach_opts, opts); + struct test_global_percpu_data *skel; + union bpf_iter_link_info linfo =3D {}; + struct bpf_link *link =3D NULL; + int fd, num_cpus, len, err; + char buf[16]; + + num_cpus =3D libbpf_num_possible_cpus(); + if (!ASSERT_GT(num_cpus, 0, "libbpf_num_possible_cpus")) + return; + + skel =3D test_global_percpu_data__open(); + if (!ASSERT_OK_PTR(skel, "test_global_percpu_data__open")) + return; + + skel->rodata->num_cpus =3D num_cpus; + skel->rodata->offsetof_num =3D offsetof(struct test_global_percpu_data__p= ercpu, struct_data); + skel->rodata->offsetof_num +=3D sizeof(skel->percpu->struct_data) - sizeo= f(int); + skel->rodata->elem_sz =3D roundup(sizeof(struct test_global_percpu_data__= percpu), 8); + skel->percpu->struct_data.nums[6] =3D 0xc0de; + + err =3D test_global_percpu_data__load(skel); + if (!ASSERT_OK(err, "test_global_percpu_data__load")) + goto out; + + linfo.map.map_fd =3D bpf_map__fd(skel->maps.percpu); + opts.link_info =3D &linfo; + opts.link_info_len =3D sizeof(linfo); + link =3D bpf_program__attach_iter(skel->progs.dump_percpu_data, &opts); + if (!ASSERT_OK_PTR(link, "bpf_program__attach_iter")) + goto out; + + fd =3D bpf_iter_create(bpf_link__fd(link)); + if (!ASSERT_GE(fd, 0, "bpf_iter_create")) + goto out; + + while ((len =3D read(fd, buf, sizeof(buf))) > 0) + do { } while (0); + ASSERT_EQ(len, 0, "read iter"); + ASSERT_TRUE(skel->bss->run_iter, "run_iter"); + ASSERT_EQ(skel->bss->percpu_data_sum, 0xc0de * num_cpus, "percpu_data_sum= "); + + close(fd); +out: + bpf_link__destroy(link); + test_global_percpu_data__destroy(skel); +} + void test_global_percpu_data(void) { if (!feat_supported(NULL, FEAT_PERCPU_DATA)) { @@ -293,4 +343,6 @@ void test_global_percpu_data(void) if (test__start_subtest("rdonly_direct_read")) test_global_percpu_data_rdonly_direct_read(); test_global_percpu_data_verifier_log(); + if (test__start_subtest("iter")) + test_global_percpu_data_iter(); } diff --git a/tools/testing/selftests/bpf/progs/test_global_percpu_data.c b/= tools/testing/selftests/bpf/progs/test_global_percpu_data.c index a6109e835948..eef88fd61af5 100644 --- a/tools/testing/selftests/bpf/progs/test_global_percpu_data.c +++ b/tools/testing/selftests/bpf/progs/test_global_percpu_data.c @@ -51,4 +51,29 @@ int verifier_snprintf(void *ctx) return 0; } =20 +volatile const __u32 num_cpus =3D 0; +volatile const int offsetof_num; +volatile const int elem_sz; +__u32 percpu_data_sum =3D 0; +bool run_iter =3D false; + +SEC("iter/bpf_map_elem") +__auxiliary +int dump_percpu_data(struct bpf_iter__bpf_map_elem *ctx) +{ + void *pptr =3D ctx->value; + int i; + + if (!pptr) + return 0; + + run_iter =3D true; + + for (i =3D 0; i < num_cpus; i++) { + percpu_data_sum +=3D *(int *) (pptr + offsetof_num); + pptr +=3D elem_sz; + } + return 0; +} + char _license[] SEC("license") =3D "GPL"; --=20 2.54.0