[PATCH v5 0/8] rust: Add Per-CPU Variable API

Mitchell Levy
2026-04-10T21:36:25Z

This series adds an API for declaring and using per-CPU variables from
Rust, and it also adds support for Rust access to C per-CPU variables
(subject to some soundness requirements). It also adds a small sample
module, samples/rust/rust_percpu.rs, in the vein of lib/percpu_test.c.

---
Signed-off-by: Mitchell Levy <levymitchell0@gmail.com>

---
Changes in v5:
- Rebased
- Documentation clarifications, typo fixes
- Added an early out in `CpumaskIter::next` to avoid WARNs under certain
configs
- `CpuGuard` functions are now `#[inline]`
- `PerCpuNumeric`s now use `ptr::cast<$ty>` to get a `*mut $ty` rather than
`ptr::cast<*mut $ty` which gives a `*mut *mut $ty`.
- Changed `make_optimization_test!`'s `CpuGuard` to be bound to a name
rather than `_` to avoid it getting dropped immediately
- Remove `DynamicPerCpu::alloc` in patch 8 since it's not necessary at
that point
- `CheckedPerCpu::get` now has a `&self` reciever rather than a `&mut
reciever`.
- Consolidated the non-zeroable dynamic per-cpu support into the
introductory patches
- `CpuGuard`s were previously automatically `Send` and `Sync`, even
though that doesn't make sense for that type. So, added a
`PhantomData<*const ()>` to prevent those from automatically being
applied.
- Impl `FusedIterator` for the cpumask iterator
- Used the cached `self.ptr` in `DynamicPerCpu`'s `get` and `get_mut`
since there's no reason not to save the indirection.
- Added `$crate::percpu::` to `PerCpuSyncMarkerType` and
`StaticPerCpuSymbol` in the define_per_cpu! macro to avoid needing
extra imports where its used. (Thanks Andreas Hindborg)
- Cleaned up logic in `CpumaskIter::next` (Thanks Yury Norov)
- Link to v4: https://lore.kernel.org/r/20251105-rust-percpu-v4-0-984b1470adcb@gmail.com

Changes in v4:
- Split what was the first patch into three patches (Thanks Yury Norov)
- Add intra-doc links to rustdoc comments (Thanks Miguel Ojeda)
- `get_remote_ptr` is no longer unsafe (Thanks Miguel Ojeda)
- Renamed the CPU mask getters to be more clear (Thanks Yury Norov)
- Add an `ExternStaticPerCpuSymbol` type for static per-CPU variables
shared with C in order to make the extra soundness requirements for
these variables more explicit.
- Properly drop the contents of dynamically allocated per-CPUs when the
`DynamicPerCpu` is dropped, and properly document that
`PerCpuAllocation` does not handle dropping values in the allocation.
- Functions on the numeric token types are now `#[inline]`
- Safety requirements of `PerCpuPtr` functions now include the fact that
the pointed-to allocation must be live and appropriately laid out in
memory, and SAFETY comments of uses of these functions have been
updated to reflect these requirements.
- Included the cpumask patches first, since it might make sense for
these to be merged separately.
- Documentation improvements throughout.
- Link to v3: https://lore.kernel.org/r/20250828-rust-percpu-v3-0-4dd92e1e7904@gmail.com

Changes in v3:
- Add a `CheckedPerCpuToken` that enables usage of per-CPU variables via
a `&T`, allowing for a wholly safe interface when `T` allows for
interior mutability (Thanks Benno Lossin)
- Add support for non-zeroable types to be used in a `DynamicPerCpu`.
- Remove necessity for `unsafe` to get a `StaticPerCpu` from its
declaration (Thanks Benno Lossin)
- Allow the declaration of static per-CPU variables of types that are
`!Sync`.
- Implement `PerCpuPtr` in terms of `MaybeUninit<T>` rather than `T` so
as to keep all invariants in the `DynamicPerCpu` and `StaticPerCpu`
types --- this would also enable `PerCpuPtr` to be used in a per-CPU
type that does lazy initialization.
- Link to v2: https://lore.kernel.org/r/20250712-rust-percpu-v2-0-826f2567521b@gmail.com

Changes in v2:
- Fix kernel test robot issues
- Fix documentation error
- Require `T: Zeroable` in the dynamic case
- Link to v1: https://lore.kernel.org/r/20250624-rust-percpu-v1-0-9c59b07d2a9c@gmail.com

Changes in v1:
- Use wrapping_add in `PerCpuPtr::get_ref` since overflow is expected.
- Separate the dynamic and static cases, with shared logic in a
`PerCpuPtr` type.
- Implement pin-hole optimizations for numeric types
- Don't assume `GFP_KERNEL` when allocating the `Arc` in the dynamic
case.
- Link to RFC v2: https://lore.kernel.org/r/20250414-rust-percpu-v2-0-5ea0d0de13a5@gmail.com

Changes in RFC v2:
- Renamed PerCpuVariable to StaticPerCpuSymbol to be more descriptive
- Support dynamically allocated per-CPU variables via the
PerCpuAllocation type. Rework statically allocated variables to use
this new type.
- Make use of a token/closure-based API via the PerCpu and PerCpuToken
types, rather than an API based on PerCpuRef that automatically
Deref(Mut)'s into a &(mut) T.
- Rebased
- Link to RFC: https://lore.kernel.org/r/20241219-rust-percpu-v1-0-209117e822b1@gmail.com

---
Mitchell Levy (8):
rust: cpumask: Add a `Cpumask` iterator
rust: cpumask: Add getters for globally defined cpumasks
rust: percpu: Add C bindings for per-CPU variable API
rust: percpu: introduce a rust API for static per-CPU variables
rust: percpu: introduce a rust API for dynamic per-CPU variables
rust: percpu: add a rust per-CPU variable sample
rust: percpu: Add pin-hole optimizations for numerics
rust: percpu: cache per-CPU pointers in the dynamic case

rust/helpers/cpumask.c | 6 +
rust/helpers/helpers.c | 2 +
rust/helpers/percpu.c | 22 +++
rust/helpers/preempt.c | 15 ++
rust/kernel/cpumask.rs | 97 ++++++++++++-
rust/kernel/lib.rs | 3 +
rust/kernel/percpu.rs | 282 ++++++++++++++++++++++++++++++++++++
rust/kernel/percpu/cpu_guard.rs | 48 ++++++
rust/kernel/percpu/dynamic.rs | 227 +++++++++++++++++++++++++++++
rust/kernel/percpu/numeric.rs | 138 ++++++++++++++++++
rust/kernel/percpu/static_.rs | 218 ++++++++++++++++++++++++++++
samples/rust/Kconfig | 9 ++
samples/rust/Makefile | 1 +
samples/rust/rust_percpu.rs | 314 ++++++++++++++++++++++++++++++++++++++++
14 files changed, 1381 insertions(+), 1 deletion(-)
---
base-commit: 8a23051ed8584215b22368e9501f771ef98f0c1d
change-id: 20240813-rust-percpu-ea2f54b5da33

Best regards,
--
Mitchell Levy <levymitchell0@gmail.com>