xref: /kernel/linux/linux-6.6/kernel/bpf/cpumask.c (revision 62306a36)
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