xref: /linux/tools/testing/selftests/bpf/progs/cpumask_common.h (revision 3d5ad2d4eca337e80f38df77de89614aa5aaceb9)
17b6abcfaSDavid Vernet /* SPDX-License-Identifier: GPL-2.0 */
27b6abcfaSDavid Vernet /* Copyright (c) 2023 Meta Platforms, Inc. and affiliates. */
37b6abcfaSDavid Vernet 
47b6abcfaSDavid Vernet #ifndef _CPUMASK_COMMON_H
57b6abcfaSDavid Vernet #define _CPUMASK_COMMON_H
67b6abcfaSDavid Vernet 
77b6abcfaSDavid Vernet #include "errno.h"
87b6abcfaSDavid Vernet #include <stdbool.h>
97b6abcfaSDavid Vernet 
10*c456f080SHou Tao /* Should use BTF_FIELDS_MAX, but it is not always available in vmlinux.h,
11*c456f080SHou Tao  * so use the hard-coded number as a workaround.
12*c456f080SHou Tao  */
13*c456f080SHou Tao #define CPUMASK_KPTR_FIELDS_MAX 11
14*c456f080SHou Tao 
157b6abcfaSDavid Vernet int err;
167b6abcfaSDavid Vernet 
172ce987e1SJose E. Marchesi #define private(name) SEC(".bss." #name) __attribute__((aligned(8)))
18a5a197dfSDavid Vernet private(MASK) static struct bpf_cpumask __kptr * global_mask;
19a5a197dfSDavid Vernet 
207b6abcfaSDavid Vernet struct __cpumask_map_value {
2103b77e17SAlexei Starovoitov 	struct bpf_cpumask __kptr * cpumask;
227b6abcfaSDavid Vernet };
237b6abcfaSDavid Vernet 
247b6abcfaSDavid Vernet struct array_map {
257b6abcfaSDavid Vernet 	__uint(type, BPF_MAP_TYPE_ARRAY);
267b6abcfaSDavid Vernet 	__type(key, int);
277b6abcfaSDavid Vernet 	__type(value, struct __cpumask_map_value);
287b6abcfaSDavid Vernet 	__uint(max_entries, 1);
297b6abcfaSDavid Vernet } __cpumask_map SEC(".maps");
307b6abcfaSDavid Vernet 
31ba6a6abbSYafang Shao struct bpf_cpumask *bpf_cpumask_create(void) __ksym __weak;
32ba6a6abbSYafang Shao void bpf_cpumask_release(struct bpf_cpumask *cpumask) __ksym __weak;
33ba6a6abbSYafang Shao struct bpf_cpumask *bpf_cpumask_acquire(struct bpf_cpumask *cpumask) __ksym __weak;
34ba6a6abbSYafang Shao u32 bpf_cpumask_first(const struct cpumask *cpumask) __ksym __weak;
35ba6a6abbSYafang Shao u32 bpf_cpumask_first_zero(const struct cpumask *cpumask) __ksym __weak;
3658476d8aSDavid Vernet u32 bpf_cpumask_first_and(const struct cpumask *src1,
37ba6a6abbSYafang Shao 			  const struct cpumask *src2) __ksym __weak;
38ba6a6abbSYafang Shao void bpf_cpumask_set_cpu(u32 cpu, struct bpf_cpumask *cpumask) __ksym __weak;
39ba6a6abbSYafang Shao void bpf_cpumask_clear_cpu(u32 cpu, struct bpf_cpumask *cpumask) __ksym __weak;
40ba6a6abbSYafang Shao bool bpf_cpumask_test_cpu(u32 cpu, const struct cpumask *cpumask) __ksym __weak;
41ba6a6abbSYafang Shao bool bpf_cpumask_test_and_set_cpu(u32 cpu, struct bpf_cpumask *cpumask) __ksym __weak;
42ba6a6abbSYafang Shao bool bpf_cpumask_test_and_clear_cpu(u32 cpu, struct bpf_cpumask *cpumask) __ksym __weak;
43ba6a6abbSYafang Shao void bpf_cpumask_setall(struct bpf_cpumask *cpumask) __ksym __weak;
44ba6a6abbSYafang Shao void bpf_cpumask_clear(struct bpf_cpumask *cpumask) __ksym __weak;
457b6abcfaSDavid Vernet bool bpf_cpumask_and(struct bpf_cpumask *cpumask,
467b6abcfaSDavid Vernet 		     const struct cpumask *src1,
47ba6a6abbSYafang Shao 		     const struct cpumask *src2) __ksym __weak;
487b6abcfaSDavid Vernet void bpf_cpumask_or(struct bpf_cpumask *cpumask,
497b6abcfaSDavid Vernet 		    const struct cpumask *src1,
50ba6a6abbSYafang Shao 		    const struct cpumask *src2) __ksym __weak;
517b6abcfaSDavid Vernet void bpf_cpumask_xor(struct bpf_cpumask *cpumask,
527b6abcfaSDavid Vernet 		     const struct cpumask *src1,
53ba6a6abbSYafang Shao 		     const struct cpumask *src2) __ksym __weak;
54ba6a6abbSYafang Shao bool bpf_cpumask_equal(const struct cpumask *src1, const struct cpumask *src2) __ksym __weak;
55ba6a6abbSYafang Shao bool bpf_cpumask_intersects(const struct cpumask *src1, const struct cpumask *src2) __ksym __weak;
56ba6a6abbSYafang Shao bool bpf_cpumask_subset(const struct cpumask *src1, const struct cpumask *src2) __ksym __weak;
57ba6a6abbSYafang Shao bool bpf_cpumask_empty(const struct cpumask *cpumask) __ksym __weak;
58ba6a6abbSYafang Shao bool bpf_cpumask_full(const struct cpumask *cpumask) __ksym __weak;
59ba6a6abbSYafang Shao void bpf_cpumask_copy(struct bpf_cpumask *dst, const struct cpumask *src) __ksym __weak;
60ba6a6abbSYafang Shao u32 bpf_cpumask_any_distribute(const struct cpumask *src) __ksym __weak;
61ba6a6abbSYafang Shao u32 bpf_cpumask_any_and_distribute(const struct cpumask *src1,
62ba6a6abbSYafang Shao 				   const struct cpumask *src2) __ksym __weak;
63ba6a6abbSYafang Shao u32 bpf_cpumask_weight(const struct cpumask *cpumask) __ksym __weak;
647b6abcfaSDavid Vernet 
65ba6a6abbSYafang Shao void bpf_rcu_read_lock(void) __ksym __weak;
66ba6a6abbSYafang Shao void bpf_rcu_read_unlock(void) __ksym __weak;
67a5a197dfSDavid Vernet 
cast(struct bpf_cpumask * cpumask)687b6abcfaSDavid Vernet static inline const struct cpumask *cast(struct bpf_cpumask *cpumask)
697b6abcfaSDavid Vernet {
707b6abcfaSDavid Vernet 	return (const struct cpumask *)cpumask;
717b6abcfaSDavid Vernet }
727b6abcfaSDavid Vernet 
create_cpumask(void)737b6abcfaSDavid Vernet static inline struct bpf_cpumask *create_cpumask(void)
747b6abcfaSDavid Vernet {
757b6abcfaSDavid Vernet 	struct bpf_cpumask *cpumask;
767b6abcfaSDavid Vernet 
777b6abcfaSDavid Vernet 	cpumask = bpf_cpumask_create();
787b6abcfaSDavid Vernet 	if (!cpumask) {
797b6abcfaSDavid Vernet 		err = 1;
807b6abcfaSDavid Vernet 		return NULL;
817b6abcfaSDavid Vernet 	}
827b6abcfaSDavid Vernet 
837b6abcfaSDavid Vernet 	if (!bpf_cpumask_empty(cast(cpumask))) {
847b6abcfaSDavid Vernet 		err = 2;
857b6abcfaSDavid Vernet 		bpf_cpumask_release(cpumask);
867b6abcfaSDavid Vernet 		return NULL;
877b6abcfaSDavid Vernet 	}
887b6abcfaSDavid Vernet 
897b6abcfaSDavid Vernet 	return cpumask;
907b6abcfaSDavid Vernet }
917b6abcfaSDavid Vernet 
cpumask_map_value_lookup(void)927b6abcfaSDavid Vernet static inline struct __cpumask_map_value *cpumask_map_value_lookup(void)
937b6abcfaSDavid Vernet {
947b6abcfaSDavid Vernet 	u32 key = 0;
957b6abcfaSDavid Vernet 
967b6abcfaSDavid Vernet 	return bpf_map_lookup_elem(&__cpumask_map, &key);
977b6abcfaSDavid Vernet }
987b6abcfaSDavid Vernet 
cpumask_map_insert(struct bpf_cpumask * mask)997b6abcfaSDavid Vernet static inline int cpumask_map_insert(struct bpf_cpumask *mask)
1007b6abcfaSDavid Vernet {
1017b6abcfaSDavid Vernet 	struct __cpumask_map_value local, *v;
1027b6abcfaSDavid Vernet 	long status;
1037b6abcfaSDavid Vernet 	struct bpf_cpumask *old;
1047b6abcfaSDavid Vernet 	u32 key = 0;
1057b6abcfaSDavid Vernet 
1067b6abcfaSDavid Vernet 	local.cpumask = NULL;
1077b6abcfaSDavid Vernet 	status = bpf_map_update_elem(&__cpumask_map, &key, &local, 0);
1087b6abcfaSDavid Vernet 	if (status) {
1097b6abcfaSDavid Vernet 		bpf_cpumask_release(mask);
1107b6abcfaSDavid Vernet 		return status;
1117b6abcfaSDavid Vernet 	}
1127b6abcfaSDavid Vernet 
1137b6abcfaSDavid Vernet 	v = bpf_map_lookup_elem(&__cpumask_map, &key);
1147b6abcfaSDavid Vernet 	if (!v) {
1157b6abcfaSDavid Vernet 		bpf_cpumask_release(mask);
1167b6abcfaSDavid Vernet 		return -ENOENT;
1177b6abcfaSDavid Vernet 	}
1187b6abcfaSDavid Vernet 
1197b6abcfaSDavid Vernet 	old = bpf_kptr_xchg(&v->cpumask, mask);
1207b6abcfaSDavid Vernet 	if (old) {
1217b6abcfaSDavid Vernet 		bpf_cpumask_release(old);
1227b6abcfaSDavid Vernet 		return -EEXIST;
1237b6abcfaSDavid Vernet 	}
1247b6abcfaSDavid Vernet 
1257b6abcfaSDavid Vernet 	return 0;
1267b6abcfaSDavid Vernet }
1277b6abcfaSDavid Vernet 
1287b6abcfaSDavid Vernet #endif /* _CPUMASK_COMMON_H */
129