@@ -422,6 +422,85 @@ __bpf_kfunc u32 bpf_cpumask_weight(const struct cpumask *cpumask)
422422 return cpumask_weight (cpumask );
423423}
424424
425+ struct bpf_iter_cpumask {
426+ __u64 __opaque [2 ];
427+ } __aligned (8 );
428+
429+ struct bpf_iter_cpumask_kern {
430+ struct cpumask * mask ;
431+ int cpu ;
432+ } __aligned (8 );
433+
434+ /**
435+ * bpf_iter_cpumask_new() - Create a new bpf_iter_cpumask for a specified cpumask
436+ * @it: The new bpf_iter_cpumask to be created.
437+ * @mask: The cpumask to be iterated over.
438+ *
439+ * This function initializes a new bpf_iter_cpumask structure for iterating over
440+ * the specified CPU mask. It assigns the provided cpumask to the newly created
441+ * bpf_iter_cpumask @it for subsequent iteration operations.
442+ *
443+ * On success, 0 is returen. On failure, ERR is returned.
444+ */
445+ __bpf_kfunc int bpf_iter_cpumask_new (struct bpf_iter_cpumask * it , const struct cpumask * mask )
446+ {
447+ struct bpf_iter_cpumask_kern * kit = (void * )it ;
448+
449+ BUILD_BUG_ON (sizeof (struct bpf_iter_cpumask_kern ) > sizeof (struct bpf_iter_cpumask ));
450+ BUILD_BUG_ON (__alignof__(struct bpf_iter_cpumask_kern ) !=
451+ __alignof__(struct bpf_iter_cpumask ));
452+
453+ kit -> mask = bpf_mem_alloc (& bpf_global_ma , sizeof (struct cpumask ));
454+ if (!kit -> mask )
455+ return - ENOMEM ;
456+
457+ cpumask_copy (kit -> mask , mask );
458+ kit -> cpu = -1 ;
459+ return 0 ;
460+ }
461+
462+ /**
463+ * bpf_iter_cpumask_next() - Get the next CPU in a bpf_iter_cpumask
464+ * @it: The bpf_iter_cpumask
465+ *
466+ * This function retrieves a pointer to the number of the next CPU within the
467+ * specified bpf_iter_cpumask. It allows sequential access to CPUs within the
468+ * cpumask. If there are no further CPUs available, it returns NULL.
469+ *
470+ * Returns a pointer to the number of the next CPU in the cpumask or NULL if no
471+ * further CPUs.
472+ */
473+ __bpf_kfunc int * bpf_iter_cpumask_next (struct bpf_iter_cpumask * it )
474+ {
475+ struct bpf_iter_cpumask_kern * kit = (void * )it ;
476+ const struct cpumask * mask = kit -> mask ;
477+ int cpu ;
478+
479+ if (!mask )
480+ return NULL ;
481+ cpu = cpumask_next (kit -> cpu , mask );
482+ if (cpu >= nr_cpu_ids )
483+ return NULL ;
484+
485+ kit -> cpu = cpu ;
486+ return & kit -> cpu ;
487+ }
488+
489+ /**
490+ * bpf_iter_cpumask_destroy() - Destroy a bpf_iter_cpumask
491+ * @it: The bpf_iter_cpumask to be destroyed.
492+ *
493+ * Destroy the resource assiciated with the bpf_iter_cpumask.
494+ */
495+ __bpf_kfunc void bpf_iter_cpumask_destroy (struct bpf_iter_cpumask * it )
496+ {
497+ struct bpf_iter_cpumask_kern * kit = (void * )it ;
498+
499+ if (!kit -> mask )
500+ return ;
501+ bpf_mem_free (& bpf_global_ma , kit -> mask );
502+ }
503+
425504__bpf_kfunc_end_defs ();
426505
427506BTF_SET8_START (cpumask_kfunc_btf_ids )
@@ -450,6 +529,9 @@ BTF_ID_FLAGS(func, bpf_cpumask_copy, KF_RCU)
450529BTF_ID_FLAGS (func , bpf_cpumask_any_distribute , KF_RCU )
451530BTF_ID_FLAGS (func , bpf_cpumask_any_and_distribute , KF_RCU )
452531BTF_ID_FLAGS (func , bpf_cpumask_weight , KF_RCU )
532+ BTF_ID_FLAGS (func , bpf_iter_cpumask_new , KF_ITER_NEW | KF_RCU )
533+ BTF_ID_FLAGS (func , bpf_iter_cpumask_next , KF_ITER_NEXT | KF_RET_NULL )
534+ BTF_ID_FLAGS (func , bpf_iter_cpumask_destroy , KF_ITER_DESTROY )
453535BTF_SET8_END (cpumask_kfunc_btf_ids )
454536
455537static const struct btf_kfunc_id_set cpumask_kfunc_set = {
0 commit comments