From nobody Sun May 24 17:49:15 2026 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8D2A73911D2 for ; Sun, 24 May 2026 11:43:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779622996; cv=none; b=I2eiJU1Xtobi5h3TZKiS87f7lPTpz5f0XKHjtunAlgDdq5hGgpUWzEAm6EvKiLb2yjBNicNRh2vXcsa6qcMLInaLYSmNEEJutH6Dvjp0gPSt7jSV+2B9/w4A9NWffaW9NBlAEe7KPm/+3k8aITMSWqAwgN9KFw/0M33wM1b4vJs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779622996; c=relaxed/simple; bh=XGaNu7SgYVdyaX3ndSTc4PQLCv4QWQfl3nIO4oftQJc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JzDxKBUuCQkEiE7Bb2llRI6/Ey/FLSSCQduFZD5lLgBxQ84AjQxSv8eLvb0tydFfY8BRxwUU7tRaKhD5jRyvzYzzpHjMR8mvlSfq2qxeIu0e2HO6KPF3mxvNeDXpGHs7MjKDz4ck1ogTcgcK/fPBYPhzRt0hDiJdNeHHKSXrhZw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=obUNq4l9; arc=none smtp.client-ip=209.85.128.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="obUNq4l9" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-4896c22fcbaso73322885e9.0 for ; Sun, 24 May 2026 04:43:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779622993; x=1780227793; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=uRurXpwEfwTN2fB8fdG+G2wFxewUTYz7K8ld4XqHEY8=; b=obUNq4l9AD38AmTLSlH3sLuuxakh/yjv8tnkGYPQgbVVEVDQtbyCk2g+xDzORcllue UJcFjdW6MV0jBjzR4q+gmD6FQ6Wh+ZdS4anNLhkP/JF33LqvprFrcqsu1lwXJui6Ey8w bYuy673fnWH7meAoETK1DLNeOIYVvfVqlzWpkEHIa4my1pJ1oOuakSocy888tQHLdMdo EkB8OdSGP+0CTVUWXsL5sQTavDaYYrtBHUTe9HSWdvUdLxWHarUgA37L4Tv/5rh2lxwX n2hZxg6vkuucDFX/dFoGHes+KUzWCF/wy4dBH3boiPaiOxWujzIzN7i4jUAr2yrg/RpF Bfaw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779622993; x=1780227793; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=uRurXpwEfwTN2fB8fdG+G2wFxewUTYz7K8ld4XqHEY8=; b=byUXhlCv6PLByzQ0QoeozBF6N8m/CmIgxo+XBIYSneAGmJgPlvyUCU9ptsfzFNs8mh hIAQYbdbA13/oEEe/VEriqphapdkbD/1E5nahxbbbQbmHLJctWYjOVYbQ9hKtNsZii/6 VxWaLFHPRS0Pm3lPiNXVJbgHXo3Ne43r2ImMI6rSPQXPXJUx6MqfGpkx5hJxzSVfUCQ8 4aGWh1eGrk0WVBVfhda7Vw9jOoBNMJcqYZGbhl5hpF3PO1C6dHrhALi26XP3bauC5Oo4 IkDy7mq4QyI1WsEyzyIXlmOhniznUULCN6aAqYc7Bf0Xgmk8KeuPAhYAX+3C66XGKJNp 2rsA== X-Forwarded-Encrypted: i=1; AFNElJ959LZuOkDvSvJSsHwp5KlEpFa3ey1d7/qghPorTRxpUhWhq6Y1Q64aLg2B9989kAmCCk+LlKq+KWYafsU=@vger.kernel.org X-Gm-Message-State: AOJu0YwN/Mx1zvg4YJENoDMLabt8vDLRaJomcyV4V+9lQ5noYq5s+5z7 UQK9ehx3sIdBtU+opiFidEmRUA6ytZn0fTYu/YgbtSxyOv12Jw4nMmNI X-Gm-Gg: Acq92OE6qw/cDLwXxZFF+U/HM1rOklNdxSWj53MwkiezIoHXteClv6pJhA7hFq4v/eg 7P5mnxgDB3TiaXGjlBLFGmRSqO4ZHdE15Y1AwbxhWCUbGs9EMHFVEdJhG7oDjLZ1OuOH6XEJI5D ZvsgyVxC9zWxAv9i1B01I2R6PdKP2mkXGhYRc6xiKjxPI5P4KoDcQpwREKXBpWZyjTI5NKmoqjS IdFAblUsB/t4IV/cXvzFiY4/lzyBC6y1PnN8AFXcCq6ksOwiJ0yHT1Q2DVyInFppJy0qdaj2XC0 C+EUhilG8T80t06aGTec6shv8ZxgEtyQs2wIhGUDdJMd/y8/iChCv36OQBKhM8yRShleMg5LP8Y KilaYpqMNPboaqV5S/7qJe4KIIykMjEQywGrMhvJO50zQRx3dzMXhXGxiKEs192S+21Fc6P0h16 Tufv41Zfqiyh1/2G+EM86HcwNFZnZINhDNJKtlgb1HIAsqm/CL/o89R4qrXWTD4jEfBHhShug= X-Received: by 2002:a05:600c:35c8:b0:490:44eb:c1e7 with SMTP id 5b1f17b1804b1-49044ebc2d5mr182436885e9.30.1779622992830; Sun, 24 May 2026 04:43:12 -0700 (PDT) Received: from ds-pc.. (host86-141-80-34.range86-141.btcentralplus.com. [86.141.80.34]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-490428d4cefsm62533065e9.14.2026.05.24.04.43.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 24 May 2026 04:43:12 -0700 (PDT) From: Dhiraj Shah To: bpf@vger.kernel.org Cc: ast@kernel.org, alexei.starovoitov@gmail.com, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev, eddyz87@gmail.com, memxor@gmail.com, song@kernel.org, yonghong.song@linux.dev, jolsa@kernel.org, corbet@lwn.net, skhan@linuxfoundation.org, emil@etsalapatis.com, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH bpf-next v2] bpf: Add kernel-doc for arena page kfuncs Date: Sun, 24 May 2026 12:42:43 +0100 Message-ID: <20260524114243.259916-1-find.dhiraj@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260521043553.199781-1-find.dhiraj@gmail.com> References: <20260521043553.199781-1-find.dhiraj@gmail.com> 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 Content-Type: text/plain; charset="utf-8" The page-management kfuncs exposed by BPF arena - bpf_arena_alloc_pages(), bpf_arena_free_pages() and bpf_arena_reserve_pages() - are part of the BPF kfunc ABI but lack rendered documentation. Their contracts (valid argument ranges, sleepable-only context, and the set of error returns) are today only discoverable by reading kernel/bpf/arena.c. Add a kernel-doc comment block above each of the three kfuncs and render them under a new "BPF arena kfuncs" subsection in Documentation/bpf/kfuncs.rst, alongside the existing core kfunc subsections. No functional change. Signed-off-by: Dhiraj Shah --- Changes in v2: - Fix the return-value description for bpf_arena_alloc_pages(): the kfunc returns a user-space virtual address (translated by the BPF JIT for accesses from the BPF program), not a kernel pointer. Thanks to Alexei Starovoitov, Emil Tsalapatis and the AI reviewers for catching this. - Drop the "callable only from sleepable BPF programs" claims for bpf_arena_alloc_pages() and bpf_arena_free_pages(): the verifier rewrites these calls to their _non_sleepable variants when the calling program is non-sleepable, so callers do not need to care about this distinction. Thanks to Emil Tsalapatis. - Tighten the prose in Documentation/bpf/kfuncs.rst accordingly. v1: https://lore.kernel.org/bpf/20260521043553.199781-1-find.dhiraj@gmail.= com/ Documentation/bpf/kfuncs.rst | 26 ++++++++++++++++ kernel/bpf/arena.c | 59 ++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/Documentation/bpf/kfuncs.rst b/Documentation/bpf/kfuncs.rst index 75e6c078e0e7..28b6b477012a 100644 --- a/Documentation/bpf/kfuncs.rst +++ b/Documentation/bpf/kfuncs.rst @@ -732,3 +732,29 @@ the verifier. bpf_cgroup_ancestor() can be used as fol= lows: BPF provides a set of kfuncs that can be used to query, allocate, mutate, = and destroy struct cpumask * objects. Please refer to :ref:`cpumasks-header-la= bel` for more details. + +4.4 BPF arena kfuncs +-------------------- + +A BPF arena (``BPF_MAP_TYPE_ARENA``) is a sparsely-populated shared memory +region that a BPF program and a user-space process can both address. The +following kfuncs allow a BPF program to allocate, free, and reserve pages +within an arena: + +.. kernel-doc:: kernel/bpf/arena.c + :identifiers: bpf_arena_alloc_pages bpf_arena_free_pages bpf_arena_rese= rve_pages + +A typical pattern is to allocate one or more pages, write to them from BPF, +and let user space access the same pages through its mapping of the arena: + +.. code-block:: c + + void __arena *page; + + page =3D bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0); + if (!page) + return -ENOMEM; + + /* ... use the page from BPF; user space sees the same bytes ... */ + + bpf_arena_free_pages(&arena, page, 1); diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c index 49a8f7b1beef..948a43159106 100644 --- a/kernel/bpf/arena.c +++ b/kernel/bpf/arena.c @@ -870,6 +870,31 @@ static void arena_free_irq(struct irq_work *iw) =20 __bpf_kfunc_start_defs(); =20 +/** + * bpf_arena_alloc_pages() - Allocate pages within a BPF arena. + * @p__map: Pointer to a ``BPF_MAP_TYPE_ARENA`` map. + * @addr__ign: Page-aligned user-space address within the arena at which to + * place the allocation, or %NULL to let the kernel choose. When + * non-NULL the address must fall inside the arena's user VMA + * range; otherwise the allocation fails. + * @page_cnt: Number of pages to allocate. Must be non-zero and no greater + * than the arena's configured size in pages. + * @node_id: NUMA node hint for the backing pages, or %NUMA_NO_NODE. + * @flags: Reserved for future use; must be 0. + * + * Allocates @page_cnt pages and inserts them into the arena at the offset + * corresponding to @addr__ign (or at an arbitrary free offset when + * @addr__ign is %NULL). The pages become accessible to the BPF program + * immediately and to user space through the arena's mmap()ed region. + * + * Return: + * * The user-space virtual address of the start of the allocated region on + * success. The BPF JIT translates this address for accesses from the BPF + * program. + * * %NULL if @p__map is not an arena, @flags is non-zero, @page_cnt is ze= ro + * or exceeds the arena size, @addr__ign is misaligned or outside the + * arena, @node_id is invalid, or the kernel is out of memory. + */ __bpf_kfunc void *bpf_arena_alloc_pages(void *p__map, void *addr__ign, u32= page_cnt, int node_id, u64 flags) { @@ -893,6 +918,20 @@ void *bpf_arena_alloc_pages_non_sleepable(void *p__map= , void *addr__ign, u32 pag =20 return (void *)arena_alloc_pages(arena, (long)addr__ign, page_cnt, node_i= d, false); } + +/** + * bpf_arena_free_pages() - Free a range of pages within a BPF arena. + * @p__map: Pointer to a ``BPF_MAP_TYPE_ARENA`` map. + * @ptr__ign: User-space virtual address of the first page to free, as + * returned by bpf_arena_alloc_pages(). + * @page_cnt: Number of pages to free. + * + * Releases the backing pages and unmaps them from any user-space mapping + * of the arena. + * + * The call is a no-op when @p__map is not an arena, when @page_cnt is zer= o, + * or when @ptr__ign is %NULL. + */ __bpf_kfunc void bpf_arena_free_pages(void *p__map, void *ptr__ign, u32 pa= ge_cnt) { struct bpf_map *map =3D p__map; @@ -913,6 +952,26 @@ void bpf_arena_free_pages_non_sleepable(void *p__map, = void *ptr__ign, u32 page_c arena_free_pages(arena, (long)ptr__ign, page_cnt, false); } =20 +/** + * bpf_arena_reserve_pages() - Reserve a page range within a BPF arena. + * @p__map: Pointer to a ``BPF_MAP_TYPE_ARENA`` map. + * @ptr__ign: Page-aligned user-space virtual address of the start of the + * range to reserve. + * @page_cnt: Number of pages to reserve. Zero is permitted and is a no-op. + * + * Marks @page_cnt pages starting at @ptr__ign as reserved so that subsequ= ent + * bpf_arena_alloc_pages() calls will not place allocations in that range. + * No physical pages are allocated by this kfunc; the range is simply + * excluded from the arena's free space. + * + * Return: + * * 0 on success, or when @page_cnt is zero. + * * -EINVAL if @p__map is not an arena or the requested range falls outsi= de + * the arena's user VMA. + * * -EBUSY if any page in the requested range is already allocated, or if + * contention on the arena's internal spinlock prevents the operation fr= om + * completing. + */ __bpf_kfunc int bpf_arena_reserve_pages(void *p__map, void *ptr__ign, u32 = page_cnt) { struct bpf_map *map =3D p__map; --=20 2.43.0