xref: /openbmc/linux/Documentation/bpf/cpumasks.rst (revision 03b77e17aeb22a5935ea20d585ca6a1f2947e62b)
1bdbda395SDavid Vernet.. SPDX-License-Identifier: GPL-2.0
2bdbda395SDavid Vernet
3bdbda395SDavid Vernet.. _cpumasks-header-label:
4bdbda395SDavid Vernet
5bdbda395SDavid Vernet==================
6bdbda395SDavid VernetBPF cpumask kfuncs
7bdbda395SDavid Vernet==================
8bdbda395SDavid Vernet
9bdbda395SDavid Vernet1. Introduction
10bdbda395SDavid Vernet===============
11bdbda395SDavid Vernet
12bdbda395SDavid Vernet``struct cpumask`` is a bitmap data structure in the kernel whose indices
13bdbda395SDavid Vernetreflect the CPUs on the system. Commonly, cpumasks are used to track which CPUs
14bdbda395SDavid Verneta task is affinitized to, but they can also be used to e.g. track which cores
15bdbda395SDavid Vernetare associated with a scheduling domain, which cores on a machine are idle,
16bdbda395SDavid Vernetetc.
17bdbda395SDavid Vernet
18bdbda395SDavid VernetBPF provides programs with a set of :ref:`kfuncs-header-label` that can be
19bdbda395SDavid Vernetused to allocate, mutate, query, and free cpumasks.
20bdbda395SDavid Vernet
21bdbda395SDavid Vernet2. BPF cpumask objects
22bdbda395SDavid Vernet======================
23bdbda395SDavid Vernet
24bdbda395SDavid VernetThere are two different types of cpumasks that can be used by BPF programs.
25bdbda395SDavid Vernet
26bdbda395SDavid Vernet2.1 ``struct bpf_cpumask *``
27bdbda395SDavid Vernet----------------------------
28bdbda395SDavid Vernet
29bdbda395SDavid Vernet``struct bpf_cpumask *`` is a cpumask that is allocated by BPF, on behalf of a
30bdbda395SDavid VernetBPF program, and whose lifecycle is entirely controlled by BPF. These cpumasks
31bdbda395SDavid Vernetare RCU-protected, can be mutated, can be used as kptrs, and can be safely cast
32bdbda395SDavid Vernetto a ``struct cpumask *``.
33bdbda395SDavid Vernet
34bdbda395SDavid Vernet2.1.1 ``struct bpf_cpumask *`` lifecycle
35bdbda395SDavid Vernet----------------------------------------
36bdbda395SDavid Vernet
37bdbda395SDavid VernetA ``struct bpf_cpumask *`` is allocated, acquired, and released, using the
38bdbda395SDavid Vernetfollowing functions:
39bdbda395SDavid Vernet
40bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
41bdbda395SDavid Vernet  :identifiers: bpf_cpumask_create
42bdbda395SDavid Vernet
43bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
44bdbda395SDavid Vernet  :identifiers: bpf_cpumask_acquire
45bdbda395SDavid Vernet
46bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
47bdbda395SDavid Vernet  :identifiers: bpf_cpumask_release
48bdbda395SDavid Vernet
49bdbda395SDavid VernetFor example:
50bdbda395SDavid Vernet
51bdbda395SDavid Vernet.. code-block:: c
52bdbda395SDavid Vernet
53bdbda395SDavid Vernet        struct cpumask_map_value {
54*03b77e17SAlexei Starovoitov                struct bpf_cpumask __kptr * cpumask;
55bdbda395SDavid Vernet        };
56bdbda395SDavid Vernet
57bdbda395SDavid Vernet        struct array_map {
58bdbda395SDavid Vernet                __uint(type, BPF_MAP_TYPE_ARRAY);
59bdbda395SDavid Vernet                __type(key, int);
60bdbda395SDavid Vernet                __type(value, struct cpumask_map_value);
61bdbda395SDavid Vernet                __uint(max_entries, 65536);
62bdbda395SDavid Vernet        } cpumask_map SEC(".maps");
63bdbda395SDavid Vernet
64bdbda395SDavid Vernet        static int cpumask_map_insert(struct bpf_cpumask *mask, u32 pid)
65bdbda395SDavid Vernet        {
66bdbda395SDavid Vernet                struct cpumask_map_value local, *v;
67bdbda395SDavid Vernet                long status;
68bdbda395SDavid Vernet                struct bpf_cpumask *old;
69bdbda395SDavid Vernet                u32 key = pid;
70bdbda395SDavid Vernet
71bdbda395SDavid Vernet                local.cpumask = NULL;
72bdbda395SDavid Vernet                status = bpf_map_update_elem(&cpumask_map, &key, &local, 0);
73bdbda395SDavid Vernet                if (status) {
74bdbda395SDavid Vernet                        bpf_cpumask_release(mask);
75bdbda395SDavid Vernet                        return status;
76bdbda395SDavid Vernet                }
77bdbda395SDavid Vernet
78bdbda395SDavid Vernet                v = bpf_map_lookup_elem(&cpumask_map, &key);
79bdbda395SDavid Vernet                if (!v) {
80bdbda395SDavid Vernet                        bpf_cpumask_release(mask);
81bdbda395SDavid Vernet                        return -ENOENT;
82bdbda395SDavid Vernet                }
83bdbda395SDavid Vernet
84bdbda395SDavid Vernet                old = bpf_kptr_xchg(&v->cpumask, mask);
85bdbda395SDavid Vernet                if (old)
86bdbda395SDavid Vernet                        bpf_cpumask_release(old);
87bdbda395SDavid Vernet
88bdbda395SDavid Vernet                return 0;
89bdbda395SDavid Vernet        }
90bdbda395SDavid Vernet
91bdbda395SDavid Vernet        /**
92bdbda395SDavid Vernet         * A sample tracepoint showing how a task's cpumask can be queried and
93bdbda395SDavid Vernet         * recorded as a kptr.
94bdbda395SDavid Vernet         */
95bdbda395SDavid Vernet        SEC("tp_btf/task_newtask")
96bdbda395SDavid Vernet        int BPF_PROG(record_task_cpumask, struct task_struct *task, u64 clone_flags)
97bdbda395SDavid Vernet        {
98bdbda395SDavid Vernet                struct bpf_cpumask *cpumask;
99bdbda395SDavid Vernet                int ret;
100bdbda395SDavid Vernet
101bdbda395SDavid Vernet                cpumask = bpf_cpumask_create();
102bdbda395SDavid Vernet                if (!cpumask)
103bdbda395SDavid Vernet                        return -ENOMEM;
104bdbda395SDavid Vernet
105bdbda395SDavid Vernet                if (!bpf_cpumask_full(task->cpus_ptr))
106bdbda395SDavid Vernet                        bpf_printk("task %s has CPU affinity", task->comm);
107bdbda395SDavid Vernet
108bdbda395SDavid Vernet                bpf_cpumask_copy(cpumask, task->cpus_ptr);
109bdbda395SDavid Vernet                return cpumask_map_insert(cpumask, task->pid);
110bdbda395SDavid Vernet        }
111bdbda395SDavid Vernet
112bdbda395SDavid Vernet----
113bdbda395SDavid Vernet
114bdbda395SDavid Vernet2.1.1 ``struct bpf_cpumask *`` as kptrs
115bdbda395SDavid Vernet---------------------------------------
116bdbda395SDavid Vernet
117bdbda395SDavid VernetAs mentioned and illustrated above, these ``struct bpf_cpumask *`` objects can
118bdbda395SDavid Vernetalso be stored in a map and used as kptrs. If a ``struct bpf_cpumask *`` is in
119bdbda395SDavid Verneta map, the reference can be removed from the map with bpf_kptr_xchg(), or
120bdbda395SDavid Vernetopportunistically acquired with bpf_cpumask_kptr_get():
121bdbda395SDavid Vernet
122bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
123bdbda395SDavid Vernet  :identifiers: bpf_cpumask_kptr_get
124bdbda395SDavid Vernet
125bdbda395SDavid VernetHere is an example of a ``struct bpf_cpumask *`` being retrieved from a map:
126bdbda395SDavid Vernet
127bdbda395SDavid Vernet.. code-block:: c
128bdbda395SDavid Vernet
129bdbda395SDavid Vernet	/* struct containing the struct bpf_cpumask kptr which is stored in the map. */
130bdbda395SDavid Vernet	struct cpumasks_kfunc_map_value {
131*03b77e17SAlexei Starovoitov		struct bpf_cpumask __kptr * bpf_cpumask;
132bdbda395SDavid Vernet	};
133bdbda395SDavid Vernet
134bdbda395SDavid Vernet	/* The map containing struct cpumasks_kfunc_map_value entries. */
135bdbda395SDavid Vernet	struct {
136bdbda395SDavid Vernet		__uint(type, BPF_MAP_TYPE_ARRAY);
137bdbda395SDavid Vernet		__type(key, int);
138bdbda395SDavid Vernet		__type(value, struct cpumasks_kfunc_map_value);
139bdbda395SDavid Vernet		__uint(max_entries, 1);
140bdbda395SDavid Vernet	} cpumasks_kfunc_map SEC(".maps");
141bdbda395SDavid Vernet
142bdbda395SDavid Vernet	/* ... */
143bdbda395SDavid Vernet
144bdbda395SDavid Vernet	/**
145bdbda395SDavid Vernet	 * A simple example tracepoint program showing how a
146bdbda395SDavid Vernet	 * struct bpf_cpumask * kptr that is stored in a map can
147bdbda395SDavid Vernet	 * be acquired using the bpf_cpumask_kptr_get() kfunc.
148bdbda395SDavid Vernet	 */
149bdbda395SDavid Vernet	SEC("tp_btf/cgroup_mkdir")
150bdbda395SDavid Vernet	int BPF_PROG(cgrp_ancestor_example, struct cgroup *cgrp, const char *path)
151bdbda395SDavid Vernet	{
152bdbda395SDavid Vernet		struct bpf_cpumask *kptr;
153bdbda395SDavid Vernet		struct cpumasks_kfunc_map_value *v;
154bdbda395SDavid Vernet		u32 key = 0;
155bdbda395SDavid Vernet
156bdbda395SDavid Vernet		/* Assume a bpf_cpumask * kptr was previously stored in the map. */
157bdbda395SDavid Vernet		v = bpf_map_lookup_elem(&cpumasks_kfunc_map, &key);
158bdbda395SDavid Vernet		if (!v)
159bdbda395SDavid Vernet			return -ENOENT;
160bdbda395SDavid Vernet
161bdbda395SDavid Vernet		/* Acquire a reference to the bpf_cpumask * kptr that's already stored in the map. */
162bdbda395SDavid Vernet		kptr = bpf_cpumask_kptr_get(&v->cpumask);
163bdbda395SDavid Vernet		if (!kptr)
164bdbda395SDavid Vernet			/* If no bpf_cpumask was present in the map, it's because
165bdbda395SDavid Vernet			 * we're racing with another CPU that removed it with
166bdbda395SDavid Vernet			 * bpf_kptr_xchg() between the bpf_map_lookup_elem()
167bdbda395SDavid Vernet			 * above, and our call to bpf_cpumask_kptr_get().
168bdbda395SDavid Vernet			 * bpf_cpumask_kptr_get() internally safely handles this
169bdbda395SDavid Vernet			 * race, and will return NULL if the cpumask is no longer
170bdbda395SDavid Vernet			 * present in the map by the time we invoke the kfunc.
171bdbda395SDavid Vernet			 */
172bdbda395SDavid Vernet			return -EBUSY;
173bdbda395SDavid Vernet
174bdbda395SDavid Vernet		/* Free the reference we just took above. Note that the
175bdbda395SDavid Vernet		 * original struct bpf_cpumask * kptr is still in the map. It will
176bdbda395SDavid Vernet		 * be freed either at a later time if another context deletes
177bdbda395SDavid Vernet		 * it from the map, or automatically by the BPF subsystem if
178bdbda395SDavid Vernet		 * it's still present when the map is destroyed.
179bdbda395SDavid Vernet		 */
180bdbda395SDavid Vernet		bpf_cpumask_release(kptr);
181bdbda395SDavid Vernet
182bdbda395SDavid Vernet		return 0;
183bdbda395SDavid Vernet	}
184bdbda395SDavid Vernet
185bdbda395SDavid Vernet----
186bdbda395SDavid Vernet
187bdbda395SDavid Vernet2.2 ``struct cpumask``
188bdbda395SDavid Vernet----------------------
189bdbda395SDavid Vernet
190bdbda395SDavid Vernet``struct cpumask`` is the object that actually contains the cpumask bitmap
191bdbda395SDavid Vernetbeing queried, mutated, etc. A ``struct bpf_cpumask`` wraps a ``struct
192bdbda395SDavid Vernetcpumask``, which is why it's safe to cast it as such (note however that it is
193bdbda395SDavid Vernet**not** safe to cast a ``struct cpumask *`` to a ``struct bpf_cpumask *``, and
194bdbda395SDavid Vernetthe verifier will reject any program that tries to do so).
195bdbda395SDavid Vernet
196bdbda395SDavid VernetAs we'll see below, any kfunc that mutates its cpumask argument will take a
197bdbda395SDavid Vernet``struct bpf_cpumask *`` as that argument. Any argument that simply queries the
198bdbda395SDavid Vernetcpumask will instead take a ``struct cpumask *``.
199bdbda395SDavid Vernet
200bdbda395SDavid Vernet3. cpumask kfuncs
201bdbda395SDavid Vernet=================
202bdbda395SDavid Vernet
203bdbda395SDavid VernetAbove, we described the kfuncs that can be used to allocate, acquire, release,
204bdbda395SDavid Vernetetc a ``struct bpf_cpumask *``. This section of the document will describe the
205bdbda395SDavid Vernetkfuncs for mutating and querying cpumasks.
206bdbda395SDavid Vernet
207bdbda395SDavid Vernet3.1 Mutating cpumasks
208bdbda395SDavid Vernet---------------------
209bdbda395SDavid Vernet
210bdbda395SDavid VernetSome cpumask kfuncs are "read-only" in that they don't mutate any of their
211bdbda395SDavid Vernetarguments, whereas others mutate at least one argument (which means that the
212bdbda395SDavid Vernetargument must be a ``struct bpf_cpumask *``, as described above).
213bdbda395SDavid Vernet
214bdbda395SDavid VernetThis section will describe all of the cpumask kfuncs which mutate at least one
215bdbda395SDavid Vernetargument. :ref:`cpumasks-querying-label` below describes the read-only kfuncs.
216bdbda395SDavid Vernet
217bdbda395SDavid Vernet3.1.1 Setting and clearing CPUs
218bdbda395SDavid Vernet-------------------------------
219bdbda395SDavid Vernet
220bdbda395SDavid Vernetbpf_cpumask_set_cpu() and bpf_cpumask_clear_cpu() can be used to set and clear
221bdbda395SDavid Verneta CPU in a ``struct bpf_cpumask`` respectively:
222bdbda395SDavid Vernet
223bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
224bdbda395SDavid Vernet   :identifiers: bpf_cpumask_set_cpu bpf_cpumask_clear_cpu
225bdbda395SDavid Vernet
226bdbda395SDavid VernetThese kfuncs are pretty straightforward, and can be used, for example, as
227bdbda395SDavid Vernetfollows:
228bdbda395SDavid Vernet
229bdbda395SDavid Vernet.. code-block:: c
230bdbda395SDavid Vernet
231bdbda395SDavid Vernet        /**
232bdbda395SDavid Vernet         * A sample tracepoint showing how a cpumask can be queried.
233bdbda395SDavid Vernet         */
234bdbda395SDavid Vernet        SEC("tp_btf/task_newtask")
235bdbda395SDavid Vernet        int BPF_PROG(test_set_clear_cpu, struct task_struct *task, u64 clone_flags)
236bdbda395SDavid Vernet        {
237bdbda395SDavid Vernet                struct bpf_cpumask *cpumask;
238bdbda395SDavid Vernet
239bdbda395SDavid Vernet                cpumask = bpf_cpumask_create();
240bdbda395SDavid Vernet                if (!cpumask)
241bdbda395SDavid Vernet                        return -ENOMEM;
242bdbda395SDavid Vernet
243bdbda395SDavid Vernet                bpf_cpumask_set_cpu(0, cpumask);
244bdbda395SDavid Vernet                if (!bpf_cpumask_test_cpu(0, cast(cpumask)))
245bdbda395SDavid Vernet                        /* Should never happen. */
246bdbda395SDavid Vernet                        goto release_exit;
247bdbda395SDavid Vernet
248bdbda395SDavid Vernet                bpf_cpumask_clear_cpu(0, cpumask);
249bdbda395SDavid Vernet                if (bpf_cpumask_test_cpu(0, cast(cpumask)))
250bdbda395SDavid Vernet                        /* Should never happen. */
251bdbda395SDavid Vernet                        goto release_exit;
252bdbda395SDavid Vernet
253bdbda395SDavid Vernet                /* struct cpumask * pointers such as task->cpus_ptr can also be queried. */
254bdbda395SDavid Vernet                if (bpf_cpumask_test_cpu(0, task->cpus_ptr))
255bdbda395SDavid Vernet                        bpf_printk("task %s can use CPU %d", task->comm, 0);
256bdbda395SDavid Vernet
257bdbda395SDavid Vernet        release_exit:
258bdbda395SDavid Vernet                bpf_cpumask_release(cpumask);
259bdbda395SDavid Vernet                return 0;
260bdbda395SDavid Vernet        }
261bdbda395SDavid Vernet
262bdbda395SDavid Vernet----
263bdbda395SDavid Vernet
264bdbda395SDavid Vernetbpf_cpumask_test_and_set_cpu() and bpf_cpumask_test_and_clear_cpu() are
265bdbda395SDavid Vernetcomplementary kfuncs that allow callers to atomically test and set (or clear)
266bdbda395SDavid VernetCPUs:
267bdbda395SDavid Vernet
268bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
269bdbda395SDavid Vernet   :identifiers: bpf_cpumask_test_and_set_cpu bpf_cpumask_test_and_clear_cpu
270bdbda395SDavid Vernet
271bdbda395SDavid Vernet----
272bdbda395SDavid Vernet
273bdbda395SDavid VernetWe can also set and clear entire ``struct bpf_cpumask *`` objects in one
274bdbda395SDavid Vernetoperation using bpf_cpumask_setall() and bpf_cpumask_clear():
275bdbda395SDavid Vernet
276bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
277bdbda395SDavid Vernet   :identifiers: bpf_cpumask_setall bpf_cpumask_clear
278bdbda395SDavid Vernet
279bdbda395SDavid Vernet3.1.2 Operations between cpumasks
280bdbda395SDavid Vernet---------------------------------
281bdbda395SDavid Vernet
282bdbda395SDavid VernetIn addition to setting and clearing individual CPUs in a single cpumask,
283bdbda395SDavid Vernetcallers can also perform bitwise operations between multiple cpumasks using
284bdbda395SDavid Vernetbpf_cpumask_and(), bpf_cpumask_or(), and bpf_cpumask_xor():
285bdbda395SDavid Vernet
286bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
287bdbda395SDavid Vernet   :identifiers: bpf_cpumask_and bpf_cpumask_or bpf_cpumask_xor
288bdbda395SDavid Vernet
289bdbda395SDavid VernetThe following is an example of how they may be used. Note that some of the
290bdbda395SDavid Vernetkfuncs shown in this example will be covered in more detail below.
291bdbda395SDavid Vernet
292bdbda395SDavid Vernet.. code-block:: c
293bdbda395SDavid Vernet
294bdbda395SDavid Vernet        /**
295bdbda395SDavid Vernet         * A sample tracepoint showing how a cpumask can be mutated using
296bdbda395SDavid Vernet           bitwise operators (and queried).
297bdbda395SDavid Vernet         */
298bdbda395SDavid Vernet        SEC("tp_btf/task_newtask")
299bdbda395SDavid Vernet        int BPF_PROG(test_and_or_xor, struct task_struct *task, u64 clone_flags)
300bdbda395SDavid Vernet        {
301bdbda395SDavid Vernet                struct bpf_cpumask *mask1, *mask2, *dst1, *dst2;
302bdbda395SDavid Vernet
303bdbda395SDavid Vernet                mask1 = bpf_cpumask_create();
304bdbda395SDavid Vernet                if (!mask1)
305bdbda395SDavid Vernet                        return -ENOMEM;
306bdbda395SDavid Vernet
307bdbda395SDavid Vernet                mask2 = bpf_cpumask_create();
308bdbda395SDavid Vernet                if (!mask2) {
309bdbda395SDavid Vernet                        bpf_cpumask_release(mask1);
310bdbda395SDavid Vernet                        return -ENOMEM;
311bdbda395SDavid Vernet                }
312bdbda395SDavid Vernet
313bdbda395SDavid Vernet                // ...Safely create the other two masks... */
314bdbda395SDavid Vernet
315bdbda395SDavid Vernet                bpf_cpumask_set_cpu(0, mask1);
316bdbda395SDavid Vernet                bpf_cpumask_set_cpu(1, mask2);
317bdbda395SDavid Vernet                bpf_cpumask_and(dst1, (const struct cpumask *)mask1, (const struct cpumask *)mask2);
318bdbda395SDavid Vernet                if (!bpf_cpumask_empty((const struct cpumask *)dst1))
319bdbda395SDavid Vernet                        /* Should never happen. */
320bdbda395SDavid Vernet                        goto release_exit;
321bdbda395SDavid Vernet
322bdbda395SDavid Vernet                bpf_cpumask_or(dst1, (const struct cpumask *)mask1, (const struct cpumask *)mask2);
323bdbda395SDavid Vernet                if (!bpf_cpumask_test_cpu(0, (const struct cpumask *)dst1))
324bdbda395SDavid Vernet                        /* Should never happen. */
325bdbda395SDavid Vernet                        goto release_exit;
326bdbda395SDavid Vernet
327bdbda395SDavid Vernet                if (!bpf_cpumask_test_cpu(1, (const struct cpumask *)dst1))
328bdbda395SDavid Vernet                        /* Should never happen. */
329bdbda395SDavid Vernet                        goto release_exit;
330bdbda395SDavid Vernet
331bdbda395SDavid Vernet                bpf_cpumask_xor(dst2, (const struct cpumask *)mask1, (const struct cpumask *)mask2);
332bdbda395SDavid Vernet                if (!bpf_cpumask_equal((const struct cpumask *)dst1,
333bdbda395SDavid Vernet                                       (const struct cpumask *)dst2))
334bdbda395SDavid Vernet                        /* Should never happen. */
335bdbda395SDavid Vernet                        goto release_exit;
336bdbda395SDavid Vernet
337bdbda395SDavid Vernet         release_exit:
338bdbda395SDavid Vernet                bpf_cpumask_release(mask1);
339bdbda395SDavid Vernet                bpf_cpumask_release(mask2);
340bdbda395SDavid Vernet                bpf_cpumask_release(dst1);
341bdbda395SDavid Vernet                bpf_cpumask_release(dst2);
342bdbda395SDavid Vernet                return 0;
343bdbda395SDavid Vernet        }
344bdbda395SDavid Vernet
345bdbda395SDavid Vernet----
346bdbda395SDavid Vernet
347bdbda395SDavid VernetThe contents of an entire cpumask may be copied to another using
348bdbda395SDavid Vernetbpf_cpumask_copy():
349bdbda395SDavid Vernet
350bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
351bdbda395SDavid Vernet   :identifiers: bpf_cpumask_copy
352bdbda395SDavid Vernet
353bdbda395SDavid Vernet----
354bdbda395SDavid Vernet
355bdbda395SDavid Vernet.. _cpumasks-querying-label:
356bdbda395SDavid Vernet
357bdbda395SDavid Vernet3.2 Querying cpumasks
358bdbda395SDavid Vernet---------------------
359bdbda395SDavid Vernet
360bdbda395SDavid VernetIn addition to the above kfuncs, there is also a set of read-only kfuncs that
361bdbda395SDavid Vernetcan be used to query the contents of cpumasks.
362bdbda395SDavid Vernet
363bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
364bdbda395SDavid Vernet   :identifiers: bpf_cpumask_first bpf_cpumask_first_zero bpf_cpumask_test_cpu
365bdbda395SDavid Vernet
366bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
367bdbda395SDavid Vernet   :identifiers: bpf_cpumask_equal bpf_cpumask_intersects bpf_cpumask_subset
368bdbda395SDavid Vernet                 bpf_cpumask_empty bpf_cpumask_full
369bdbda395SDavid Vernet
370bdbda395SDavid Vernet.. kernel-doc:: kernel/bpf/cpumask.c
371bdbda395SDavid Vernet   :identifiers: bpf_cpumask_any bpf_cpumask_any_and
372bdbda395SDavid Vernet
373bdbda395SDavid Vernet----
374bdbda395SDavid Vernet
375bdbda395SDavid VernetSome example usages of these querying kfuncs were shown above. We will not
376bdbda395SDavid Vernetreplicate those exmaples here. Note, however, that all of the aforementioned
377bdbda395SDavid Vernetkfuncs are tested in `tools/testing/selftests/bpf/progs/cpumask_success.c`_, so
378bdbda395SDavid Vernetplease take a look there if you're looking for more examples of how they can be
379bdbda395SDavid Vernetused.
380bdbda395SDavid Vernet
381bdbda395SDavid Vernet.. _tools/testing/selftests/bpf/progs/cpumask_success.c:
382bdbda395SDavid Vernet   https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/tools/testing/selftests/bpf/progs/cpumask_success.c
383bdbda395SDavid Vernet
384bdbda395SDavid Vernet
385bdbda395SDavid Vernet4. Adding BPF cpumask kfuncs
386bdbda395SDavid Vernet============================
387bdbda395SDavid Vernet
388bdbda395SDavid VernetThe set of supported BPF cpumask kfuncs are not (yet) a 1-1 match with the
389bdbda395SDavid Vernetcpumask operations in include/linux/cpumask.h. Any of those cpumask operations
390bdbda395SDavid Vernetcould easily be encapsulated in a new kfunc if and when required. If you'd like
391bdbda395SDavid Vernetto support a new cpumask operation, please feel free to submit a patch. If you
392bdbda395SDavid Vernetdo add a new cpumask kfunc, please document it here, and add any relevant
393bdbda395SDavid Vernetselftest testcases to the cpumask selftest suite.
394