[PATCH bpf-next 08/16] bpf: Extend syscall to accept arena percpu information
From: Xu Kuohai
Date: Tue Oct 20 2026 - 10:16:41 EST
From: Xu Kuohai <xukuohai@xxxxxxxxxx>
Extend the bpf syscall to accept the arena percpu chunk offset and
size. Both are checked at arena creation time to make sure they are
page-aligned and the percpu chunks live inside the arena vm_range. If
the checks pass, the values are stored in struct bpf_arena for the
verifier and the JIT.
Signed-off-by: Xu Kuohai <xukuohai@xxxxxxxxxx>
---
include/uapi/linux/bpf.h | 4 ++++
kernel/bpf/arena.c | 18 ++++++++++++++++++
kernel/bpf/syscall.c | 2 +-
3 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 9e5fa52c9bc2..6b17dcfc36b4 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1628,6 +1628,10 @@ union bpf_attr {
__aligned_u64 excl_prog_hash;
/* Size of the passed excl_prog_hash. */
__u32 excl_prog_hash_size;
+
+ /* offset and size of an arena percpu chunk */
+ __u32 arena_percpu_chunk_off;
+ __u32 arena_percpu_chunk_sz;
};
struct { /* anonymous struct used by BPF_MAP_*_ELEM and BPF_MAP_FREEZE commands */
diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
index 868589f07330..05cd6397adae 100644
--- a/kernel/bpf/arena.c
+++ b/kernel/bpf/arena.c
@@ -67,6 +67,9 @@ struct bpf_arena {
struct irq_work free_irq;
struct work_struct free_work;
struct llist_head free_spans;
+ /* percpu chunk offset and size */
+ u32 percpu_chunk_off;
+ u32 percpu_chunk_sz;
};
static void arena_free_worker(struct work_struct *work);
@@ -298,6 +301,17 @@ static struct bpf_map *arena_map_alloc(union bpf_attr *attr)
/* user vma must not cross 32-bit boundary */
return ERR_PTR(-ERANGE);
+ if (attr->arena_percpu_chunk_sz) {
+ u64 offset = attr->arena_percpu_chunk_off;
+ u64 size = attr->arena_percpu_chunk_sz;
+
+ if (!IS_ALIGNED(offset, PAGE_SIZE) || !IS_ALIGNED(size, PAGE_SIZE))
+ return ERR_PTR(-EINVAL);
+
+ if (offset > vm_range || size > (vm_range - offset) / nr_cpu_ids)
+ return ERR_PTR(-E2BIG);
+ }
+
kern_vm = get_vm_area(KERN_VM_SZ, VM_SPARSE | VM_USERMAP);
if (!kern_vm)
return ERR_PTR(-ENOMEM);
@@ -311,6 +325,10 @@ static struct bpf_map *arena_map_alloc(union bpf_attr *attr)
if (arena->user_vm_start)
arena->user_vm_end = arena->user_vm_start + vm_range;
+ arena->percpu_chunk_sz = attr->arena_percpu_chunk_sz;
+ if (attr->arena_percpu_chunk_sz)
+ arena->percpu_chunk_off = attr->arena_percpu_chunk_off;
+
INIT_LIST_HEAD(&arena->vma_list);
init_llist_head(&arena->free_spans);
init_irq_work(&arena->free_irq, arena_free_irq);
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 849bc9136299..240c7349284d 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1396,7 +1396,7 @@ static int map_check_btf(struct bpf_map *map, struct bpf_token *token,
return ret;
}
-#define BPF_MAP_CREATE_LAST_FIELD excl_prog_hash_size
+#define BPF_MAP_CREATE_LAST_FIELD arena_percpu_chunk_sz
/* called via syscall */
static int map_create_alloc(union bpf_attr *attr, bpfptr_t uattr, struct bpf_verifier_log *log,
struct bpf_map **mapp, struct bpf_token **tokenp)
--
2.47.3