On Thu, Aug 13, 2026 at 8:24 AM Leon Hwang <[email protected]> wrote:
>
> 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.
>
> Acked-by: Quentin Monnet <[email protected]>
> Assisted-by: Codex:gpt-5.5-xhigh
> Signed-off-by: Leon Hwang <[email protected]>
> ---
> tools/bpf/bpftool/gen.c | 53 +++++++++++++++++++++++++++--------
> tools/lib/bpf/skel_internal.h | 24 ++++++++++++++--
> 2 files changed, 63 insertions(+), 14 deletions(-)
[...]
> @@ -263,13 +269,24 @@ static bool is_mmapable_map(const struct bpf_map *map,
> char *buf, size_t sz)
> return true;
> }
>
> - if (!bpf_map__is_internal(map) || !(bpf_map__map_flags(map) &
> BPF_F_MMAPABLE))
> + if (!bpf_map__is_internal(map))
> return false;
>
> if (!get_map_ident(map, buf, sz))
> return false;
>
> - return true;
> + if (bpf_map__map_flags(map) & BPF_F_MMAPABLE)
> + return true;
> +
> + if (bpf_map__type(map) == BPF_MAP_TYPE_PERCPU_ARRAY)
> + return bpf_map__btf_value_type_id(map) != 0;
why do we need this btf_value_type_id() check? in what case it's
expected that there will be no BTF info set?
> +
> + return false;
> +}
> +
> +static bool is_mmapable_map(const struct bpf_map *map, char *buf, size_t sz)
> +{
> + return is_skel_data(map, buf, sz) && bpf_map__type(map) !=
> BPF_MAP_TYPE_PERCPU_ARRAY;
> }
>
[...]