summaryrefslogtreecommitdiff
path: root/rust/kernel/alloc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-06-15 09:25:48 +0530
committerLinus Torvalds <torvalds@linux-foundation.org>2026-06-15 09:25:48 +0530
commitb079329b8691768962aa514b8f8c9077ca352459 (patch)
treebfa889319f6a8174e3cdf84e339c45f76f93bdd3 /rust/kernel/alloc
parentb8b674748fa4b1a384aaa647811109fe9007c0a4 (diff)
parent48b375e482027ba6566107cec40c1b21b453fa4e (diff)
Merge tag 'rust-7.2' of gitolite.kernel.org:pub/scm/linux/kernel/git/ojeda/linux
Pull Rust updates from Miguel Ojeda: "This one is big due to the vendoring of the `zerocopy` library, which allows us to replace a bunch of `unsafe` code dealing with conversions between byte sequences and other types with safe alternatives. More details on that below (and in its merge commit). Toolchain and infrastructure: - Introduce support for the 'zerocopy' library [1][2]: Fast, safe, compile error. Pick two. Zerocopy makes zero-cost memory manipulation effortless. We write `unsafe` so you don't have to. It essentially provides derivable traits (e.g. 'FromBytes') and macros (e.g. 'transmute!') for safely converting between byte sequences and other types. Having such support allows us to remove some 'unsafe' code. It is among the most downloaded Rust crates and it is also used by the Rust compiler itself. It is licensed under "BSD-2-Clause OR Apache-2.0 OR MIT". The crates are imported essentially as-is (only +2/-3 lines needed to be adapted), plus SPDX identifiers. Upstream has since added the SPDX identifiers as well as one of the tweaks at my request, thus reducing our future diffs on updates -- I keep the details in one of our usual live lists [3]. In total, it is about ~39k lines added, ~32k without counting 'benches/' which are just for documentation purposes. The series includes a few Kbuild and rust-analyzer improvements and an example patch using it in Nova, removing one 'unsafe impl'. I checked that the codegen of an isolated example function (similar to the Nova patch on top) is essentially identical. It also turns out that (for that particular case) the 'zerocopy' version, even with 'debug-assertions' enabled, has no remaining panics, unlike a few in the current code (since the compiler can prove the remaining 'ub_checks' statically). So their "fast, safe" does indeed check out -- at least in that case. - Support AutoFDO. This allows Rust code to be profiled and optimized based on the profile. Tested with Rust Binder: ~13% slower without AutoFDO in the binderAddInts benchmark (using an app-launch benchmark for the profile). - Support Software Tag-Based KASAN. In addition, fix KASAN Kconfig by requiring Clang. - Add Kconfig options for each existing Rust KUnit test suite, such as 'CONFIG_RUST_BITMAP_KUNIT_TEST'. They are placed within a new menu, 'CONFIG_RUST_KUNIT_TESTS', in the new 'rust/kernel/Kconfig.test' file. - Support the upcoming Rust 1.98.0 release (expected 2026-08-20): lint cleanups and an unstable flag rename. - Disable 'rustdoc' documentation inlining for all prelude items, which bloats the generated documentation. - Ignore (in Git) and clean (in Kbuild) the (rarely) 'rustc'-generated '*.long-type-*.txt' files. 'kernel' crate: - Add new 'bitfield' module with the 'bitfield!' macro (extracted from the existing 'register!' one), which declares integer types that are split into distinct bit fields of arbitrary length. Each field is a 'Bounded' of the appropriate bit width (ensuring values are properly validated and avoiding implicit data loss) and gets several generated getters and setters (infallible, 'const' and fallible) as well as associated constants ('_MASK', '_SHIFT' and '_RANGE'). It also supports fields that can be converted from/to custom types, either fallibly ('?=>') or infallibly ('=>'). For instance: bitfield! { struct Rgb(u16) { 15:11 blue; 10:5 green; 4:0 red; } } // Compile-time checks. let color = Rgb::zeroed().with_const_green::<0x1f>(); assert_eq!(color.green(), 0x1f); assert_eq!(color.into_raw(), 0x1f << Rgb::GREEN_SHIFT); Add as well documentation and a test suite for it, as usual; and update the 'register!' macro to use it. It will be maintained by Alexandre Courbot (with Yury Norov as reviewer) under a new 'MAINTAINERS' entry: 'RUST [BITFIELD]'. - 'ptr' module: rework index projection syntax into keyworded syntax and introduce panicking variant. The keyword syntax ('build:', 'try:', 'panic:') is more explicit and paves the way of perhaps adding more flavors in the future, e.g. an 'unsafe' index projection. For instance, projections now look like this: fn f(p: *const [u8; 32]) -> Result { // Ok, within bounds, checked at build time. project!(p, [build: 1]); // Build error. project!(p, [build: 128]); // `OutOfBound` runtime error (convertible to `ERANGE`). project!(p, [try: 128]); // Runtime panic. project!(p, [panic: 128]); Ok(()) } Update as well the users, which now look like e.g. // Pointer to the first entry of the GSP message queue. let data = project!(self.0.as_ptr(), .gspq.msgq.data[build: 0]); - 'build_assert' module: make the module the home of its macros instead of rendering them twice. - 'sync' module: add 'UniqueArc::as_ptr()' associated function. - 'alloc' module: - Fix the 'Vec::reserve()' doctest to properly account for the existing vector length in the capacity assertion. - Fix an incorrect operator in the 'Vec::extend_with()' 'SAFETY' comment; add a doc test demonstrating basic usage and the zero-length case. - Clean imports across several modules to follow the "kernel vertical" import style in order to minimize conflicts. 'pin-init' crate: - User visible changes: - Do not generate 'non_snake_case' warnings for identifiers that are syntactically just users of a field name. This would allow all '#[allow(non_snake_case)]' in nova-core to be removed, which Gary will send to the nova tree next cycle. - Filter non-cfg attributes out properly in derived structs. This improves pin-init compatibility with other derive macros. - Insert projection types' where clause properly. - Other changes: - Bump MSRV to 1.82, plus associated cleanups. - Overhaul how init slots are projected. The new approach is easier to justify with safety comments. - Mark more functions as inline, which should help mitigate the super-long symbol name issue due to lack of inlining. rust-analyzer: - Support '--envs' for passing env vars for crates like 'zerocopy'. 'MAINTAINERS': - Add the following reviewers to the 'RUST' entry: - Daniel Almeida - Tamir Duberstein - Alexandre Courbot - Onur Özkan They have been involved in the Rust for Linux project for about 7 collective years and bring expertise across several domains, which will be very useful to have around in the future. Thanks everyone for stepping up! And some other fixes, cleanups and improvements" Link: https://github.com/google/zerocopy [1] Link: https://docs.rs/zerocopy [2] Link: https://github.com/Rust-for-Linux/linux/issues/1239 [3] * tag 'rust-7.2' of gitolite.kernel.org:pub/scm/linux/kernel/git/ojeda/linux: (86 commits) MAINTAINERS: add Onur Özkan as Rust reviewer MAINTAINERS: add Alexandre Courbot as Rust reviewer MAINTAINERS: add Tamir Duberstein as Rust reviewer MAINTAINERS: add Daniel Almeida as Rust reviewer kbuild: rust: clean `zerocopy-derive` in `mrproper` rust: make `build_assert` module the home of related macros rust: str: clean unused import for Rust >= 1.98 rust: str: use the "kernel vertical" imports style rust: aref: use the "kernel vertical" imports style rust: page: use the "kernel vertical" imports style gpu: nova-core: firmware: parse `FalconUCodeDescV2` via `zerocopy` rust: prelude: add `zerocopy{,_derive}::FromBytes` rust: zerocopy-derive: enable support in kbuild rust: zerocopy-derive: add `README.md` rust: zerocopy-derive: avoid generating non-ASCII identifiers rust: zerocopy-derive: add SPDX License Identifiers rust: zerocopy-derive: import crate rust: zerocopy: enable support in kbuild rust: zerocopy: add `README.md` rust: zerocopy: remove float `Display` support ...
Diffstat (limited to 'rust/kernel/alloc')
-rw-r--r--rust/kernel/alloc/allocator.rs35
-rw-r--r--rust/kernel/alloc/allocator/iter.rs8
-rw-r--r--rust/kernel/alloc/kbox.rs78
-rw-r--r--rust/kernel/alloc/kvec.rs82
-rw-r--r--rust/kernel/alloc/kvec/errors.rs6
-rw-r--r--rust/kernel/alloc/layout.rs10
6 files changed, 161 insertions, 58 deletions
diff --git a/rust/kernel/alloc/allocator.rs b/rust/kernel/alloc/allocator.rs
index 63bfb91b3671..cd4203f27aed 100644
--- a/rust/kernel/alloc/allocator.rs
+++ b/rust/kernel/alloc/allocator.rs
@@ -8,14 +8,25 @@
//!
//! Reference: <https://docs.kernel.org/core-api/memory-allocation.html>
-use super::Flags;
-use core::alloc::Layout;
-use core::ptr;
-use core::ptr::NonNull;
-
-use crate::alloc::{AllocError, Allocator, NumaNode};
-use crate::bindings;
-use crate::page;
+use super::{
+ AllocError,
+ Allocator,
+ Flags,
+ NumaNode, //
+};
+
+use crate::{
+ bindings,
+ page, //
+};
+
+use core::{
+ alloc::Layout,
+ ptr::{
+ self,
+ NonNull, //
+ }, //
+};
const ARCH_KMALLOC_MINALIGN: usize = bindings::ARCH_KMALLOC_MINALIGN;
@@ -163,8 +174,11 @@ impl Vmalloc {
/// # Examples
///
/// ```
- /// # use core::ptr::{NonNull, from_mut};
- /// # use kernel::{page, prelude::*};
+ /// # use core::ptr::{
+ /// # from_mut,
+ /// # NonNull, //
+ /// # };
+ /// # use kernel::page;
/// use kernel::alloc::allocator::Vmalloc;
///
/// let mut vbox = VBox::<[u8; page::PAGE_SIZE]>::new_uninit(GFP_KERNEL)?;
@@ -251,6 +265,7 @@ unsafe impl Allocator for KVmalloc {
}
}
+#[cfg(CONFIG_RUST_ALLOCATOR_KUNIT_TEST)]
#[macros::kunit_tests(rust_allocator)]
mod tests {
use super::*;
diff --git a/rust/kernel/alloc/allocator/iter.rs b/rust/kernel/alloc/allocator/iter.rs
index e0a70b7a744a..02fda3ea5cae 100644
--- a/rust/kernel/alloc/allocator/iter.rs
+++ b/rust/kernel/alloc/allocator/iter.rs
@@ -1,9 +1,13 @@
// SPDX-License-Identifier: GPL-2.0
use super::Vmalloc;
+
use crate::page;
-use core::marker::PhantomData;
-use core::ptr::NonNull;
+
+use core::{
+ marker::PhantomData,
+ ptr::NonNull, //
+};
/// An [`Iterator`] of [`page::BorrowedPage`] items owned by a [`Vmalloc`] allocation.
///
diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index bd6da02c7ab8..80eb39364e86 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -3,24 +3,47 @@
//! Implementation of [`Box`].
#[allow(unused_imports)] // Used in doc comments.
-use super::allocator::{KVmalloc, Kmalloc, Vmalloc, VmallocPageIter};
-use super::{AllocError, Allocator, Flags, NumaNode};
-use core::alloc::Layout;
-use core::borrow::{Borrow, BorrowMut};
-use core::marker::PhantomData;
-use core::mem::ManuallyDrop;
-use core::mem::MaybeUninit;
-use core::ops::{Deref, DerefMut};
-use core::pin::Pin;
-use core::ptr::NonNull;
-use core::result::Result;
-
-use crate::ffi::c_void;
-use crate::fmt;
-use crate::init::InPlaceInit;
-use crate::page::AsPageIter;
-use crate::types::ForeignOwnable;
-use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption};
+use super::allocator::{
+ KVmalloc,
+ Kmalloc,
+ Vmalloc,
+ VmallocPageIter, //
+};
+
+use super::{
+ AllocError,
+ Allocator,
+ Flags,
+ NumaNode, //
+};
+
+use crate::{
+ fmt,
+ page::AsPageIter,
+ prelude::*,
+ types::ForeignOwnable, //
+};
+
+use core::{
+ alloc::Layout,
+ borrow::{
+ Borrow,
+ BorrowMut, //
+ },
+ marker::PhantomData,
+ mem::{
+ ManuallyDrop,
+ MaybeUninit, //
+ },
+ ops::{
+ Deref,
+ DerefMut, //
+ },
+ ptr::NonNull,
+ result::Result, //
+};
+
+use pin_init::ZeroableOption;
/// The kernel's [`Box`] type -- a heap allocation for a single value of type `T`.
///
@@ -274,7 +297,10 @@ where
/// # Examples
///
/// ```
- /// use kernel::sync::{new_spinlock, SpinLock};
+ /// use kernel::sync::{
+ /// new_spinlock,
+ /// SpinLock, //
+ /// };
///
/// struct Inner {
/// a: u32,
@@ -411,6 +437,7 @@ where
{
type Initialized = Box<T, A>;
+ #[inline]
fn write_init<E>(mut self, init: impl Init<T, E>) -> Result<Self::Initialized, E> {
let slot = self.as_mut_ptr();
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
@@ -420,6 +447,7 @@ where
Ok(unsafe { Box::assume_init(self) })
}
+ #[inline]
fn write_pin_init<E>(mut self, init: impl PinInit<T, E>) -> Result<Pin<Self::Initialized>, E> {
let slot = self.as_mut_ptr();
// SAFETY: When init errors/panics, slot will get deallocated but not dropped,
@@ -567,7 +595,6 @@ where
///
/// ```
/// # use core::borrow::Borrow;
-/// # use kernel::alloc::KBox;
/// struct Foo<B: Borrow<u32>>(B);
///
/// // Owned instance.
@@ -595,7 +622,6 @@ where
///
/// ```
/// # use core::borrow::BorrowMut;
-/// # use kernel::alloc::KBox;
/// struct Foo<B: BorrowMut<u32>>(B);
///
/// // Owned instance.
@@ -660,9 +686,13 @@ where
/// # Examples
///
/// ```
-/// # use kernel::prelude::*;
-/// use kernel::alloc::allocator::VmallocPageIter;
-/// use kernel::page::{AsPageIter, PAGE_SIZE};
+/// use kernel::{
+/// alloc::allocator::VmallocPageIter,
+/// page::{
+/// AsPageIter,
+/// PAGE_SIZE, //
+/// }, //
+/// };
///
/// let mut vbox = VBox::new((), GFP_KERNEL)?;
///
diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index 6438385e4322..f7af62835aa8 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -3,29 +3,52 @@
//! Implementation of [`Vec`].
use super::{
- allocator::{KVmalloc, Kmalloc, Vmalloc, VmallocPageIter},
+ allocator::{
+ KVmalloc,
+ Kmalloc,
+ Vmalloc,
+ VmallocPageIter, //
+ },
layout::ArrayLayout,
- AllocError, Allocator, Box, Flags, NumaNode,
+ AllocError,
+ Allocator,
+ Box,
+ Flags,
+ NumaNode, //
};
+
use crate::{
fmt,
page::{
AsPageIter,
PAGE_SIZE, //
- },
+ }, //
};
+
use core::{
- borrow::{Borrow, BorrowMut},
+ borrow::{
+ Borrow,
+ BorrowMut, //
+ },
marker::PhantomData,
- mem::{ManuallyDrop, MaybeUninit},
- ops::Deref,
- ops::DerefMut,
- ops::Index,
- ops::IndexMut,
- ptr,
- ptr::NonNull,
- slice,
- slice::SliceIndex,
+ mem::{
+ ManuallyDrop,
+ MaybeUninit, //
+ },
+ ops::{
+ Deref,
+ DerefMut,
+ Index,
+ IndexMut, //
+ },
+ ptr::{
+ self,
+ NonNull, //
+ },
+ slice::{
+ self,
+ SliceIndex, //
+ }, //
};
mod errors;
@@ -614,7 +637,7 @@ where
///
/// v.reserve(10, GFP_KERNEL)?;
/// let cap = v.capacity();
- /// assert!(cap >= 10);
+ /// assert!(cap >= v.len() + 10);
///
/// v.reserve(10, GFP_KERNEL)?;
/// let new_cap = v.capacity();
@@ -849,6 +872,24 @@ impl<T> Vec<T, KVmalloc> {
impl<T: Clone, A: Allocator> Vec<T, A> {
/// Extend the vector by `n` clones of `value`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let mut v = KVec::new();
+ /// v.push(1, GFP_KERNEL)?;
+ ///
+ /// v.extend_with(3, 5, GFP_KERNEL)?;
+ /// assert_eq!(&v, &[1, 5, 5, 5]);
+ ///
+ /// v.extend_with(2, 8, GFP_KERNEL)?;
+ /// assert_eq!(&v, &[1, 5, 5, 5, 8, 8]);
+ ///
+ /// v.extend_with(0, 3, GFP_KERNEL)?;
+ /// assert_eq!(&v, &[1, 5, 5, 5, 8, 8]);
+ ///
+ /// # Ok::<(), Error>(())
+ /// ```
pub fn extend_with(&mut self, n: usize, value: T, flags: Flags) -> Result<(), AllocError> {
if n == 0 {
return Ok(());
@@ -866,7 +907,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
spare[n - 1].write(value);
// SAFETY:
- // - `self.len() + n < self.capacity()` due to the call to reserve above,
+ // - `self.len() + n <= self.capacity()` due to the call to reserve above,
// - the loop and the line above initialized the next `n` elements.
unsafe { self.inc_len(n) };
@@ -1146,9 +1187,13 @@ where
/// # Examples
///
/// ```
-/// # use kernel::prelude::*;
-/// use kernel::alloc::allocator::VmallocPageIter;
-/// use kernel::page::{AsPageIter, PAGE_SIZE};
+/// use kernel::{
+/// alloc::allocator::VmallocPageIter,
+/// page::{
+/// AsPageIter,
+/// PAGE_SIZE, //
+/// }, //
+/// };
///
/// let mut vec = VVec::<u8>::new();
///
@@ -1463,6 +1508,7 @@ impl<'vec, T> Drop for DrainAll<'vec, T> {
}
}
+#[cfg(CONFIG_RUST_KVEC_KUNIT_TEST)]
#[macros::kunit_tests(rust_kvec)]
mod tests {
use super::*;
diff --git a/rust/kernel/alloc/kvec/errors.rs b/rust/kernel/alloc/kvec/errors.rs
index 985c5f2c3962..aaca6446516a 100644
--- a/rust/kernel/alloc/kvec/errors.rs
+++ b/rust/kernel/alloc/kvec/errors.rs
@@ -2,8 +2,10 @@
//! Errors for the [`Vec`] type.
-use kernel::fmt;
-use kernel::prelude::*;
+use crate::{
+ fmt,
+ prelude::*, //
+};
/// Error type for [`Vec::push_within_capacity`].
pub struct PushError<T>(pub T);
diff --git a/rust/kernel/alloc/layout.rs b/rust/kernel/alloc/layout.rs
index 9f8be72feb7a..62a459c66baf 100644
--- a/rust/kernel/alloc/layout.rs
+++ b/rust/kernel/alloc/layout.rs
@@ -4,7 +4,10 @@
//!
//! Custom layout types extending or improving [`Layout`].
-use core::{alloc::Layout, marker::PhantomData};
+use core::{
+ alloc::Layout,
+ marker::PhantomData, //
+};
/// Error when constructing an [`ArrayLayout`].
pub struct LayoutError;
@@ -47,7 +50,10 @@ impl<T> ArrayLayout<T> {
/// # Examples
///
/// ```
- /// # use kernel::alloc::layout::{ArrayLayout, LayoutError};
+ /// # use kernel::alloc::layout::{
+ /// # ArrayLayout,
+ /// # LayoutError, //
+ /// # };
/// let layout = ArrayLayout::<i32>::new(15)?;
/// assert_eq!(layout.len(), 15);
///