162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Copyright (c) 2023 Meta, Inc */ 362306a36Sopenharmony_ci#include <linux/bpf.h> 462306a36Sopenharmony_ci#include <linux/bpf_mem_alloc.h> 562306a36Sopenharmony_ci#include <linux/btf.h> 662306a36Sopenharmony_ci#include <linux/btf_ids.h> 762306a36Sopenharmony_ci#include <linux/cpumask.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/** 1062306a36Sopenharmony_ci * struct bpf_cpumask - refcounted BPF cpumask wrapper structure 1162306a36Sopenharmony_ci * @cpumask: The actual cpumask embedded in the struct. 1262306a36Sopenharmony_ci * @usage: Object reference counter. When the refcount goes to 0, the 1362306a36Sopenharmony_ci * memory is released back to the BPF allocator, which provides 1462306a36Sopenharmony_ci * RCU safety. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Note that we explicitly embed a cpumask_t rather than a cpumask_var_t. This 1762306a36Sopenharmony_ci * is done to avoid confusing the verifier due to the typedef of cpumask_var_t 1862306a36Sopenharmony_ci * changing depending on whether CONFIG_CPUMASK_OFFSTACK is defined or not. See 1962306a36Sopenharmony_ci * the details in <linux/cpumask.h>. The consequence is that this structure is 2062306a36Sopenharmony_ci * likely a bit larger than it needs to be when CONFIG_CPUMASK_OFFSTACK is 2162306a36Sopenharmony_ci * defined due to embedding the whole NR_CPUS-size bitmap, but the extra memory 2262306a36Sopenharmony_ci * overhead is minimal. For the more typical case of CONFIG_CPUMASK_OFFSTACK 2362306a36Sopenharmony_ci * not being defined, the structure is the same size regardless. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_cistruct bpf_cpumask { 2662306a36Sopenharmony_ci cpumask_t cpumask; 2762306a36Sopenharmony_ci refcount_t usage; 2862306a36Sopenharmony_ci}; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic struct bpf_mem_alloc bpf_cpumask_ma; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic bool cpu_valid(u32 cpu) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci return cpu < nr_cpu_ids; 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci__diag_push(); 3862306a36Sopenharmony_ci__diag_ignore_all("-Wmissing-prototypes", 3962306a36Sopenharmony_ci "Global kfuncs as their definitions will be in BTF"); 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/** 4262306a36Sopenharmony_ci * bpf_cpumask_create() - Create a mutable BPF cpumask. 4362306a36Sopenharmony_ci * 4462306a36Sopenharmony_ci * Allocates a cpumask that can be queried, mutated, acquired, and released by 4562306a36Sopenharmony_ci * a BPF program. The cpumask returned by this function must either be embedded 4662306a36Sopenharmony_ci * in a map as a kptr, or freed with bpf_cpumask_release(). 4762306a36Sopenharmony_ci * 4862306a36Sopenharmony_ci * bpf_cpumask_create() allocates memory using the BPF memory allocator, and 4962306a36Sopenharmony_ci * will not block. It may return NULL if no memory is available. 5062306a36Sopenharmony_ci */ 5162306a36Sopenharmony_ci__bpf_kfunc struct bpf_cpumask *bpf_cpumask_create(void) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci struct bpf_cpumask *cpumask; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* cpumask must be the first element so struct bpf_cpumask be cast to struct cpumask. */ 5662306a36Sopenharmony_ci BUILD_BUG_ON(offsetof(struct bpf_cpumask, cpumask) != 0); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci cpumask = bpf_mem_cache_alloc(&bpf_cpumask_ma); 5962306a36Sopenharmony_ci if (!cpumask) 6062306a36Sopenharmony_ci return NULL; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci memset(cpumask, 0, sizeof(*cpumask)); 6362306a36Sopenharmony_ci refcount_set(&cpumask->usage, 1); 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci return cpumask; 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/** 6962306a36Sopenharmony_ci * bpf_cpumask_acquire() - Acquire a reference to a BPF cpumask. 7062306a36Sopenharmony_ci * @cpumask: The BPF cpumask being acquired. The cpumask must be a trusted 7162306a36Sopenharmony_ci * pointer. 7262306a36Sopenharmony_ci * 7362306a36Sopenharmony_ci * Acquires a reference to a BPF cpumask. The cpumask returned by this function 7462306a36Sopenharmony_ci * must either be embedded in a map as a kptr, or freed with 7562306a36Sopenharmony_ci * bpf_cpumask_release(). 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_ci__bpf_kfunc struct bpf_cpumask *bpf_cpumask_acquire(struct bpf_cpumask *cpumask) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci refcount_inc(&cpumask->usage); 8062306a36Sopenharmony_ci return cpumask; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/** 8462306a36Sopenharmony_ci * bpf_cpumask_release() - Release a previously acquired BPF cpumask. 8562306a36Sopenharmony_ci * @cpumask: The cpumask being released. 8662306a36Sopenharmony_ci * 8762306a36Sopenharmony_ci * Releases a previously acquired reference to a BPF cpumask. When the final 8862306a36Sopenharmony_ci * reference of the BPF cpumask has been released, it is subsequently freed in 8962306a36Sopenharmony_ci * an RCU callback in the BPF memory allocator. 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_ci__bpf_kfunc void bpf_cpumask_release(struct bpf_cpumask *cpumask) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci if (!refcount_dec_and_test(&cpumask->usage)) 9462306a36Sopenharmony_ci return; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci migrate_disable(); 9762306a36Sopenharmony_ci bpf_mem_cache_free_rcu(&bpf_cpumask_ma, cpumask); 9862306a36Sopenharmony_ci migrate_enable(); 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/** 10262306a36Sopenharmony_ci * bpf_cpumask_first() - Get the index of the first nonzero bit in the cpumask. 10362306a36Sopenharmony_ci * @cpumask: The cpumask being queried. 10462306a36Sopenharmony_ci * 10562306a36Sopenharmony_ci * Find the index of the first nonzero bit of the cpumask. A struct bpf_cpumask 10662306a36Sopenharmony_ci * pointer may be safely passed to this function. 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_ci__bpf_kfunc u32 bpf_cpumask_first(const struct cpumask *cpumask) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci return cpumask_first(cpumask); 11162306a36Sopenharmony_ci} 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/** 11462306a36Sopenharmony_ci * bpf_cpumask_first_zero() - Get the index of the first unset bit in the 11562306a36Sopenharmony_ci * cpumask. 11662306a36Sopenharmony_ci * @cpumask: The cpumask being queried. 11762306a36Sopenharmony_ci * 11862306a36Sopenharmony_ci * Find the index of the first unset bit of the cpumask. A struct bpf_cpumask 11962306a36Sopenharmony_ci * pointer may be safely passed to this function. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_ci__bpf_kfunc u32 bpf_cpumask_first_zero(const struct cpumask *cpumask) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci return cpumask_first_zero(cpumask); 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci/** 12762306a36Sopenharmony_ci * bpf_cpumask_first_and() - Return the index of the first nonzero bit from the 12862306a36Sopenharmony_ci * AND of two cpumasks. 12962306a36Sopenharmony_ci * @src1: The first cpumask. 13062306a36Sopenharmony_ci * @src2: The second cpumask. 13162306a36Sopenharmony_ci * 13262306a36Sopenharmony_ci * Find the index of the first nonzero bit of the AND of two cpumasks. 13362306a36Sopenharmony_ci * struct bpf_cpumask pointers may be safely passed to @src1 and @src2. 13462306a36Sopenharmony_ci */ 13562306a36Sopenharmony_ci__bpf_kfunc u32 bpf_cpumask_first_and(const struct cpumask *src1, 13662306a36Sopenharmony_ci const struct cpumask *src2) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci return cpumask_first_and(src1, src2); 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci/** 14262306a36Sopenharmony_ci * bpf_cpumask_set_cpu() - Set a bit for a CPU in a BPF cpumask. 14362306a36Sopenharmony_ci * @cpu: The CPU to be set in the cpumask. 14462306a36Sopenharmony_ci * @cpumask: The BPF cpumask in which a bit is being set. 14562306a36Sopenharmony_ci */ 14662306a36Sopenharmony_ci__bpf_kfunc void bpf_cpumask_set_cpu(u32 cpu, struct bpf_cpumask *cpumask) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci if (!cpu_valid(cpu)) 14962306a36Sopenharmony_ci return; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci cpumask_set_cpu(cpu, (struct cpumask *)cpumask); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/** 15562306a36Sopenharmony_ci * bpf_cpumask_clear_cpu() - Clear a bit for a CPU in a BPF cpumask. 15662306a36Sopenharmony_ci * @cpu: The CPU to be cleared from the cpumask. 15762306a36Sopenharmony_ci * @cpumask: The BPF cpumask in which a bit is being cleared. 15862306a36Sopenharmony_ci */ 15962306a36Sopenharmony_ci__bpf_kfunc void bpf_cpumask_clear_cpu(u32 cpu, struct bpf_cpumask *cpumask) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci if (!cpu_valid(cpu)) 16262306a36Sopenharmony_ci return; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci cpumask_clear_cpu(cpu, (struct cpumask *)cpumask); 16562306a36Sopenharmony_ci} 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci/** 16862306a36Sopenharmony_ci * bpf_cpumask_test_cpu() - Test whether a CPU is set in a cpumask. 16962306a36Sopenharmony_ci * @cpu: The CPU being queried for. 17062306a36Sopenharmony_ci * @cpumask: The cpumask being queried for containing a CPU. 17162306a36Sopenharmony_ci * 17262306a36Sopenharmony_ci * Return: 17362306a36Sopenharmony_ci * * true - @cpu is set in the cpumask 17462306a36Sopenharmony_ci * * false - @cpu was not set in the cpumask, or @cpu is an invalid cpu. 17562306a36Sopenharmony_ci */ 17662306a36Sopenharmony_ci__bpf_kfunc bool bpf_cpumask_test_cpu(u32 cpu, const struct cpumask *cpumask) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci if (!cpu_valid(cpu)) 17962306a36Sopenharmony_ci return false; 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci return cpumask_test_cpu(cpu, (struct cpumask *)cpumask); 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci/** 18562306a36Sopenharmony_ci * bpf_cpumask_test_and_set_cpu() - Atomically test and set a CPU in a BPF cpumask. 18662306a36Sopenharmony_ci * @cpu: The CPU being set and queried for. 18762306a36Sopenharmony_ci * @cpumask: The BPF cpumask being set and queried for containing a CPU. 18862306a36Sopenharmony_ci * 18962306a36Sopenharmony_ci * Return: 19062306a36Sopenharmony_ci * * true - @cpu is set in the cpumask 19162306a36Sopenharmony_ci * * false - @cpu was not set in the cpumask, or @cpu is invalid. 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_ci__bpf_kfunc bool bpf_cpumask_test_and_set_cpu(u32 cpu, struct bpf_cpumask *cpumask) 19462306a36Sopenharmony_ci{ 19562306a36Sopenharmony_ci if (!cpu_valid(cpu)) 19662306a36Sopenharmony_ci return false; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci return cpumask_test_and_set_cpu(cpu, (struct cpumask *)cpumask); 19962306a36Sopenharmony_ci} 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci/** 20262306a36Sopenharmony_ci * bpf_cpumask_test_and_clear_cpu() - Atomically test and clear a CPU in a BPF 20362306a36Sopenharmony_ci * cpumask. 20462306a36Sopenharmony_ci * @cpu: The CPU being cleared and queried for. 20562306a36Sopenharmony_ci * @cpumask: The BPF cpumask being cleared and queried for containing a CPU. 20662306a36Sopenharmony_ci * 20762306a36Sopenharmony_ci * Return: 20862306a36Sopenharmony_ci * * true - @cpu is set in the cpumask 20962306a36Sopenharmony_ci * * false - @cpu was not set in the cpumask, or @cpu is invalid. 21062306a36Sopenharmony_ci */ 21162306a36Sopenharmony_ci__bpf_kfunc bool bpf_cpumask_test_and_clear_cpu(u32 cpu, struct bpf_cpumask *cpumask) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci if (!cpu_valid(cpu)) 21462306a36Sopenharmony_ci return false; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci return cpumask_test_and_clear_cpu(cpu, (struct cpumask *)cpumask); 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci/** 22062306a36Sopenharmony_ci * bpf_cpumask_setall() - Set all of the bits in a BPF cpumask. 22162306a36Sopenharmony_ci * @cpumask: The BPF cpumask having all of its bits set. 22262306a36Sopenharmony_ci */ 22362306a36Sopenharmony_ci__bpf_kfunc void bpf_cpumask_setall(struct bpf_cpumask *cpumask) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci cpumask_setall((struct cpumask *)cpumask); 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci/** 22962306a36Sopenharmony_ci * bpf_cpumask_clear() - Clear all of the bits in a BPF cpumask. 23062306a36Sopenharmony_ci * @cpumask: The BPF cpumask being cleared. 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_ci__bpf_kfunc void bpf_cpumask_clear(struct bpf_cpumask *cpumask) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci cpumask_clear((struct cpumask *)cpumask); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/** 23862306a36Sopenharmony_ci * bpf_cpumask_and() - AND two cpumasks and store the result. 23962306a36Sopenharmony_ci * @dst: The BPF cpumask where the result is being stored. 24062306a36Sopenharmony_ci * @src1: The first input. 24162306a36Sopenharmony_ci * @src2: The second input. 24262306a36Sopenharmony_ci * 24362306a36Sopenharmony_ci * Return: 24462306a36Sopenharmony_ci * * true - @dst has at least one bit set following the operation 24562306a36Sopenharmony_ci * * false - @dst is empty following the operation 24662306a36Sopenharmony_ci * 24762306a36Sopenharmony_ci * struct bpf_cpumask pointers may be safely passed to @src1 and @src2. 24862306a36Sopenharmony_ci */ 24962306a36Sopenharmony_ci__bpf_kfunc bool bpf_cpumask_and(struct bpf_cpumask *dst, 25062306a36Sopenharmony_ci const struct cpumask *src1, 25162306a36Sopenharmony_ci const struct cpumask *src2) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci return cpumask_and((struct cpumask *)dst, src1, src2); 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci/** 25762306a36Sopenharmony_ci * bpf_cpumask_or() - OR two cpumasks and store the result. 25862306a36Sopenharmony_ci * @dst: The BPF cpumask where the result is being stored. 25962306a36Sopenharmony_ci * @src1: The first input. 26062306a36Sopenharmony_ci * @src2: The second input. 26162306a36Sopenharmony_ci * 26262306a36Sopenharmony_ci * struct bpf_cpumask pointers may be safely passed to @src1 and @src2. 26362306a36Sopenharmony_ci */ 26462306a36Sopenharmony_ci__bpf_kfunc void bpf_cpumask_or(struct bpf_cpumask *dst, 26562306a36Sopenharmony_ci const struct cpumask *src1, 26662306a36Sopenharmony_ci const struct cpumask *src2) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci cpumask_or((struct cpumask *)dst, src1, src2); 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/** 27262306a36Sopenharmony_ci * bpf_cpumask_xor() - XOR two cpumasks and store the result. 27362306a36Sopenharmony_ci * @dst: The BPF cpumask where the result is being stored. 27462306a36Sopenharmony_ci * @src1: The first input. 27562306a36Sopenharmony_ci * @src2: The second input. 27662306a36Sopenharmony_ci * 27762306a36Sopenharmony_ci * struct bpf_cpumask pointers may be safely passed to @src1 and @src2. 27862306a36Sopenharmony_ci */ 27962306a36Sopenharmony_ci__bpf_kfunc void bpf_cpumask_xor(struct bpf_cpumask *dst, 28062306a36Sopenharmony_ci const struct cpumask *src1, 28162306a36Sopenharmony_ci const struct cpumask *src2) 28262306a36Sopenharmony_ci{ 28362306a36Sopenharmony_ci cpumask_xor((struct cpumask *)dst, src1, src2); 28462306a36Sopenharmony_ci} 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci/** 28762306a36Sopenharmony_ci * bpf_cpumask_equal() - Check two cpumasks for equality. 28862306a36Sopenharmony_ci * @src1: The first input. 28962306a36Sopenharmony_ci * @src2: The second input. 29062306a36Sopenharmony_ci * 29162306a36Sopenharmony_ci * Return: 29262306a36Sopenharmony_ci * * true - @src1 and @src2 have the same bits set. 29362306a36Sopenharmony_ci * * false - @src1 and @src2 differ in at least one bit. 29462306a36Sopenharmony_ci * 29562306a36Sopenharmony_ci * struct bpf_cpumask pointers may be safely passed to @src1 and @src2. 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_ci__bpf_kfunc bool bpf_cpumask_equal(const struct cpumask *src1, const struct cpumask *src2) 29862306a36Sopenharmony_ci{ 29962306a36Sopenharmony_ci return cpumask_equal(src1, src2); 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci/** 30362306a36Sopenharmony_ci * bpf_cpumask_intersects() - Check two cpumasks for overlap. 30462306a36Sopenharmony_ci * @src1: The first input. 30562306a36Sopenharmony_ci * @src2: The second input. 30662306a36Sopenharmony_ci * 30762306a36Sopenharmony_ci * Return: 30862306a36Sopenharmony_ci * * true - @src1 and @src2 have at least one of the same bits set. 30962306a36Sopenharmony_ci * * false - @src1 and @src2 don't have any of the same bits set. 31062306a36Sopenharmony_ci * 31162306a36Sopenharmony_ci * struct bpf_cpumask pointers may be safely passed to @src1 and @src2. 31262306a36Sopenharmony_ci */ 31362306a36Sopenharmony_ci__bpf_kfunc bool bpf_cpumask_intersects(const struct cpumask *src1, const struct cpumask *src2) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci return cpumask_intersects(src1, src2); 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci/** 31962306a36Sopenharmony_ci * bpf_cpumask_subset() - Check if a cpumask is a subset of another. 32062306a36Sopenharmony_ci * @src1: The first cpumask being checked as a subset. 32162306a36Sopenharmony_ci * @src2: The second cpumask being checked as a superset. 32262306a36Sopenharmony_ci * 32362306a36Sopenharmony_ci * Return: 32462306a36Sopenharmony_ci * * true - All of the bits of @src1 are set in @src2. 32562306a36Sopenharmony_ci * * false - At least one bit in @src1 is not set in @src2. 32662306a36Sopenharmony_ci * 32762306a36Sopenharmony_ci * struct bpf_cpumask pointers may be safely passed to @src1 and @src2. 32862306a36Sopenharmony_ci */ 32962306a36Sopenharmony_ci__bpf_kfunc bool bpf_cpumask_subset(const struct cpumask *src1, const struct cpumask *src2) 33062306a36Sopenharmony_ci{ 33162306a36Sopenharmony_ci return cpumask_subset(src1, src2); 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci/** 33562306a36Sopenharmony_ci * bpf_cpumask_empty() - Check if a cpumask is empty. 33662306a36Sopenharmony_ci * @cpumask: The cpumask being checked. 33762306a36Sopenharmony_ci * 33862306a36Sopenharmony_ci * Return: 33962306a36Sopenharmony_ci * * true - None of the bits in @cpumask are set. 34062306a36Sopenharmony_ci * * false - At least one bit in @cpumask is set. 34162306a36Sopenharmony_ci * 34262306a36Sopenharmony_ci * A struct bpf_cpumask pointer may be safely passed to @cpumask. 34362306a36Sopenharmony_ci */ 34462306a36Sopenharmony_ci__bpf_kfunc bool bpf_cpumask_empty(const struct cpumask *cpumask) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci return cpumask_empty(cpumask); 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci/** 35062306a36Sopenharmony_ci * bpf_cpumask_full() - Check if a cpumask has all bits set. 35162306a36Sopenharmony_ci * @cpumask: The cpumask being checked. 35262306a36Sopenharmony_ci * 35362306a36Sopenharmony_ci * Return: 35462306a36Sopenharmony_ci * * true - All of the bits in @cpumask are set. 35562306a36Sopenharmony_ci * * false - At least one bit in @cpumask is cleared. 35662306a36Sopenharmony_ci * 35762306a36Sopenharmony_ci * A struct bpf_cpumask pointer may be safely passed to @cpumask. 35862306a36Sopenharmony_ci */ 35962306a36Sopenharmony_ci__bpf_kfunc bool bpf_cpumask_full(const struct cpumask *cpumask) 36062306a36Sopenharmony_ci{ 36162306a36Sopenharmony_ci return cpumask_full(cpumask); 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci/** 36562306a36Sopenharmony_ci * bpf_cpumask_copy() - Copy the contents of a cpumask into a BPF cpumask. 36662306a36Sopenharmony_ci * @dst: The BPF cpumask being copied into. 36762306a36Sopenharmony_ci * @src: The cpumask being copied. 36862306a36Sopenharmony_ci * 36962306a36Sopenharmony_ci * A struct bpf_cpumask pointer may be safely passed to @src. 37062306a36Sopenharmony_ci */ 37162306a36Sopenharmony_ci__bpf_kfunc void bpf_cpumask_copy(struct bpf_cpumask *dst, const struct cpumask *src) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci cpumask_copy((struct cpumask *)dst, src); 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci/** 37762306a36Sopenharmony_ci * bpf_cpumask_any_distribute() - Return a random set CPU from a cpumask. 37862306a36Sopenharmony_ci * @cpumask: The cpumask being queried. 37962306a36Sopenharmony_ci * 38062306a36Sopenharmony_ci * Return: 38162306a36Sopenharmony_ci * * A random set bit within [0, num_cpus) if at least one bit is set. 38262306a36Sopenharmony_ci * * >= num_cpus if no bit is set. 38362306a36Sopenharmony_ci * 38462306a36Sopenharmony_ci * A struct bpf_cpumask pointer may be safely passed to @src. 38562306a36Sopenharmony_ci */ 38662306a36Sopenharmony_ci__bpf_kfunc u32 bpf_cpumask_any_distribute(const struct cpumask *cpumask) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci return cpumask_any_distribute(cpumask); 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci/** 39262306a36Sopenharmony_ci * bpf_cpumask_any_and_distribute() - Return a random set CPU from the AND of 39362306a36Sopenharmony_ci * two cpumasks. 39462306a36Sopenharmony_ci * @src1: The first cpumask. 39562306a36Sopenharmony_ci * @src2: The second cpumask. 39662306a36Sopenharmony_ci * 39762306a36Sopenharmony_ci * Return: 39862306a36Sopenharmony_ci * * A random set bit within [0, num_cpus) from the AND of two cpumasks, if at 39962306a36Sopenharmony_ci * least one bit is set. 40062306a36Sopenharmony_ci * * >= num_cpus if no bit is set. 40162306a36Sopenharmony_ci * 40262306a36Sopenharmony_ci * struct bpf_cpumask pointers may be safely passed to @src1 and @src2. 40362306a36Sopenharmony_ci */ 40462306a36Sopenharmony_ci__bpf_kfunc u32 bpf_cpumask_any_and_distribute(const struct cpumask *src1, 40562306a36Sopenharmony_ci const struct cpumask *src2) 40662306a36Sopenharmony_ci{ 40762306a36Sopenharmony_ci return cpumask_any_and_distribute(src1, src2); 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci__diag_pop(); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ciBTF_SET8_START(cpumask_kfunc_btf_ids) 41362306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_create, KF_ACQUIRE | KF_RET_NULL) 41462306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_release, KF_RELEASE) 41562306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_acquire, KF_ACQUIRE | KF_TRUSTED_ARGS) 41662306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_first, KF_RCU) 41762306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_first_zero, KF_RCU) 41862306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_first_and, KF_RCU) 41962306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_set_cpu, KF_RCU) 42062306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_clear_cpu, KF_RCU) 42162306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_test_cpu, KF_RCU) 42262306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_test_and_set_cpu, KF_RCU) 42362306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_test_and_clear_cpu, KF_RCU) 42462306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_setall, KF_RCU) 42562306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_clear, KF_RCU) 42662306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_and, KF_RCU) 42762306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_or, KF_RCU) 42862306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_xor, KF_RCU) 42962306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_equal, KF_RCU) 43062306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_intersects, KF_RCU) 43162306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_subset, KF_RCU) 43262306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_empty, KF_RCU) 43362306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_full, KF_RCU) 43462306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_copy, KF_RCU) 43562306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_any_distribute, KF_RCU) 43662306a36Sopenharmony_ciBTF_ID_FLAGS(func, bpf_cpumask_any_and_distribute, KF_RCU) 43762306a36Sopenharmony_ciBTF_SET8_END(cpumask_kfunc_btf_ids) 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic const struct btf_kfunc_id_set cpumask_kfunc_set = { 44062306a36Sopenharmony_ci .owner = THIS_MODULE, 44162306a36Sopenharmony_ci .set = &cpumask_kfunc_btf_ids, 44262306a36Sopenharmony_ci}; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ciBTF_ID_LIST(cpumask_dtor_ids) 44562306a36Sopenharmony_ciBTF_ID(struct, bpf_cpumask) 44662306a36Sopenharmony_ciBTF_ID(func, bpf_cpumask_release) 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic int __init cpumask_kfunc_init(void) 44962306a36Sopenharmony_ci{ 45062306a36Sopenharmony_ci int ret; 45162306a36Sopenharmony_ci const struct btf_id_dtor_kfunc cpumask_dtors[] = { 45262306a36Sopenharmony_ci { 45362306a36Sopenharmony_ci .btf_id = cpumask_dtor_ids[0], 45462306a36Sopenharmony_ci .kfunc_btf_id = cpumask_dtor_ids[1] 45562306a36Sopenharmony_ci }, 45662306a36Sopenharmony_ci }; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci ret = bpf_mem_alloc_init(&bpf_cpumask_ma, sizeof(struct bpf_cpumask), false); 45962306a36Sopenharmony_ci ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &cpumask_kfunc_set); 46062306a36Sopenharmony_ci ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &cpumask_kfunc_set); 46162306a36Sopenharmony_ci return ret ?: register_btf_id_dtor_kfuncs(cpumask_dtors, 46262306a36Sopenharmony_ci ARRAY_SIZE(cpumask_dtors), 46362306a36Sopenharmony_ci THIS_MODULE); 46462306a36Sopenharmony_ci} 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_cilate_initcall(cpumask_kfunc_init); 467