mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Some bpf_cpumask-related kfuncs have kdoc strings that are missing return values. Add a the missing descriptions for the return values. Reported-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Emil Tsalapatis (Meta) <emil@etsalapatis.com> Acked-by: Hou Tao <houtao1@huawei.com> Link: https://lore.kernel.org/r/20250309230427.26603-4-emil@etsalapatis.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
		
			
				
	
	
		
			534 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			534 lines
		
	
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0-only
 | 
						|
/* Copyright (c) 2023 Meta, Inc */
 | 
						|
#include <linux/bpf.h>
 | 
						|
#include <linux/bpf_mem_alloc.h>
 | 
						|
#include <linux/btf.h>
 | 
						|
#include <linux/btf_ids.h>
 | 
						|
#include <linux/cpumask.h>
 | 
						|
 | 
						|
/**
 | 
						|
 * struct bpf_cpumask - refcounted BPF cpumask wrapper structure
 | 
						|
 * @cpumask:	The actual cpumask embedded in the struct.
 | 
						|
 * @usage:	Object reference counter. When the refcount goes to 0, the
 | 
						|
 *		memory is released back to the BPF allocator, which provides
 | 
						|
 *		RCU safety.
 | 
						|
 *
 | 
						|
 * Note that we explicitly embed a cpumask_t rather than a cpumask_var_t.  This
 | 
						|
 * is done to avoid confusing the verifier due to the typedef of cpumask_var_t
 | 
						|
 * changing depending on whether CONFIG_CPUMASK_OFFSTACK is defined or not. See
 | 
						|
 * the details in <linux/cpumask.h>. The consequence is that this structure is
 | 
						|
 * likely a bit larger than it needs to be when CONFIG_CPUMASK_OFFSTACK is
 | 
						|
 * defined due to embedding the whole NR_CPUS-size bitmap, but the extra memory
 | 
						|
 * overhead is minimal. For the more typical case of CONFIG_CPUMASK_OFFSTACK
 | 
						|
 * not being defined, the structure is the same size regardless.
 | 
						|
 */
 | 
						|
struct bpf_cpumask {
 | 
						|
	cpumask_t cpumask;
 | 
						|
	refcount_t usage;
 | 
						|
};
 | 
						|
 | 
						|
static struct bpf_mem_alloc bpf_cpumask_ma;
 | 
						|
 | 
						|
static bool cpu_valid(u32 cpu)
 | 
						|
{
 | 
						|
	return cpu < nr_cpu_ids;
 | 
						|
}
 | 
						|
 | 
						|
__bpf_kfunc_start_defs();
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_create() - Create a mutable BPF cpumask.
 | 
						|
 *
 | 
						|
 * Allocates a cpumask that can be queried, mutated, acquired, and released by
 | 
						|
 * a BPF program. The cpumask returned by this function must either be embedded
 | 
						|
 * in a map as a kptr, or freed with bpf_cpumask_release().
 | 
						|
 *
 | 
						|
 * bpf_cpumask_create() allocates memory using the BPF memory allocator, and
 | 
						|
 * will not block. It may return NULL if no memory is available.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * A pointer to a new struct bpf_cpumask instance on success.
 | 
						|
 * * NULL if the BPF memory allocator is out of memory.
 | 
						|
 */
 | 
						|
