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