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