__bpf_kfunc struct bpf_cpumask *bpf_cpumask_create(void)
 | 
						|
{
 | 
						|
	struct bpf_cpumask *cpumask;
 | 
						|
 | 
						|
	/* cpumask must be the first element so struct bpf_cpumask be cast to struct cpumask. */
 | 
						|
	BUILD_BUG_ON(offsetof(struct bpf_cpumask, cpumask) != 0);
 | 
						|
 | 
						|
	cpumask = bpf_mem_cache_alloc(&bpf_cpumask_ma);
 | 
						|
	if (!cpumask)
 | 
						|
		return NULL;
 | 
						|
 | 
						|
	memset(cpumask, 0, sizeof(*cpumask));
 | 
						|
	refcount_set(&cpumask->usage, 1);
 | 
						|
 | 
						|
	return cpumask;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_acquire() - Acquire a reference to a BPF cpumask.
 | 
						|
 * @cpumask: The BPF cpumask being acquired. The cpumask must be a trusted
 | 
						|
 *	     pointer.
 | 
						|
 *
 | 
						|
 * Acquires a reference to a BPF cpumask. The cpumask returned by this function
 | 
						|
 * must either be embedded in a map as a kptr, or freed with
 | 
						|
 * bpf_cpumask_release().
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * The struct bpf_cpumask pointer passed to the function.
 | 
						|
 *
 | 
						|
 */
 | 
						|
__bpf_kfunc struct bpf_cpumask *bpf_cpumask_acquire(struct bpf_cpumask *cpumask)
 | 
						|
{
 | 
						|
	refcount_inc(&cpumask->usage);
 | 
						|
	return cpumask;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_release() - Release a previously acquired BPF cpumask.
 | 
						|
 * @cpumask: The cpumask being released.
 | 
						|
 *
 | 
						|
 * Releases a previously acquired reference to a BPF cpumask. When the final
 | 
						|
 * reference of the BPF cpumask has been released, it is subsequently freed in
 | 
						|
 * an RCU callback in the BPF memory allocator.
 | 
						|
 */
 | 
						|
__bpf_kfunc void bpf_cpumask_release(struct bpf_cpumask *cpumask)
 | 
						|
{
 | 
						|
	if (!refcount_dec_and_test(&cpumask->usage))
 | 
						|
		return;
 | 
						|
 | 
						|
	bpf_mem_cache_free_rcu(&bpf_cpumask_ma, cpumask);
 | 
						|
}
 | 
						|
 | 
						|
__bpf_kfunc void bpf_cpumask_release_dtor(void *cpumask)
 | 
						|
{
 | 
						|
	bpf_cpumask_release(cpumask);
 | 
						|
}
 | 
						|
CFI_NOSEAL(bpf_cpumask_release_dtor);
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_first() - Get the index of the first nonzero bit in the cpumask.
 | 
						|
 * @cpumask: The cpumask being queried.
 | 
						|
 *
 | 
						|
 * Find the index of the first nonzero bit of the cpumask. A struct bpf_cpumask
 | 
						|
 * pointer may be safely passed to this function.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * The index of the first nonzero bit in the struct cpumask.
 | 
						|
 */
 | 
						|
__bpf_kfunc u32 bpf_cpumask_first(const struct cpumask *cpumask)
 | 
						|
{
 | 
						|
	return cpumask_first(cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_first_zero() - Get the index of the first unset bit in the
 | 
						|
 *			      cpumask.
 | 
						|
 * @cpumask: The cpumask being queried.
 | 
						|
 *
 | 
						|
 * Find the index of the first unset bit of the cpumask. A struct bpf_cpumask
 | 
						|
 * pointer may be safely passed to this function.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * The index of the first zero bit in the struct cpumask.
 | 
						|
 */
 | 
						|
__bpf_kfunc u32 bpf_cpumask_first_zero(const struct cpumask *cpumask)
 | 
						|
{
 | 
						|
	return cpumask_first_zero(cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_first_and() - Return the index of the first nonzero bit from the
 | 
						|
 *			     AND of two cpumasks.
 | 
						|
 * @src1: The first cpumask.
 | 
						|
 * @src2: The second cpumask.
 | 
						|
 *
 | 
						|
 * Find the index of the first nonzero bit of the AND of two cpumasks.
 | 
						|
 * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * The index of the first bit that is nonzero in both cpumask instances.
 | 
						|
 */
 | 
						|
__bpf_kfunc u32 bpf_cpumask_first_and(const struct cpumask *src1,
 | 
						|
				      const struct cpumask *src2)
 | 
						|
{
 | 
						|
	return cpumask_first_and(src1, src2);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_set_cpu() - Set a bit for a CPU in a BPF cpumask.
 | 
						|
 * @cpu: The CPU to be set in the cpumask.
 | 
						|
 * @cpumask: The BPF cpumask in which a bit is being set.
 | 
						|
 */
 | 
						|
__bpf_kfunc void bpf_cpumask_set_cpu(u32 cpu, struct bpf_cpumask *cpumask)
 | 
						|
{
 | 
						|
	if (!cpu_valid(cpu))
 | 
						|
		return;
 | 
						|
 | 
						|
	cpumask_set_cpu(cpu, (struct cpumask *)cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_clear_cpu() - Clear a bit for a CPU in a BPF cpumask.
 | 
						|
 * @cpu: The CPU to be cleared from the cpumask.
 | 
						|
 * @cpumask: The BPF cpumask in which a bit is being cleared.
 | 
						|
 */
 | 
						|
__bpf_kfunc void bpf_cpumask_clear_cpu(u32 cpu, struct bpf_cpumask *cpumask)
 | 
						|
{
 | 
						|
	if (!cpu_valid(cpu))
 | 
						|
		return;
 | 
						|
 | 
						|
	cpumask_clear_cpu(cpu, (struct cpumask *)cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_test_cpu() - Test whether a CPU is set in a cpumask.
 | 
						|
 * @cpu: The CPU being queried for.
 | 
						|
 * @cpumask: The cpumask being queried for containing a CPU.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * true  - @cpu is set in the cpumask
 | 
						|
 * * false - @cpu was not set in the cpumask, or @cpu is an invalid cpu.
 | 
						|
 */
 | 
						|
__bpf_kfunc bool bpf_cpumask_test_cpu(u32 cpu, const struct cpumask *cpumask)
 | 
						|
{
 | 
						|
	if (!cpu_valid(cpu))
 | 
						|
		return false;
 | 
						|
 | 
						|
	return cpumask_test_cpu(cpu, (struct cpumask *)cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_test_and_set_cpu() - Atomically test and set a CPU in a BPF cpumask.
 | 
						|
 * @cpu: The CPU being set and queried for.
 | 
						|
 * @cpumask: The BPF cpumask being set and queried for containing a CPU.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * true  - @cpu is set in the cpumask
 | 
						|
 * * false - @cpu was not set in the cpumask, or @cpu is invalid.
 | 
						|
 */
 | 
						|
__bpf_kfunc bool bpf_cpumask_test_and_set_cpu(u32 cpu, struct bpf_cpumask *cpumask)
 | 
						|
{
 | 
						|
	if (!cpu_valid(cpu))
 | 
						|
		return false;
 | 
						|
 | 
						|
	return cpumask_test_and_set_cpu(cpu, (struct cpumask *)cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_test_and_clear_cpu() - Atomically test and clear a CPU in a BPF
 | 
						|
 *				      cpumask.
 | 
						|
 * @cpu: The CPU being cleared and queried for.
 | 
						|
 * @cpumask: The BPF cpumask being cleared and queried for containing a CPU.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * true  - @cpu is set in the cpumask
 | 
						|
 * * false - @cpu was not set in the cpumask, or @cpu is invalid.
 | 
						|
 */
 | 
						|
__bpf_kfunc bool bpf_cpumask_test_and_clear_cpu(u32 cpu, struct bpf_cpumask *cpumask)
 | 
						|
{
 | 
						|
	if (!cpu_valid(cpu))
 | 
						|
		return false;
 | 
						|
 | 
						|
	return cpumask_test_and_clear_cpu(cpu, (struct cpumask *)cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_setall() - Set all of the bits in a BPF cpumask.
 | 
						|
 * @cpumask: The BPF cpumask having all of its bits set.
 | 
						|
 */
 | 
						|
__bpf_kfunc void bpf_cpumask_setall(struct bpf_cpumask *cpumask)
 | 
						|
{
 | 
						|
	cpumask_setall((struct cpumask *)cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_clear() - Clear all of the bits in a BPF cpumask.
 | 
						|
 * @cpumask: The BPF cpumask being cleared.
 | 
						|
 */
 | 
						|
__bpf_kfunc void bpf_cpumask_clear(struct bpf_cpumask *cpumask)
 | 
						|
{
 | 
						|
	cpumask_clear((struct cpumask *)cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_and() - AND two cpumasks and store the result.
 | 
						|
 * @dst: The BPF cpumask where the result is being stored.
 | 
						|
 * @src1: The first input.
 | 
						|
 * @src2: The second input.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * true  - @dst has at least one bit set following the operation
 | 
						|
 * * false - @dst is empty following the operation
 | 
						|
 *
 | 
						|
 * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
 | 
						|
 */
 | 
						|
__bpf_kfunc bool bpf_cpumask_and(struct bpf_cpumask *dst,
 | 
						|
				 const struct cpumask *src1,
 | 
						|
				 const struct cpumask *src2)
 | 
						|
{
 | 
						|
	return cpumask_and((struct cpumask *)dst, src1, src2);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_or() - OR two cpumasks and store the result.
 | 
						|
 * @dst: The BPF cpumask where the result is being stored.
 | 
						|
 * @src1: The first input.
 | 
						|
 * @src2: The second input.
 | 
						|
 *
 | 
						|
 * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
 | 
						|
 */
 | 
						|
__bpf_kfunc void bpf_cpumask_or(struct bpf_cpumask *dst,
 | 
						|
				const struct cpumask *src1,
 | 
						|
				const struct cpumask *src2)
 | 
						|
{
 | 
						|
	cpumask_or((struct cpumask *)dst, src1, src2);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_xor() - XOR two cpumasks and store the result.
 | 
						|
 * @dst: The BPF cpumask where the result is being stored.
 | 
						|
 * @src1: The first input.
 | 
						|
 * @src2: The second input.
 | 
						|
 *
 | 
						|
 * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
 | 
						|
 */
 | 
						|
__bpf_kfunc void bpf_cpumask_xor(struct bpf_cpumask *dst,
 | 
						|
				 const struct cpumask *src1,
 | 
						|
				 const struct cpumask *src2)
 | 
						|
{
 | 
						|
	cpumask_xor((struct cpumask *)dst, src1, src2);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_equal() - Check two cpumasks for equality.
 | 
						|
 * @src1: The first input.
 | 
						|
 * @src2: The second input.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * true   - @src1 and @src2 have the same bits set.
 | 
						|
 * * false  - @src1 and @src2 differ in at least one bit.
 | 
						|
 *
 | 
						|
 * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
 | 
						|
 */
 | 
						|
__bpf_kfunc bool bpf_cpumask_equal(const struct cpumask *src1, const struct cpumask *src2)
 | 
						|
{
 | 
						|
	return cpumask_equal(src1, src2);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_intersects() - Check two cpumasks for overlap.
 | 
						|
 * @src1: The first input.
 | 
						|
 * @src2: The second input.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * true   - @src1 and @src2 have at least one of the same bits set.
 | 
						|
 * * false  - @src1 and @src2 don't have any of the same bits set.
 | 
						|
 *
 | 
						|
 * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
 | 
						|
 */
 | 
						|
__bpf_kfunc bool bpf_cpumask_intersects(const struct cpumask *src1, const struct cpumask *src2)
 | 
						|
{
 | 
						|
	return cpumask_intersects(src1, src2);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_subset() - Check if a cpumask is a subset of another.
 | 
						|
 * @src1: The first cpumask being checked as a subset.
 | 
						|
 * @src2: The second cpumask being checked as a superset.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * true   - All of the bits of @src1 are set in @src2.
 | 
						|
 * * false  - At least one bit in @src1 is not set in @src2.
 | 
						|
 *
 | 
						|
 * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
 | 
						|
 */
 | 
						|
__bpf_kfunc bool bpf_cpumask_subset(const struct cpumask *src1, const struct cpumask *src2)
 | 
						|
{
 | 
						|
	return cpumask_subset(src1, src2);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_empty() - Check if a cpumask is empty.
 | 
						|
 * @cpumask: The cpumask being checked.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * true   - None of the bits in @cpumask are set.
 | 
						|
 * * false  - At least one bit in @cpumask is set.
 | 
						|
 *
 | 
						|
 * A struct bpf_cpumask pointer may be safely passed to @cpumask.
 | 
						|
 */
 | 
						|
__bpf_kfunc bool bpf_cpumask_empty(const struct cpumask *cpumask)
 | 
						|
{
 | 
						|
	return cpumask_empty(cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_full() - Check if a cpumask has all bits set.
 | 
						|
 * @cpumask: The cpumask being checked.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * true   - All of the bits in @cpumask are set.
 | 
						|
 * * false  - At least one bit in @cpumask is cleared.
 | 
						|
 *
 | 
						|
 * A struct bpf_cpumask pointer may be safely passed to @cpumask.
 | 
						|
 */
 | 
						|
__bpf_kfunc bool bpf_cpumask_full(const struct cpumask *cpumask)
 | 
						|
{
 | 
						|
	return cpumask_full(cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_copy() - Copy the contents of a cpumask into a BPF cpumask.
 | 
						|
 * @dst: The BPF cpumask being copied into.
 | 
						|
 * @src: The cpumask being copied.
 | 
						|
 *
 | 
						|
 * A struct bpf_cpumask pointer may be safely passed to @src.
 | 
						|
 */
 | 
						|
__bpf_kfunc void bpf_cpumask_copy(struct bpf_cpumask *dst, const struct cpumask *src)
 | 
						|
{
 | 
						|
	cpumask_copy((struct cpumask *)dst, src);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_any_distribute() - Return a random set CPU from a cpumask.
 | 
						|
 * @cpumask: The cpumask being queried.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * A random set bit within [0, num_cpus) if at least one bit is set.
 | 
						|
 * * >= num_cpus if no bit is set.
 | 
						|
 *
 | 
						|
 * A struct bpf_cpumask pointer may be safely passed to @src.
 | 
						|
 */
 | 
						|
__bpf_kfunc u32 bpf_cpumask_any_distribute(const struct cpumask *cpumask)
 | 
						|
{
 | 
						|
	return cpumask_any_distribute(cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_any_and_distribute() - Return a random set CPU from the AND of
 | 
						|
 *				      two cpumasks.
 | 
						|
 * @src1: The first cpumask.
 | 
						|
 * @src2: The second cpumask.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * A random set bit within [0, num_cpus) from the AND of two cpumasks, if at
 | 
						|
 *   least one bit is set.
 | 
						|
 * * >= num_cpus if no bit is set.
 | 
						|
 *
 | 
						|
 * struct bpf_cpumask pointers may be safely passed to @src1 and @src2.
 | 
						|
 */
 | 
						|
__bpf_kfunc u32 bpf_cpumask_any_and_distribute(const struct cpumask *src1,
 | 
						|
					       const struct cpumask *src2)
 | 
						|
{
 | 
						|
	return cpumask_any_and_distribute(src1, src2);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_weight() - Return the number of bits in @cpumask.
 | 
						|
 * @cpumask: The cpumask being queried.
 | 
						|
 *
 | 
						|
 * Count the number of set bits in the given cpumask.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * The number of bits set in the mask.
 | 
						|
 */
 | 
						|
__bpf_kfunc u32 bpf_cpumask_weight(const struct cpumask *cpumask)
 | 
						|
{
 | 
						|
	return cpumask_weight(cpumask);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * bpf_cpumask_populate() - Populate the CPU mask from the contents of
 | 
						|
 * a BPF memory region.
 | 
						|
 *
 | 
						|
 * @cpumask: The cpumask being populated.
 | 
						|
 * @src: The BPF memory holding the bit pattern.
 | 
						|
 * @src__sz: Length of the BPF memory region in bytes.
 | 
						|
 *
 | 
						|
 * Return:
 | 
						|
 * * 0 if the struct cpumask * instance was populated successfully.
 | 
						|
 * * -EACCES if the memory region is too small to populate the cpumask.
 | 
						|
 * * -EINVAL if the memory region is not aligned to the size of a long
 | 
						|
 *   and the architecture does not support efficient unaligned accesses.
 | 
						|
 */
 | 
						|
__bpf_kfunc int bpf_cpumask_populate(struct cpumask *cpumask, void *src, size_t src__sz)
 | 
						|
{
 | 
						|
	unsigned long source = (unsigned long)src;
 | 
						|
 | 
						|
	/* The memory region must be large enough to populate the entire CPU mask. */
 | 
						|
	if (src__sz < bitmap_size(nr_cpu_ids))
 | 
						|
		return -EACCES;
 | 
						|
 | 
						|
	/* If avoiding unaligned accesses, the input region must be aligned to the nearest long. */
 | 
						|
	if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) &&
 | 
						|
		!IS_ALIGNED(source, sizeof(long)))
 | 
						|
		return -EINVAL;
 | 
						|
 | 
						|
	bitmap_copy(cpumask_bits(cpumask), src, nr_cpu_ids);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
__bpf_kfunc_end_defs();
 | 
						|
 | 
						|
BTF_KFUNCS_START(cpumask_kfunc_btf_ids)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_create, KF_ACQUIRE | KF_RET_NULL)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_release, KF_RELEASE)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_acquire, KF_ACQUIRE | KF_TRUSTED_ARGS)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_first, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_first_zero, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_first_and, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_set_cpu, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_clear_cpu, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_test_cpu, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_test_and_set_cpu, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_test_and_clear_cpu, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_setall, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_clear, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_and, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_or, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_xor, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_equal, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_intersects, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_subset, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_empty, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_full, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_copy, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_any_distribute, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_any_and_distribute, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_weight, KF_RCU)
 | 
						|
BTF_ID_FLAGS(func, bpf_cpumask_populate, KF_RCU)
 | 
						|
BTF_KFUNCS_END(cpumask_kfunc_btf_ids)
 | 
						|
 | 
						|
static const struct btf_kfunc_id_set cpumask_kfunc_set = {
 | 
						|
	.owner = THIS_MODULE,
 | 
						|
	.set   = &cpumask_kfunc_btf_ids,
 | 
						|
};
 | 
						|
 | 
						|
BTF_ID_LIST(cpumask_dtor_ids)
 | 
						|
BTF_ID(struct, bpf_cpumask)
 | 
						|
BTF_ID(func, bpf_cpumask_release_dtor)
 | 
						|
 | 
						|
static int __init cpumask_kfunc_init(void)
 | 
						|
{
 | 
						|
	int ret;
 | 
						|
	const struct btf_id_dtor_kfunc cpumask_dtors[] = {
 | 
						|
		{
 | 
						|
			.btf_id	      = cpumask_dtor_ids[0],
 | 
						|
			.kfunc_btf_id = cpumask_dtor_ids[1]
 | 
						|
		},
 | 
						|
	};
 | 
						|
 | 
						|
	ret = bpf_mem_alloc_init(&bpf_cpumask_ma, sizeof(struct bpf_cpumask), false);
 | 
						|
	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &cpumask_kfunc_set);
 | 
						|
	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, &cpumask_kfunc_set);
 | 
						|
	ret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &cpumask_kfunc_set);
 | 
						|
	return  ret ?: register_btf_id_dtor_kfuncs(cpumask_dtors,
 | 
						|
						   ARRAY_SIZE(cpumask_dtors),
 | 
						|
						   THIS_MODULE);
 | 
						|
}
 | 
						|
 | 
						|
late_initcall(cpumask_kfunc_init);
 |