From: Xu Kuohai Introduce two helpers for user space. - bpf_map__arena_percpu_base(): return the base address of the arena percpu. The generated skeleton will call it to set up its arena percpu data. - bpf_map__arena_percpu_ptr(): translate a variable address in cpu 0's chunk to the address in the target cpu's chunk. Signed-off-by: Xu Kuohai --- tools/lib/bpf/libbpf.c | 49 ++++++++++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf.h | 26 +++++++++++++++++++++ tools/lib/bpf/libbpf.map | 2 ++ 3 files changed, 77 insertions(+) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index be2ddaf96631..0edce476451c 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -12287,6 +12287,55 @@ void *bpf_map__initial_value(const struct bpf_map *map, size_t *psize) return map->mmaped; } +void *bpf_map__arena_percpu_ptr(const struct bpf_map *map, void *ptr, unsigned int cpu) +{ + struct bpf_object *obj; + uint64_t base; + + if (!map || !ptr) + return libbpf_err_ptr(-EINVAL); + + obj = map->obj; + if (map->def.type != BPF_MAP_TYPE_ARENA || !obj->arena_percpu.present) + return libbpf_err_ptr(-EINVAL); + + if (cpu >= obj->arena_percpu.nr_chunks) + return libbpf_err_ptr(-ERANGE); + + /* + * obj->arena_percpu.chunk is freed by arena_percpu_populate(), and only + * then the map is mmaped + */ + if (obj->arena_percpu.chunk) + return libbpf_err_ptr(-EINVAL); + + base = (uint64_t)map->mmaped + obj->arena_percpu.offset; + if ((uint64_t)ptr < base || (uint64_t)ptr >= base + obj->arena_percpu.chunk_sz) + return libbpf_err_ptr(-EINVAL); + + return (void *)((uint64_t)ptr + (uint64_t)cpu * obj->arena_percpu.chunk_sz); +} + +void *bpf_map__arena_percpu_base(const struct bpf_map *map) +{ + struct bpf_object *obj; + + if (!map) + return NULL; + + obj = map->obj; + /* + * The per-cpu chunks exist once the map is created and populated; + * obj->arena_percpu.chunk is freed by arena_percpu_populate(), and + * only then the map is mmaped + */ + if (map->def.type != BPF_MAP_TYPE_ARENA || !obj->arena_percpu.present || + obj->arena_percpu.chunk) + return NULL; + + return map->mmaped + obj->arena_percpu.offset; +} + bool bpf_map__is_internal(const struct bpf_map *map) { return map->libbpf_type != LIBBPF_MAP_UNSPEC; diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 3e0b7bc91bef..31d3982226cc 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -1230,6 +1230,32 @@ LIBBPF_API int bpf_map__set_initial_value(struct bpf_map *map, */ LIBBPF_API void *bpf_map__initial_value(const struct bpf_map *map, size_t *psize); +/** + * @brief **bpf_map__arena_percpu_ptr()** translates an address within + * cpu 0's chunk of the arena's per-cpu area (e.g. the address of an + * `__arena_percpu` variable as seen in the skeleton's arena_percpu + * section) to the per-cpu chunk of the requested @cpu. + * @param map the ARENA map + * @param ptr address of an `__arena_percpu` variable (cpu 0's chunk) + * @param cpu cpu id to obtain the chunk for + * @return pointer to the variable in the chunk of @cpu; error pointer, if the + * map is not a loaded ARENA map with a per-cpu area, @cpu is out of range, + * or @ptr is not within cpu 0's chunk + */ +LIBBPF_API void *bpf_map__arena_percpu_ptr(const struct bpf_map *map, void *ptr, + unsigned int cpu); + +/** + * @brief **bpf_map__arena_percpu_base()** returns the base of cpu 0's + * chunk of the arena's per-cpu area in the user-space-visible mmap of + * the arena, i.e. where the skeleton's arena_percpu section points. + * @param map the ARENA map + * @return pointer to the start of cpu 0's chunk; NULL if @map is not a + * loaded ARENA map whose per-cpu chunks have been populated (e.g. + * before load, or for a map with `autocreate == false`) + */ +LIBBPF_API void *bpf_map__arena_percpu_base(const struct bpf_map *map); + /** * @brief **bpf_map__is_internal()** tells the caller whether or not the * passed map is a special map created by libbpf automatically for things like diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index eeba4072a5da..eda89ab60543 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -458,6 +458,8 @@ LIBBPF_1.7.0 { LIBBPF_1.8.0 { global: + bpf_map__arena_percpu_base; + bpf_map__arena_percpu_ptr; bpf_map__attach_cgroup_opts; bpf_prog_stream_open; bpf_program__add_flags; -- 2.47.3