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 
107b6abcfaSDavid Vernet int err;
117b6abcfaSDavid Vernet 
12a5a197dfSDavid Vernet #define private(name) SEC(".bss." #name) __hidden __attribute__((aligned(8)))
13a5a197dfSDavid Vernet private(MASK) static struct bpf_cpumask __kptr * global_mask;
14a5a197dfSDavid Vernet 
157b6abcfaSDavid Vernet struct __cpumask_map_value {
1603b77e17SAlexei Starovoitov 	struct bpf_cpumask __kptr * cpumask;
177b6abcfaSDavid Vernet };
187b6abcfaSDavid Vernet 
197b6abcfaSDavid Vernet struct array_map {
207b6abcfaSDavid Vernet 	__uint(type, BPF_MAP_TYPE_ARRAY);
217b6abcfaSDavid Vernet 	__type(key, int);
227b6abcfaSDavid Vernet 	__type(value, struct __cpumask_map_value);
237b6abcfaSDavid Vernet 	__uint(max_entries, 1);
247b6abcfaSDavid Vernet } __cpumask_map SEC(".maps");
257b6abcfaSDavid Vernet 
267b6abcfaSDavid Vernet struct bpf_cpumask *bpf_cpumask_create(void) __ksym;
277b6abcfaSDavid Vernet void bpf_cpumask_release(struct bpf_cpumask *cpumask) __ksym;
287b6abcfaSDavid Vernet struct bpf_cpumask *bpf_cpumask_acquire(struct bpf_cpumask *cpumask) __ksym;
297b6abcfaSDavid Vernet u32 bpf_cpumask_first(const struct cpumask *cpumask) __ksym;
307b6abcfaSDavid Vernet u32 bpf_cpumask_first_zero(const struct cpumask *cpumask) __ksym;
3158476d8aSDavid Vernet u32 bpf_cpumask_first_and(const struct cpumask *src1,
3258476d8aSDavid Vernet 			  const struct cpumask *src2) __ksym;
337b6abcfaSDavid Vernet void bpf_cpumask_set_cpu(u32 cpu, struct bpf_cpumask *cpumask) __ksym;
347b6abcfaSDavid Vernet void bpf_cpumask_clear_cpu(u32 cpu, struct bpf_cpumask *cpumask) __ksym;
357b6abcfaSDavid Vernet bool bpf_cpumask_test_cpu(u32 cpu, const struct cpumask *cpumask) __ksym;
367b6abcfaSDavid Vernet bool bpf_cpumask_test_and_set_cpu(u32 cpu, struct bpf_cpumask *cpumask) __ksym;
377b6abcfaSDavid Vernet bool bpf_cpumask_test_and_clear_cpu(u32 cpu, struct bpf_cpumask *cpumask) __ksym;
387b6abcfaSDavid Vernet void bpf_cpumask_setall(struct bpf_cpumask *cpumask) __ksym;
397b6abcfaSDavid Vernet void bpf_cpumask_clear(struct bpf_cpumask *cpumask) __ksym;
407b6abcfaSDavid Vernet bool bpf_cpumask_and(struct bpf_cpumask *cpumask,
417b6abcfaSDavid Vernet 		     const struct cpumask *src1,
427b6abcfaSDavid Vernet 		     const struct cpumask *src2) __ksym;
437b6abcfaSDavid Vernet void bpf_cpumask_or(struct bpf_cpumask *cpumask,
447b6abcfaSDavid Vernet 		    const struct cpumask *src1,
457b6abcfaSDavid Vernet 		    const struct cpumask *src2) __ksym;
467b6abcfaSDavid Vernet void bpf_cpumask_xor(struct bpf_cpumask *cpumask,
477b6abcfaSDavid Vernet 		     const struct cpumask *src1,
487b6abcfaSDavid Vernet 		     const struct cpumask *src2) __ksym;
497b6abcfaSDavid Vernet bool bpf_cpumask_equal(const struct cpumask *src1, const struct cpumask *src2) __ksym;
507b6abcfaSDavid Vernet bool bpf_cpumask_intersects(const struct cpumask *src1, const struct cpumask *src2) __ksym;
517b6abcfaSDavid Vernet bool bpf_cpumask_subset(const struct cpumask *src1, const struct cpumask *src2) __ksym;
527b6abcfaSDavid Vernet bool bpf_cpumask_empty(const struct cpumask *cpumask) __ksym;
537b6abcfaSDavid Vernet bool bpf_cpumask_full(const struct cpumask *cpumask) __ksym;
547b6abcfaSDavid Vernet void bpf_cpumask_copy(struct bpf_cpumask *dst, const struct cpumask *src) __ksym;
55*5a73efc7SDavid Vernet u32 bpf_cpumask_any_distribute(const struct cpumask *src) __ksym;
56*5a73efc7SDavid Vernet u32 bpf_cpumask_any_and_distribute(const struct cpumask *src1, const struct cpumask *src2) __ksym;
577b6abcfaSDavid Vernet 
58a5a197dfSDavid Vernet void bpf_rcu_read_lock(void) __ksym;
59a5a197dfSDavid Vernet void bpf_rcu_read_unlock(void) __ksym;
60a5a197dfSDavid Vernet 
cast(struct bpf_cpumask * cpumask)617b6abcfaSDavid Vernet static inline const struct cpumask *cast(struct bpf_cpumask *cpumask)
627b6abcfaSDavid Vernet {
637b6abcfaSDavid Vernet 	return (const struct cpumask *)cpumask;
647b6abcfaSDavid Vernet }
657b6abcfaSDavid Vernet 
create_cpumask(void)667b6abcfaSDavid Vernet static inline struct bpf_cpumask *create_cpumask(void)
677b6abcfaSDavid Vernet {
687b6abcfaSDavid Vernet 	struct bpf_cpumask *cpumask;
697b6abcfaSDavid Vernet 
707b6abcfaSDavid Vernet 	cpumask = bpf_cpumask_create();
717b6abcfaSDavid Vernet 	if (!cpumask) {
727b6abcfaSDavid Vernet 		err = 1;
737b6abcfaSDavid Vernet 		return NULL;
747b6abcfaSDavid Vernet 	}
757b6abcfaSDavid Vernet 
767b6abcfaSDavid Vernet 	if (!bpf_cpumask_empty(cast(cpumask))) {
777b6abcfaSDavid Vernet 		err = 2;
787b6abcfaSDavid Vernet 		bpf_cpumask_release(cpumask);
797b6abcfaSDavid Vernet 		return NULL;
807b6abcfaSDavid Vernet 	}
817b6abcfaSDavid Vernet 
827b6abcfaSDavid Vernet 	return cpumask;
837b6abcfaSDavid Vernet }
847b6abcfaSDavid Vernet 
cpumask_map_value_lookup(void)857b6abcfaSDavid Vernet static inline struct __cpumask_map_value *cpumask_map_value_lookup(void)
867b6abcfaSDavid Vernet {
877b6abcfaSDavid Vernet 	u32 key = 0;
887b6abcfaSDavid Vernet 
897b6abcfaSDavid Vernet 	return bpf_map_lookup_elem(&__cpumask_map, &key);
907b6abcfaSDavid Vernet }
917b6abcfaSDavid Vernet 
cpumask_map_insert(struct bpf_cpumask * mask)927b6abcfaSDavid Vernet static inline int cpumask_map_insert(struct bpf_cpumask *mask)
937b6abcfaSDavid Vernet {
947b6abcfaSDavid Vernet 	struct __cpumask_map_value local, *v;
957b6abcfaSDavid Vernet 	long status;
967b6abcfaSDavid Vernet 	struct bpf_cpumask *old;
977b6abcfaSDavid Vernet 	u32 key = 0;
987b6abcfaSDavid Vernet 
997b6abcfaSDavid Vernet 	local.cpumask = NULL;
1007b6abcfaSDavid Vernet 	status = bpf_map_update_elem(&__cpumask_map, &key, &local, 0);
1017b6abcfaSDavid Vernet 	if (status) {
1027b6abcfaSDavid Vernet 		bpf_cpumask_release(mask);
1037b6abcfaSDavid Vernet 		return status;
1047b6abcfaSDavid Vernet 	}
1057b6abcfaSDavid Vernet 
1067b6abcfaSDavid Vernet 	v = bpf_map_lookup_elem(&__cpumask_map, &key);
1077b6abcfaSDavid Vernet 	if (!v) {
1087b6abcfaSDavid Vernet 		bpf_cpumask_release(mask);
1097b6abcfaSDavid Vernet 		return -ENOENT;
1107b6abcfaSDavid Vernet 	}
1117b6abcfaSDavid Vernet 
1127b6abcfaSDavid Vernet 	old = bpf_kptr_xchg(&v->cpumask, mask);
1137b6abcfaSDavid Vernet 	if (old) {
1147b6abcfaSDavid Vernet 		bpf_cpumask_release(old);
1157b6abcfaSDavid Vernet 		return -EEXIST;
1167b6abcfaSDavid Vernet 	}
1177b6abcfaSDavid Vernet 
1187b6abcfaSDavid Vernet 	return 0;
1197b6abcfaSDavid Vernet }
1207b6abcfaSDavid Vernet 
1217b6abcfaSDavid Vernet #endif /* _CPUMASK_COMMON_H */
122