1516f4d33SDavid Vernet // SPDX-License-Identifier: GPL-2.0-only
2516f4d33SDavid Vernet /* Copyright (c) 2023 Meta, Inc */
3516f4d33SDavid Vernet #include <linux/bpf.h>
4516f4d33SDavid Vernet #include <linux/bpf_mem_alloc.h>
5516f4d33SDavid Vernet #include <linux/btf.h>
6516f4d33SDavid Vernet #include <linux/btf_ids.h>
7516f4d33SDavid Vernet #include <linux/cpumask.h>
8516f4d33SDavid Vernet
9516f4d33SDavid Vernet /**
10516f4d33SDavid Vernet * struct bpf_cpumask - refcounted BPF cpumask wrapper structure
11516f4d33SDavid Vernet * @cpumask: The actual cpumask embedded in the struct.
12516f4d33SDavid Vernet * @usage: Object reference counter. When the refcount goes to 0, the
13516f4d33SDavid Vernet * memory is released back to the BPF allocator, which provides
14516f4d33SDavid Vernet * RCU safety.
15516f4d33SDavid Vernet *
16516f4d33SDavid Vernet * Note that we explicitly embed a cpumask_t rather than a cpumask_var_t. This
17516f4d33SDavid Vernet * is done to avoid confusing the verifier due to the typedef of cpumask_var_t
18516f4d33SDavid Vernet * changing depending on whether CONFIG_CPUMASK_OFFSTACK is defined or not. See
19516f4d33SDavid Vernet * the details in <linux/cpumask.h>. The consequence is that this structure is
20516f4d33SDavid Vernet * likely a bit larger than it needs to be when CONFIG_CPUMASK_OFFSTACK is
21516f4d33SDavid Vernet * defined due to embedding the whole NR_CPUS-size bitmap, but the extra memory
22516f4d33SDavid Vernet * overhead is minimal. For the more typical case of CONFIG_CPUMASK_OFFSTACK
23516f4d33SDavid Vernet * not being defined, the structure is the same size regardless.
24516f4d33SDavid Vernet */
25516f4d33SDavid Vernet struct bpf_cpumask {
26516f4d33SDavid Vernet cpumask_t cpumask;
27516f4d33SDavid Vernet refcount_t usage;
28516f4d33SDavid Vernet };
29516f4d33SDavid Vernet
30516f4d33SDavid Vernet static struct bpf_mem_alloc bpf_cpumask_ma;
31516f4d33SDavid Vernet
cpu_valid(u32 cpu)32516f4d33SDavid Vernet static bool cpu_valid(u32 cpu)
33516f4d33SDavid Vernet {
34516f4d33SDavid Vernet return cpu < nr_cpu_ids;
35516f4d33SDavid Vernet }
36516f4d33SDavid Vernet
37516f4d33SDavid Vernet __diag_push();
38516f4d33SDavid Vernet __diag_ignore_all("-Wmissing-prototypes",
39516f4d33SDavid Vernet "Global kfuncs as their definitions will be in BTF");
40516f4d33SDavid Vernet
41bdbda395SDavid Vernet /**
42bdbda395SDavid Vernet * bpf_cpumask_create() - Create a mutable BPF cpumask.
43bdbda395SDavid Vernet *
44bdbda395SDavid Vernet * Allocates a cpumask that can be queried, mutated, acquired, and released by
45bdbda395SDavid Vernet * a BPF program. The cpumask returned by this function must either be embedded
46bdbda395SDavid Vernet * in a map as a kptr, or freed with bpf_cpumask_release().
47bdbda395SDavid Vernet *
48bdbda395SDavid Vernet * bpf_cpumask_create() allocates memory using the BPF memory allocator, and
49bdbda395SDavid Vernet * will not block. It may return NULL if no memory is available.
50bdbda395SDavid Vernet */
bpf_cpumask_create(void)51400031e0SDavid Vernet __bpf_kfunc struct bpf_cpumask *bpf_cpumask_create(void)
52516f4d33SDavid Vernet {
53516f4d33SDavid Vernet struct bpf_cpumask *cpumask;
54516f4d33SDavid Vernet
55cb4a21eaSDavid Vernet /* cpumask must be the first element so struct bpf_cpumask be cast to struct cpumask. */
56cb4a21eaSDavid Vernet BUILD_BUG_ON(offsetof(struct bpf_cpumask, cpumask) != 0);
57cb4a21eaSDavid Vernet
585d5de3a4SHou Tao cpumask = bpf_mem_cache_alloc(&bpf_cpumask_ma);
59516f4d33SDavid Vernet if (!cpumask)
60516f4d33SDavid Vernet return NULL;
61516f4d33SDavid Vernet
62516f4d33SDavid Vernet memset(cpumask, 0, sizeof(*cpumask));
63516f4d33SDavid Vernet refcount_set(&cpumask->usage, 1);
64516f4d33SDavid Vernet
65516f4d33SDavid Vernet return cpumask;
66516f4d33SDavid Vernet }
67516f4d33SDavid Vernet
68bdbda395SDavid Vernet /**
69bdbda395SDavid Vernet * bpf_cpumask_acquire() - Acquire a reference to a BPF cpumask.
70bdbda395SDavid Vernet * @cpumask: The BPF cpumask being acquired. The cpumask must be a trusted
71bdbda395SDavid Vernet * pointer.
72bdbda395SDavid Vernet *
73bdbda395SDavid Vernet * Acquires a reference to a BPF cpumask. The cpumask returned by this function
74bdbda395SDavid Vernet * must either be embedded in a map as a kptr, or freed with
75bdbda395SDavid Vernet * bpf_cpumask_release().
76bdbda395SDavid Vernet */
bpf_cpumask_acquire(struct bpf_cpumask * cpumask)77400031e0SDavid Vernet __bpf_kfunc struct bpf_cpumask *bpf_cpumask_acquire(struct bpf_cpumask *cpumask)
78516f4d33SDavid Vernet {
79516f4d33SDavid Vernet refcount_inc(&cpumask->usage);
80516f4d33SDavid Vernet return cpumask;
81516f4d33SDavid Vernet }
82516f4d33SDavid Vernet
83bdbda395SDavid Vernet /**
84bdbda395SDavid Vernet * bpf_cpumask_release() - Release a previously acquired BPF cpumask.
85bdbda395SDavid Vernet * @cpumask: The cpumask being released.
86bdbda395SDavid Vernet *
87bdbda395SDavid Vernet * Releases a previously acquired reference to a BPF cpumask. When the final
88bdbda395SDavid Vernet * reference of the BPF cpumask has been released, it is subsequently freed in
89bdbda395SDavid Vernet * an RCU callback in the BPF memory allocator.
90bdbda395SDavid Vernet */
bpf_cpumask_release(struct bpf_cpumask * cpumask)91400031e0SDavid Vernet __bpf_kfunc void bpf_cpumask_release(struct bpf_cpumask *cpumask)
92516f4d33SDavid Vernet {
93*8e07bb9eSAlexei Starovoitov if (!refcount_dec_and_test(&cpumask->usage))
94*8e07bb9eSAlexei Starovoitov return;
95*8e07bb9eSAlexei Starovoitov
96*8e07bb9eSAlexei Starovoitov migrate_disable();
97*8e07bb9eSAlexei Starovoitov bpf_mem_cache_free_rcu(&bpf_cpumask_ma, cpumask);
98*8e07bb9eSAlexei Starovoitov migrate_enable();
99516f4d33SDavid Vernet }
100516f4d33SDavid Vernet
101bdbda395SDavid Vernet /**
102bdbda395SDavid Vernet * bpf_cpumask_first() - Get the index of the first nonzero bit in the cpumask.
103bdbda395SDavid Vernet * @cpumask: The cpumask being queried.
104bdbda395SDavid Vernet *
105bdbda395SDavid Vernet * Find the index of the first nonzero bit of the cpumask. A struct bpf_cpumask
106bdbda395SDavid Vernet * pointer may be safely passed to this function.
107bdbda395SDavid Vernet */
bpf_cpumask_first(const struct cpumask * cpumask)108400031e0SDavid Vernet __bpf_kfunc u32 bpf_cpumask_first(const struct cpumask *cpumask)
109516f4d33SDavid Vernet {
110516f4d33SDavid Vernet return cpumask_first(cpumask);
111516f4d33SDavid Vernet }
112516f4d33SDavid Vernet
113bdbda395SDavid Vernet /**
114bdbda395SDavid Vernet * bpf_cpumask_first_zero() - Get the index of the first unset bit in the
115bdbda395SDavid Vernet * cpumask.
116bdbda395SDavid Vernet * @cpumask: The cpumask being queried.
117bdbda395SDavid Vernet *
118bdbda395SDavid Vernet * Find the index of the first unset bit of the cpumask. A struct bpf_cpumask
119bdbda395SDavid Vernet * pointer may be safely passed to this function.
120bdbda395SDavid Vernet */
bpf_cpumask_first_zero(const struct cpumask * cpumask)121400031e0SDavid Vernet __bpf_kfunc u32 bpf_cpumask_first_zero(const struct cpumask *cpumask)
122516f4d33SDavid Vernet {
123516f4d33SDavid Vernet return cpumask_first_zero(cpumask);
124516f4d33SDavid Vernet }
125516f4d33SDavid Vernet
126bdbda395SDavid Vernet /**
1275ba3a7a8SDavid Vernet * bpf_cpumask_first_and() - Return the index of the first nonzero bit from the
1285ba3a7a8SDavid Vernet * AND of two cpumasks.
1295ba3a7a8SDavid Vernet * @src1: The first cpumask.
1305ba3a7a8SDavid Vernet * @src2: The second cpumask.
1315ba3a7a8SDavid Vernet *
1325ba3a7a8SDavid Vernet * Find the index of the first nonzero bit of the AND of two cpumasks.
1335ba3a7a8SDavid Vernet * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
1345ba3a7a8SDavid Vernet */
bpf_cpumask_first_and(const struct cpumask * src1,const struct cpumask * src2)1355ba3a7a8SDavid Vernet __bpf_kfunc u32 bpf_cpumask_first_and(const struct cpumask *src1,
1365ba3a7a8SDavid Vernet const struct cpumask *src2)
1375ba3a7a8SDavid Vernet {
1385ba3a7a8SDavid Vernet return cpumask_first_and(src1, src2);
1395ba3a7a8SDavid Vernet }
1405ba3a7a8SDavid Vernet
1415ba3a7a8SDavid Vernet /**
142bdbda395SDavid Vernet * bpf_cpumask_set_cpu() - Set a bit for a CPU in a BPF cpumask.
143bdbda395SDavid Vernet * @cpu: The CPU to be set in the cpumask.
144bdbda395SDavid Vernet * @cpumask: The BPF cpumask in which a bit is being set.
145bdbda395SDavid Vernet */
bpf_cpumask_set_cpu(u32 cpu,struct bpf_cpumask * cpumask)146400031e0SDavid Vernet __bpf_kfunc void bpf_cpumask_set_cpu(u32 cpu, struct bpf_cpumask *cpumask)
147516f4d33SDavid Vernet {
148516f4d33SDavid Vernet if (!cpu_valid(cpu))
149516f4d33SDavid Vernet return;
150516f4d33SDavid Vernet
151516f4d33SDavid Vernet cpumask_set_cpu(cpu, (struct cpumask *)cpumask);
152516f4d33SDavid Vernet }
153516f4d33SDavid Vernet
154bdbda395SDavid Vernet /**
155bdbda395SDavid Vernet * bpf_cpumask_clear_cpu() - Clear a bit for a CPU in a BPF cpumask.
156bdbda395SDavid Vernet * @cpu: The CPU to be cleared from the cpumask.
157bdbda395SDavid Vernet * @cpumask: The BPF cpumask in which a bit is being cleared.
158bdbda395SDavid Vernet */
bpf_cpumask_clear_cpu(u32 cpu,struct bpf_cpumask * cpumask)159400031e0SDavid Vernet __bpf_kfunc void bpf_cpumask_clear_cpu(u32 cpu, struct bpf_cpumask *cpumask)
160516f4d33SDavid Vernet {
161516f4d33SDavid Vernet if (!cpu_valid(cpu))
162516f4d33SDavid Vernet return;
163516f4d33SDavid Vernet
164516f4d33SDavid Vernet cpumask_clear_cpu(cpu, (struct cpumask *)cpumask);
165516f4d33SDavid Vernet }
166516f4d33SDavid Vernet
167bdbda395SDavid Vernet /**
168bdbda395SDavid Vernet * bpf_cpumask_test_cpu() - Test whether a CPU is set in a cpumask.
169bdbda395SDavid Vernet * @cpu: The CPU being queried for.
170bdbda395SDavid Vernet * @cpumask: The cpumask being queried for containing a CPU.
171bdbda395SDavid Vernet *
172bdbda395SDavid Vernet * Return:
173bdbda395SDavid Vernet * * true - @cpu is set in the cpumask
174bdbda395SDavid Vernet * * false - @cpu was not set in the cpumask, or @cpu is an invalid cpu.
175bdbda395SDavid Vernet */
bpf_cpumask_test_cpu(u32 cpu,const struct cpumask * cpumask)176400031e0SDavid Vernet __bpf_kfunc bool bpf_cpumask_test_cpu(u32 cpu, const struct cpumask *cpumask)
177516f4d33SDavid Vernet {
178516f4d33SDavid Vernet if (!cpu_valid(cpu))
179516f4d33SDavid Vernet return false;
180516f4d33SDavid Vernet
181516f4d33SDavid Vernet return cpumask_test_cpu(cpu, (struct cpumask *)cpumask);
182516f4d33SDavid Vernet }
183516f4d33SDavid Vernet
184bdbda395SDavid Vernet /**
185bdbda395SDavid Vernet * bpf_cpumask_test_and_set_cpu() - Atomically test and set a CPU in a BPF cpumask.
186bdbda395SDavid Vernet * @cpu: The CPU being set and queried for.
187bdbda395SDavid Vernet * @cpumask: The BPF cpumask being set and queried for containing a CPU.
188bdbda395SDavid Vernet *
189bdbda395SDavid Vernet * Return:
190bdbda395SDavid Vernet * * true - @cpu is set in the cpumask
191bdbda395SDavid Vernet * * false - @cpu was not set in the cpumask, or @cpu is invalid.
192bdbda395SDavid Vernet */
bpf_cpumask_test_and_set_cpu(u32 cpu,struct bpf_cpumask * cpumask)193400031e0SDavid Vernet __bpf_kfunc bool bpf_cpumask_test_and_set_cpu(u32 cpu, struct bpf_cpumask *cpumask)
194516f4d33SDavid Vernet {
195516f4d33SDavid Vernet if (!cpu_valid(cpu))
196516f4d33SDavid Vernet return false;
197516f4d33SDavid Vernet
198516f4d33SDavid Vernet return cpumask_test_and_set_cpu(cpu, (struct cpumask *)cpumask);
199516f4d33SDavid Vernet }
200516f4d33SDavid Vernet
201bdbda395SDavid Vernet /**
202bdbda395SDavid Vernet * bpf_cpumask_test_and_clear_cpu() - Atomically test and clear a CPU in a BPF
203bdbda395SDavid Vernet * cpumask.
204bdbda395SDavid Vernet * @cpu: The CPU being cleared and queried for.
205bdbda395SDavid Vernet * @cpumask: The BPF cpumask being cleared and queried for containing a CPU.
206bdbda395SDavid Vernet *
207bdbda395SDavid Vernet * Return:
208bdbda395SDavid Vernet * * true - @cpu is set in the cpumask
209bdbda395SDavid Vernet * * false - @cpu was not set in the cpumask, or @cpu is invalid.
210bdbda395SDavid Vernet */
bpf_cpumask_test_and_clear_cpu(u32 cpu,struct bpf_cpumask * cpumask)211400031e0SDavid Vernet __bpf_kfunc bool bpf_cpumask_test_and_clear_cpu(u32 cpu, struct bpf_cpumask *cpumask)
212516f4d33SDavid Vernet {
213516f4d33SDavid Vernet if (!cpu_valid(cpu))
214516f4d33SDavid Vernet return false;
215516f4d33SDavid Vernet
216516f4d33SDavid Vernet return cpumask_test_and_clear_cpu(cpu, (struct cpumask *)cpumask);
217516f4d33SDavid Vernet }
218516f4d33SDavid Vernet
219bdbda395SDavid Vernet /**
220bdbda395SDavid Vernet * bpf_cpumask_setall() - Set all of the bits in a BPF cpumask.
221bdbda395SDavid Vernet * @cpumask: The BPF cpumask having all of its bits set.
222bdbda395SDavid Vernet */
bpf_cpumask_setall(struct bpf_cpumask * cpumask)223400031e0SDavid Vernet __bpf_kfunc void bpf_cpumask_setall(struct bpf_cpumask *cpumask)
224516f4d33SDavid Vernet {
225516f4d33SDavid Vernet cpumask_setall((struct cpumask *)cpumask);
226516f4d33SDavid Vernet }
227516f4d33SDavid Vernet
228bdbda395SDavid Vernet /**
229bdbda395SDavid Vernet * bpf_cpumask_clear() - Clear all of the bits in a BPF cpumask.
230bdbda395SDavid Vernet * @cpumask: The BPF cpumask being cleared.
231bdbda395SDavid Vernet */
bpf_cpumask_clear(struct bpf_cpumask * cpumask)232400031e0SDavid Vernet __bpf_kfunc void bpf_cpumask_clear(struct bpf_cpumask *cpumask)
233516f4d33SDavid Vernet {
234516f4d33SDavid Vernet cpumask_clear((struct cpumask *)cpumask);
235516f4d33SDavid Vernet }
236516f4d33SDavid Vernet
237bdbda395SDavid Vernet /**
238bdbda395SDavid Vernet * bpf_cpumask_and() - AND two cpumasks and store the result.
239bdbda395SDavid Vernet * @dst: The BPF cpumask where the result is being stored.
240bdbda395SDavid Vernet * @src1: The first input.
241bdbda395SDavid Vernet * @src2: The second input.
242bdbda395SDavid Vernet *
243bdbda395SDavid Vernet * Return:
244bdbda395SDavid Vernet * * true - @dst has at least one bit set following the operation
245bdbda395SDavid Vernet * * false - @dst is empty following the operation
246bdbda395SDavid Vernet *
247bdbda395SDavid Vernet * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
248bdbda395SDavid Vernet */
bpf_cpumask_and(struct bpf_cpumask * dst,const struct cpumask * src1,const struct cpumask * src2)249400031e0SDavid Vernet __bpf_kfunc bool bpf_cpumask_and(struct bpf_cpumask *dst,
250516f4d33SDavid Vernet const struct cpumask *src1,
251516f4d33SDavid Vernet const struct cpumask *src2)
252516f4d33SDavid Vernet {
253516f4d33SDavid Vernet return cpumask_and((struct cpumask *)dst, src1, src2);
254516f4d33SDavid Vernet }
255516f4d33SDavid Vernet
256bdbda395SDavid Vernet /**
257bdbda395SDavid Vernet * bpf_cpumask_or() - OR two cpumasks and store the result.
258bdbda395SDavid Vernet * @dst: The BPF cpumask where the result is being stored.
259bdbda395SDavid Vernet * @src1: The first input.
260bdbda395SDavid Vernet * @src2: The second input.
261bdbda395SDavid Vernet *
262bdbda395SDavid Vernet * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
263bdbda395SDavid Vernet */
bpf_cpumask_or(struct bpf_cpumask * dst,const struct cpumask * src1,const struct cpumask * src2)264400031e0SDavid Vernet __bpf_kfunc void bpf_cpumask_or(struct bpf_cpumask *dst,
265516f4d33SDavid Vernet const struct cpumask *src1,
266516f4d33SDavid Vernet const struct cpumask *src2)
267516f4d33SDavid Vernet {
268516f4d33SDavid Vernet cpumask_or((struct cpumask *)dst, src1, src2);
269516f4d33SDavid Vernet }
270516f4d33SDavid Vernet
271bdbda395SDavid Vernet /**
272bdbda395SDavid Vernet * bpf_cpumask_xor() - XOR two cpumasks and store the result.
273bdbda395SDavid Vernet * @dst: The BPF cpumask where the result is being stored.
274bdbda395SDavid Vernet * @src1: The first input.
275bdbda395SDavid Vernet * @src2: The second input.
276bdbda395SDavid Vernet *
277bdbda395SDavid Vernet * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
278bdbda395SDavid Vernet */
bpf_cpumask_xor(struct bpf_cpumask * dst,const struct cpumask * src1,const struct cpumask * src2)279400031e0SDavid Vernet __bpf_kfunc void bpf_cpumask_xor(struct bpf_cpumask *dst,
280516f4d33SDavid Vernet const struct cpumask *src1,
281516f4d33SDavid Vernet const struct cpumask *src2)
282516f4d33SDavid Vernet {
283516f4d33SDavid Vernet cpumask_xor((struct cpumask *)dst, src1, src2);
284516f4d33SDavid Vernet }
285516f4d33SDavid Vernet
286bdbda395SDavid Vernet /**
287bdbda395SDavid Vernet * bpf_cpumask_equal() - Check two cpumasks for equality.
288bdbda395SDavid Vernet * @src1: The first input.
289bdbda395SDavid Vernet * @src2: The second input.
290bdbda395SDavid Vernet *
291bdbda395SDavid Vernet * Return:
292bdbda395SDavid Vernet * * true - @src1 and @src2 have the same bits set.
293bdbda395SDavid Vernet * * false - @src1 and @src2 differ in at least one bit.
294bdbda395SDavid Vernet *
295bdbda395SDavid Vernet * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
296bdbda395SDavid Vernet */
bpf_cpumask_equal(const struct cpumask * src1,const struct cpumask * src2)297400031e0SDavid Vernet __bpf_kfunc bool bpf_cpumask_equal(const struct cpumask *src1, const struct cpumask *src2)
298516f4d33SDavid Vernet {
299516f4d33SDavid Vernet return cpumask_equal(src1, src2);
300516f4d33SDavid Vernet }
301516f4d33SDavid Vernet
302bdbda395SDavid Vernet /**
303bdbda395SDavid Vernet * bpf_cpumask_intersects() - Check two cpumasks for overlap.
304bdbda395SDavid Vernet * @src1: The first input.
305bdbda395SDavid Vernet * @src2: The second input.
306bdbda395SDavid Vernet *
307bdbda395SDavid Vernet * Return:
308bdbda395SDavid Vernet * * true - @src1 and @src2 have at least one of the same bits set.
309bdbda395SDavid Vernet * * false - @src1 and @src2 don't have any of the same bits set.
310bdbda395SDavid Vernet *
311bdbda395SDavid Vernet * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
312bdbda395SDavid Vernet */
bpf_cpumask_intersects(const struct cpumask * src1,const struct cpumask * src2)313400031e0SDavid Vernet __bpf_kfunc bool bpf_cpumask_intersects(const struct cpumask *src1, const struct cpumask *src2)
314516f4d33SDavid Vernet {
315516f4d33SDavid Vernet return cpumask_intersects(src1, src2);
316516f4d33SDavid Vernet }
317516f4d33SDavid Vernet
318bdbda395SDavid Vernet /**
319bdbda395SDavid Vernet * bpf_cpumask_subset() - Check if a cpumask is a subset of another.
320bdbda395SDavid Vernet * @src1: The first cpumask being checked as a subset.
321bdbda395SDavid Vernet * @src2: The second cpumask being checked as a superset.
322bdbda395SDavid Vernet *
323bdbda395SDavid Vernet * Return:
324bdbda395SDavid Vernet * * true - All of the bits of @src1 are set in @src2.
325bdbda395SDavid Vernet * * false - At least one bit in @src1 is not set in @src2.
326bdbda395SDavid Vernet *
327bdbda395SDavid Vernet * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
328bdbda395SDavid Vernet */
bpf_cpumask_subset(const struct cpumask * src1,const struct cpumask * src2)329400031e0SDavid Vernet __bpf_kfunc bool bpf_cpumask_subset(const struct cpumask *src1, const struct cpumask *src2)
330516f4d33SDavid Vernet {
331516f4d33SDavid Vernet return cpumask_subset(src1, src2);
332516f4d33SDavid Vernet }
333516f4d33SDavid Vernet
334bdbda395SDavid Vernet /**
335bdbda395SDavid Vernet * bpf_cpumask_empty() - Check if a cpumask is empty.
336bdbda395SDavid Vernet * @cpumask: The cpumask being checked.
337bdbda395SDavid Vernet *
338bdbda395SDavid Vernet * Return:
339bdbda395SDavid Vernet * * true - None of the bits in @cpumask are set.
340bdbda395SDavid Vernet * * false - At least one bit in @cpumask is set.
341bdbda395SDavid Vernet *
342bdbda395SDavid Vernet * A struct bpf_cpumask pointer may be safely passed to @cpumask.
343bdbda395SDavid Vernet */
bpf_cpumask_empty(const struct cpumask * cpumask)344400031e0SDavid Vernet __bpf_kfunc bool bpf_cpumask_empty(const struct cpumask *cpumask)
345516f4d33SDavid Vernet {
346516f4d33SDavid Vernet return cpumask_empty(cpumask);
347516f4d33SDavid Vernet }
348516f4d33SDavid Vernet
349bdbda395SDavid Vernet /**
350bdbda395SDavid Vernet * bpf_cpumask_full() - Check if a cpumask has all bits set.
351bdbda395SDavid Vernet * @cpumask: The cpumask being checked.
352bdbda395SDavid Vernet *
353bdbda395SDavid Vernet * Return:
354bdbda395SDavid Vernet * * true - All of the bits in @cpumask are set.
355bdbda395SDavid Vernet * * false - At least one bit in @cpumask is cleared.
356bdbda395SDavid Vernet *
357bdbda395SDavid Vernet * A struct bpf_cpumask pointer may be safely passed to @cpumask.
358bdbda395SDavid Vernet */
bpf_cpumask_full(const struct cpumask * cpumask)359400031e0SDavid Vernet __bpf_kfunc bool bpf_cpumask_full(const struct cpumask *cpumask)
360516f4d33SDavid Vernet {
361516f4d33SDavid Vernet return cpumask_full(cpumask);
362516f4d33SDavid Vernet }
363516f4d33SDavid Vernet
364bdbda395SDavid Vernet /**
365bdbda395SDavid Vernet * bpf_cpumask_copy() - Copy the contents of a cpumask into a BPF cpumask.
366bdbda395SDavid Vernet * @dst: The BPF cpumask being copied into.
367bdbda395SDavid Vernet * @src: The cpumask being copied.
368bdbda395SDavid Vernet *
369bdbda395SDavid Vernet * A struct bpf_cpumask pointer may be safely passed to @src.
370bdbda395SDavid Vernet */
bpf_cpumask_copy(struct bpf_cpumask * dst,const struct cpumask * src)371400031e0SDavid Vernet __bpf_kfunc void bpf_cpumask_copy(struct bpf_cpumask *dst, const struct cpumask *src)
372516f4d33SDavid Vernet {
373516f4d33SDavid Vernet cpumask_copy((struct cpumask *)dst, src);
374516f4d33SDavid Vernet }
375516f4d33SDavid Vernet
376bdbda395SDavid Vernet /**
377f983be91SDavid Vernet * bpf_cpumask_any_distribute() - Return a random set CPU from a cpumask.
378bdbda395SDavid Vernet * @cpumask: The cpumask being queried.
379bdbda395SDavid Vernet *
380bdbda395SDavid Vernet * Return:
381bdbda395SDavid Vernet * * A random set bit within [0, num_cpus) if at least one bit is set.
382bdbda395SDavid Vernet * * >= num_cpus if no bit is set.
383bdbda395SDavid Vernet *
384bdbda395SDavid Vernet * A struct bpf_cpumask pointer may be safely passed to @src.
385bdbda395SDavid Vernet */
bpf_cpumask_any_distribute(const struct cpumask * cpumask)386f983be91SDavid Vernet __bpf_kfunc u32 bpf_cpumask_any_distribute(const struct cpumask *cpumask)
387516f4d33SDavid Vernet {
388f983be91SDavid Vernet return cpumask_any_distribute(cpumask);
389516f4d33SDavid Vernet }
390516f4d33SDavid Vernet
391bdbda395SDavid Vernet /**
392f983be91SDavid Vernet * bpf_cpumask_any_and_distribute() - Return a random set CPU from the AND of
393f983be91SDavid Vernet * two cpumasks.
394bdbda395SDavid Vernet * @src1: The first cpumask.
395bdbda395SDavid Vernet * @src2: The second cpumask.
396bdbda395SDavid Vernet *
397bdbda395SDavid Vernet * Return:
398f983be91SDavid Vernet * * A random set bit within [0, num_cpus) from the AND of two cpumasks, if at
399f983be91SDavid Vernet * least one bit is set.
400bdbda395SDavid Vernet * * >= num_cpus if no bit is set.
401bdbda395SDavid Vernet *
402bdbda395SDavid Vernet * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
403bdbda395SDavid Vernet */
bpf_cpumask_any_and_distribute(const struct cpumask * src1,const struct cpumask * src2)404f983be91SDavid Vernet __bpf_kfunc u32 bpf_cpumask_any_and_distribute(const struct cpumask *src1,
405f983be91SDavid Vernet const struct cpumask *src2)
406516f4d33SDavid Vernet {
407f983be91SDavid Vernet return cpumask_any_and_distribute(src1, src2);
408516f4d33SDavid Vernet }
409516f4d33SDavid Vernet
410516f4d33SDavid Vernet __diag_pop();
411516f4d33SDavid Vernet
412516f4d33SDavid Vernet BTF_SET8_START(cpumask_kfunc_btf_ids)
413516f4d33SDavid Vernet BTF_ID_FLAGS(func, bpf_cpumask_create, KF_ACQUIRE | KF_RET_NULL)
4146c831c46SDavid Vernet BTF_ID_FLAGS(func, bpf_cpumask_release, KF_RELEASE)
415516f4d33SDavid Vernet BTF_ID_FLAGS(func, bpf_cpumask_acquire, KF_ACQUIRE | KF_TRUSTED_ARGS)
4166fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_first, KF_RCU)
4176fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_first_zero, KF_RCU)
4185ba3a7a8SDavid Vernet BTF_ID_FLAGS(func, bpf_cpumask_first_and, KF_RCU)
4196fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_set_cpu, KF_RCU)
4206fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_clear_cpu, KF_RCU)
4216fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_test_cpu, KF_RCU)
4226fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_test_and_set_cpu, KF_RCU)
4236fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_test_and_clear_cpu, KF_RCU)
4246fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_setall, KF_RCU)
4256fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_clear, KF_RCU)
4266fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_and, KF_RCU)
4276fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_or, KF_RCU)
4286fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_xor, KF_RCU)
4296fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_equal, KF_RCU)
4306fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_intersects, KF_RCU)
4316fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_subset, KF_RCU)
4326fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_empty, KF_RCU)
4336fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_full, KF_RCU)
4346fcd486bSAlexei Starovoitov BTF_ID_FLAGS(func, bpf_cpumask_copy, KF_RCU)
435f983be91SDavid Vernet BTF_ID_FLAGS(func, bpf_cpumask_any_distribute, KF_RCU)
436f983be91SDavid Vernet BTF_ID_FLAGS(func, bpf_cpumask_any_and_distribute, KF_RCU)
437516f4d33SDavid Vernet BTF_SET8_END(cpumask_kfunc_btf_ids)
438516f4d33SDavid Vernet
439516f4d33SDavid Vernet static const struct btf_kfunc_id_set cpumask_kfunc_set = {
440516f4d33SDavid Vernet .owner = THIS_MODULE,
441516f4d33SDavid Vernet .set = &cpumask_kfunc_btf_ids,
442516f4d33SDavid Vernet };
443516f4d33SDavid Vernet
444516f4d33SDavid Vernet BTF_ID_LIST(cpumask_dtor_ids)
BTF_ID(struct,bpf_cpumask)445516f4d33SDavid Vernet BTF_ID(struct, bpf_cpumask)
446516f4d33SDavid Vernet BTF_ID(func, bpf_cpumask_release)
447516f4d33SDavid Vernet
448516f4d33SDavid Vernet static int __init cpumask_kfunc_init(void)
449516f4d33SDavid Vernet {
450516f4d33SDavid Vernet int ret;
451516f4d33SDavid Vernet const struct btf_id_dtor_kfunc cpumask_dtors[] = {
452516f4d33SDavid Vernet {
453516f4d33SDavid Vernet .btf_id = cpumask_dtor_ids[0],
454516f4d33SDavid Vernet .kfunc_btf_id = cpumask_dtor_ids[1]
455516f4d33SDavid Vernet },
456516f4d33SDavid Vernet };
457516f4d33SDavid Vernet
4585d5de3a4SHou Tao ret = bpf_mem_alloc_init(&bpf_cpumask_ma, sizeof(struct bpf_cpumask), false);
459516f4d33SDavid Vernet ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &cpumask_kfunc_set);
460516f4d33SDavid Vernet ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &cpumask_kfunc_set);
461516f4d33SDavid Vernet return ret ?: register_btf_id_dtor_kfuncs(cpumask_dtors,
462516f4d33SDavid Vernet ARRAY_SIZE(cpumask_dtors),
463516f4d33SDavid Vernet THIS_MODULE);
464516f4d33SDavid Vernet }
465516f4d33SDavid Vernet
466516f4d33SDavid Vernet late_initcall(cpumask_kfunc_init);
467