Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'alloc-next-v6.18-2025-09-04' of https://github.com/Rust-for-Linux/linux into rust-next

Pull alloc and DMA updates from Danilo Krummrich:

Allocator:
- Provide information about the minimum alignment guarantees of
'Kmalloc', 'Vmalloc' and 'KVmalloc'.
- Take minimum alignment guarantees of allocators for
'ForeignOwnable' into account.
- Remove the 'allocator_test' incl. 'Cmalloc'.

Box:
- Implement 'Box::pin_slice()', which constructs a pinned slice of
elements.

Vec:
- Simplify KUnit test module name to 'rust_kvec'.
- Add doc-test for 'Vec::as_slice()'.
- Constify various methods.

DMA:
- Update 'ARef' and 'AlwaysRefCounted' imports.

MISC:
- Remove support for unused host '#[test]'s.
- Constify 'ArrayLayout::new_unchecked()'.

* tag 'alloc-next-v6.18-2025-09-04' of https://github.com/Rust-for-Linux/linux:
rust: alloc: remove `allocator_test`
rust: kernel: remove support for unused host `#[test]`s
rust: alloc: implement Box::pin_slice()
rust: alloc: add ARCH_KMALLOC_MINALIGN to bindgen blocklist
rust: dma: Update ARef and AlwaysRefCounted imports from sync::aref
rust: alloc: take the allocator into account for FOREIGN_ALIGN
rust: alloc: specify the minimum alignment of each allocator
rust: make `kvec::Vec` functions `const fn`
rust: make `ArrayLayout::new_unchecked` a `const fn`
rust: alloc: kvec: simplify KUnit test module name to "rust_kvec"
rust: alloc: kvec: add doc example for as_slice method

+130 -158
+1 -8
rust/Makefile
··· 248 248 $(objtree)/$(obj)/test/$(subst rusttest-,,$@) $(rust_test_quiet) \ 249 249 $(rustc_test_run_flags) 250 250 251 - rusttest: rusttest-macros rusttest-kernel 251 + rusttest: rusttest-macros 252 252 253 253 rusttest-macros: private rustc_target_flags = --extern proc_macro \ 254 254 --extern macros --extern kernel --extern pin_init ··· 257 257 rusttestlib-macros rusttestlib-kernel rusttestlib-pin_init FORCE 258 258 +$(call if_changed,rustc_test) 259 259 +$(call if_changed,rustdoc_test) 260 - 261 - rusttest-kernel: private rustc_target_flags = --extern ffi --extern pin_init \ 262 - --extern build_error --extern macros --extern bindings --extern uapi 263 - rusttest-kernel: $(src)/kernel/lib.rs rusttestlib-ffi rusttestlib-kernel \ 264 - rusttestlib-build_error rusttestlib-macros rusttestlib-bindings \ 265 - rusttestlib-uapi rusttestlib-pin_init FORCE 266 - +$(call if_changed,rustc_test) 267 260 268 261 ifdef CONFIG_CC_IS_CLANG 269 262 bindgen_c_flags = $(c_flags)
+1
rust/bindgen_parameters
··· 34 34 # We use const helpers to aid bindgen, to avoid conflicts when constants are 35 35 # recognized, block generation of the non-helper constants. 36 36 --blocklist-item ARCH_SLAB_MINALIGN 37 + --blocklist-item ARCH_KMALLOC_MINALIGN
+1
rust/bindings/bindings_helper.h
··· 84 84 85 85 /* `bindgen` gets confused at certain things. */ 86 86 const size_t RUST_CONST_HELPER_ARCH_SLAB_MINALIGN = ARCH_SLAB_MINALIGN; 87 + const size_t RUST_CONST_HELPER_ARCH_KMALLOC_MINALIGN = ARCH_KMALLOC_MINALIGN; 87 88 const size_t RUST_CONST_HELPER_PAGE_SIZE = PAGE_SIZE; 88 89 const gfp_t RUST_CONST_HELPER_GFP_ATOMIC = GFP_ATOMIC; 89 90 const gfp_t RUST_CONST_HELPER_GFP_KERNEL = GFP_KERNEL;
+8 -7
rust/kernel/alloc.rs
··· 2 2 3 3 //! Implementation of the kernel's memory allocation infrastructure. 4 4 5 - #[cfg(not(any(test, testlib)))] 6 5 pub mod allocator; 7 6 pub mod kbox; 8 7 pub mod kvec; 9 8 pub mod layout; 10 - 11 - #[cfg(any(test, testlib))] 12 - pub mod allocator_test; 13 - 14 - #[cfg(any(test, testlib))] 15 - pub use self::allocator_test as allocator; 16 9 17 10 pub use self::kbox::Box; 18 11 pub use self::kbox::KBox; ··· 130 137 /// - Implementers must ensure that all trait functions abide by the guarantees documented in the 131 138 /// `# Guarantees` sections. 132 139 pub unsafe trait Allocator { 140 + /// The minimum alignment satisfied by all allocations from this allocator. 141 + /// 142 + /// # Guarantees 143 + /// 144 + /// Any pointer allocated by this allocator is guaranteed to be aligned to `MIN_ALIGN` even if 145 + /// the requested layout has a smaller alignment. 146 + const MIN_ALIGN: usize; 147 + 133 148 /// Allocate memory based on `layout` and `flags`. 134 149 /// 135 150 /// On success, returns a buffer represented as `NonNull<[u8]>` that satisfies the layout
+8
rust/kernel/alloc/allocator.rs
··· 17 17 use crate::bindings; 18 18 use crate::pr_warn; 19 19 20 + const ARCH_KMALLOC_MINALIGN: usize = bindings::ARCH_KMALLOC_MINALIGN; 21 + 20 22 /// The contiguous kernel allocator. 21 23 /// 22 24 /// `Kmalloc` is typically used for physically contiguous allocations up to page size, but also ··· 130 128 // - passing a pointer to a valid memory allocation is OK, 131 129 // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same. 132 130 unsafe impl Allocator for Kmalloc { 131 + const MIN_ALIGN: usize = ARCH_KMALLOC_MINALIGN; 132 + 133 133 #[inline] 134 134 unsafe fn realloc( 135 135 ptr: Option<NonNull<u8>>, ··· 151 147 // - passing a pointer to a valid memory allocation is OK, 152 148 // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same. 153 149 unsafe impl Allocator for Vmalloc { 150 + const MIN_ALIGN: usize = kernel::page::PAGE_SIZE; 151 + 154 152 #[inline] 155 153 unsafe fn realloc( 156 154 ptr: Option<NonNull<u8>>, ··· 177 171 // - passing a pointer to a valid memory allocation is OK, 178 172 // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same. 179 173 unsafe impl Allocator for KVmalloc { 174 + const MIN_ALIGN: usize = ARCH_KMALLOC_MINALIGN; 175 + 180 176 #[inline] 181 177 unsafe fn realloc( 182 178 ptr: Option<NonNull<u8>>,
-124
rust/kernel/alloc/allocator_test.rs
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - 3 - //! So far the kernel's `Box` and `Vec` types can't be used by userspace test cases, since all users 4 - //! of those types (e.g. `CString`) use kernel allocators for instantiation. 5 - //! 6 - //! In order to allow userspace test cases to make use of such types as well, implement the 7 - //! `Cmalloc` allocator within the `allocator_test` module and type alias all kernel allocators to 8 - //! `Cmalloc`. The `Cmalloc` allocator uses libc's `realloc()` function as allocator backend. 9 - 10 - #![allow(missing_docs)] 11 - 12 - use super::{flags::*, AllocError, Allocator, Flags}; 13 - use core::alloc::Layout; 14 - use core::cmp; 15 - use core::ptr; 16 - use core::ptr::NonNull; 17 - 18 - /// The userspace allocator based on libc. 19 - pub struct Cmalloc; 20 - 21 - pub type Kmalloc = Cmalloc; 22 - pub type Vmalloc = Kmalloc; 23 - pub type KVmalloc = Kmalloc; 24 - 25 - impl Cmalloc { 26 - /// Returns a [`Layout`] that makes [`Kmalloc`] fulfill the requested size and alignment of 27 - /// `layout`. 28 - pub fn aligned_layout(layout: Layout) -> Layout { 29 - // Note that `layout.size()` (after padding) is guaranteed to be a multiple of 30 - // `layout.align()` which together with the slab guarantees means that `Kmalloc` will return 31 - // a properly aligned object (see comments in `kmalloc()` for more information). 32 - layout.pad_to_align() 33 - } 34 - } 35 - 36 - extern "C" { 37 - #[link_name = "aligned_alloc"] 38 - fn libc_aligned_alloc(align: usize, size: usize) -> *mut crate::ffi::c_void; 39 - 40 - #[link_name = "free"] 41 - fn libc_free(ptr: *mut crate::ffi::c_void); 42 - } 43 - 44 - // SAFETY: 45 - // - memory remains valid until it is explicitly freed, 46 - // - passing a pointer to a valid memory allocation created by this `Allocator` is always OK, 47 - // - `realloc` provides the guarantees as provided in the `# Guarantees` section. 48 - unsafe impl Allocator for Cmalloc { 49 - unsafe fn realloc( 50 - ptr: Option<NonNull<u8>>, 51 - layout: Layout, 52 - old_layout: Layout, 53 - flags: Flags, 54 - ) -> Result<NonNull<[u8]>, AllocError> { 55 - let src = match ptr { 56 - Some(src) => { 57 - if old_layout.size() == 0 { 58 - ptr::null_mut() 59 - } else { 60 - src.as_ptr() 61 - } 62 - } 63 - None => ptr::null_mut(), 64 - }; 65 - 66 - if layout.size() == 0 { 67 - // SAFETY: `src` is either NULL or was previously allocated with this `Allocator` 68 - unsafe { libc_free(src.cast()) }; 69 - 70 - return Ok(NonNull::slice_from_raw_parts( 71 - crate::alloc::dangling_from_layout(layout), 72 - 0, 73 - )); 74 - } 75 - 76 - // ISO C (ISO/IEC 9899:2011) defines `aligned_alloc`: 77 - // 78 - // > The value of alignment shall be a valid alignment supported by the implementation 79 - // [...]. 80 - // 81 - // As an example of the "supported by the implementation" requirement, POSIX.1-2001 (IEEE 82 - // 1003.1-2001) defines `posix_memalign`: 83 - // 84 - // > The value of alignment shall be a power of two multiple of sizeof (void *). 85 - // 86 - // and POSIX-based implementations of `aligned_alloc` inherit this requirement. At the time 87 - // of writing, this is known to be the case on macOS (but not in glibc). 88 - // 89 - // Satisfy the stricter requirement to avoid spurious test failures on some platforms. 90 - let min_align = core::mem::size_of::<*const crate::ffi::c_void>(); 91 - let layout = layout.align_to(min_align).map_err(|_| AllocError)?; 92 - let layout = layout.pad_to_align(); 93 - 94 - // SAFETY: Returns either NULL or a pointer to a memory allocation that satisfies or 95 - // exceeds the given size and alignment requirements. 96 - let dst = unsafe { libc_aligned_alloc(layout.align(), layout.size()) }.cast::<u8>(); 97 - let dst = NonNull::new(dst).ok_or(AllocError)?; 98 - 99 - if flags.contains(__GFP_ZERO) { 100 - // SAFETY: The preceding calls to `libc_aligned_alloc` and `NonNull::new` 101 - // guarantee that `dst` points to memory of at least `layout.size()` bytes. 102 - unsafe { dst.as_ptr().write_bytes(0, layout.size()) }; 103 - } 104 - 105 - if !src.is_null() { 106 - // SAFETY: 107 - // - `src` has previously been allocated with this `Allocator`; `dst` has just been 108 - // newly allocated, hence the memory regions do not overlap. 109 - // - both` src` and `dst` are properly aligned and valid for reads and writes 110 - unsafe { 111 - ptr::copy_nonoverlapping( 112 - src, 113 - dst.as_ptr(), 114 - cmp::min(layout.size(), old_layout.size()), 115 - ) 116 - }; 117 - } 118 - 119 - // SAFETY: `src` is either NULL or was previously allocated with this `Allocator` 120 - unsafe { libc_free(src.cast()) }; 121 - 122 - Ok(NonNull::slice_from_raw_parts(dst, layout.size())) 123 - } 124 - }
+86 -4
rust/kernel/alloc/kbox.rs
··· 290 290 Ok(Self::new(x, flags)?.into()) 291 291 } 292 292 293 + /// Construct a pinned slice of elements `Pin<Box<[T], A>>`. 294 + /// 295 + /// This is a convenient means for creation of e.g. slices of structrures containing spinlocks 296 + /// or mutexes. 297 + /// 298 + /// # Examples 299 + /// 300 + /// ``` 301 + /// use kernel::sync::{new_spinlock, SpinLock}; 302 + /// 303 + /// struct Inner { 304 + /// a: u32, 305 + /// b: u32, 306 + /// } 307 + /// 308 + /// #[pin_data] 309 + /// struct Example { 310 + /// c: u32, 311 + /// #[pin] 312 + /// d: SpinLock<Inner>, 313 + /// } 314 + /// 315 + /// impl Example { 316 + /// fn new() -> impl PinInit<Self, Error> { 317 + /// try_pin_init!(Self { 318 + /// c: 10, 319 + /// d <- new_spinlock!(Inner { a: 20, b: 30 }), 320 + /// }) 321 + /// } 322 + /// } 323 + /// 324 + /// // Allocate a boxed slice of 10 `Example`s. 325 + /// let s = KBox::pin_slice( 326 + /// | _i | Example::new(), 327 + /// 10, 328 + /// GFP_KERNEL 329 + /// )?; 330 + /// 331 + /// assert_eq!(s[5].c, 10); 332 + /// assert_eq!(s[3].d.lock().a, 20); 333 + /// # Ok::<(), Error>(()) 334 + /// ``` 335 + pub fn pin_slice<Func, Item, E>( 336 + mut init: Func, 337 + len: usize, 338 + flags: Flags, 339 + ) -> Result<Pin<Box<[T], A>>, E> 340 + where 341 + Func: FnMut(usize) -> Item, 342 + Item: PinInit<T, E>, 343 + E: From<AllocError>, 344 + { 345 + let mut buffer = super::Vec::<T, A>::with_capacity(len, flags)?; 346 + for i in 0..len { 347 + let ptr = buffer.spare_capacity_mut().as_mut_ptr().cast(); 348 + // SAFETY: 349 + // - `ptr` is a valid pointer to uninitialized memory. 350 + // - `ptr` is not used if an error is returned. 351 + // - `ptr` won't be moved until it is dropped, i.e. it is pinned. 352 + unsafe { init(i).__pinned_init(ptr)? }; 353 + 354 + // SAFETY: 355 + // - `i + 1 <= len`, hence we don't exceed the capacity, due to the call to 356 + // `with_capacity()` above. 357 + // - The new value at index buffer.len() + 1 is the only element being added here, and 358 + // it has been initialized above by `init(i).__pinned_init(ptr)`. 359 + unsafe { buffer.inc_len(1) }; 360 + } 361 + 362 + let (ptr, _, _) = buffer.into_raw_parts(); 363 + let slice = core::ptr::slice_from_raw_parts_mut(ptr, len); 364 + 365 + // SAFETY: `slice` points to an allocation allocated with `A` (`buffer`) and holds a valid 366 + // `[T]`. 367 + Ok(Pin::from(unsafe { Box::from_raw(slice) })) 368 + } 369 + 293 370 /// Convert a [`Box<T,A>`] to a [`Pin<Box<T,A>>`]. If `T` does not implement 294 371 /// [`Unpin`], then `x` will be pinned in memory and can't be moved. 295 372 pub fn into_pin(this: Self) -> Pin<Self> { ··· 478 401 } 479 402 480 403 // SAFETY: The pointer returned by `into_foreign` comes from a well aligned 481 - // pointer to `T`. 404 + // pointer to `T` allocated by `A`. 482 405 unsafe impl<T: 'static, A> ForeignOwnable for Box<T, A> 483 406 where 484 407 A: Allocator, 485 408 { 486 - const FOREIGN_ALIGN: usize = core::mem::align_of::<T>(); 409 + const FOREIGN_ALIGN: usize = if core::mem::align_of::<T>() < A::MIN_ALIGN { 410 + A::MIN_ALIGN 411 + } else { 412 + core::mem::align_of::<T>() 413 + }; 414 + 487 415 type Borrowed<'a> = &'a T; 488 416 type BorrowedMut<'a> = &'a mut T; 489 417 ··· 517 435 } 518 436 519 437 // SAFETY: The pointer returned by `into_foreign` comes from a well aligned 520 - // pointer to `T`. 438 + // pointer to `T` allocated by `A`. 521 439 unsafe impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>> 522 440 where 523 441 A: Allocator, 524 442 { 525 - const FOREIGN_ALIGN: usize = core::mem::align_of::<T>(); 443 + const FOREIGN_ALIGN: usize = <Box<T, A> as ForeignOwnable>::FOREIGN_ALIGN; 526 444 type Borrowed<'a> = Pin<&'a T>; 527 445 type BorrowedMut<'a> = Pin<&'a mut T>; 528 446
+16 -6
rust/kernel/alloc/kvec.rs
··· 175 175 176 176 /// Returns the number of elements that can be stored within the vector without allocating 177 177 /// additional memory. 178 - pub fn capacity(&self) -> usize { 178 + pub const fn capacity(&self) -> usize { 179 179 if const { Self::is_zst() } { 180 180 usize::MAX 181 181 } else { ··· 185 185 186 186 /// Returns the number of elements stored within the vector. 187 187 #[inline] 188 - pub fn len(&self) -> usize { 188 + pub const fn len(&self) -> usize { 189 189 self.len 190 190 } 191 191 ··· 196 196 /// - `additional` must be less than or equal to `self.capacity - self.len`. 197 197 /// - All elements within the interval [`self.len`,`self.len + additional`) must be initialized. 198 198 #[inline] 199 - pub unsafe fn inc_len(&mut self, additional: usize) { 199 + pub const unsafe fn inc_len(&mut self, additional: usize) { 200 200 // Guaranteed by the type invariant to never underflow. 201 201 debug_assert!(additional <= self.capacity() - self.len()); 202 202 // INVARIANT: By the safety requirements of this method this represents the exact number of ··· 224 224 } 225 225 226 226 /// Returns a slice of the entire vector. 227 + /// 228 + /// # Examples 229 + /// 230 + /// ``` 231 + /// let mut v = KVec::new(); 232 + /// v.push(1, GFP_KERNEL)?; 233 + /// v.push(2, GFP_KERNEL)?; 234 + /// assert_eq!(v.as_slice(), &[1, 2]); 235 + /// # Ok::<(), Error>(()) 236 + /// ``` 227 237 #[inline] 228 238 pub fn as_slice(&self) -> &[T] { 229 239 self ··· 255 245 /// Returns a raw pointer to the vector's backing buffer, or, if `T` is a ZST, a dangling raw 256 246 /// pointer. 257 247 #[inline] 258 - pub fn as_ptr(&self) -> *const T { 248 + pub const fn as_ptr(&self) -> *const T { 259 249 self.ptr.as_ptr() 260 250 } 261 251 ··· 271 261 /// assert!(!v.is_empty()); 272 262 /// ``` 273 263 #[inline] 274 - pub fn is_empty(&self) -> bool { 264 + pub const fn is_empty(&self) -> bool { 275 265 self.len() == 0 276 266 } 277 267 ··· 1304 1294 } 1305 1295 } 1306 1296 1307 - #[macros::kunit_tests(rust_kvec_kunit)] 1297 + #[macros::kunit_tests(rust_kvec)] 1308 1298 mod tests { 1309 1299 use super::*; 1310 1300 use crate::prelude::*;
+1 -1
rust/kernel/alloc/layout.rs
··· 80 80 /// # Safety 81 81 /// 82 82 /// `len` must be a value, for which `len * size_of::<T>() <= isize::MAX` is true. 83 - pub unsafe fn new_unchecked(len: usize) -> Self { 83 + pub const unsafe fn new_unchecked(len: usize) -> Self { 84 84 // INVARIANT: By the safety requirements of this function 85 85 // `len * size_of::<T>() <= isize::MAX`. 86 86 Self {
+1 -1
rust/kernel/dma.rs
··· 9 9 device::{Bound, Core}, 10 10 error::{to_result, Result}, 11 11 prelude::*, 12 + sync::aref::ARef, 12 13 transmute::{AsBytes, FromBytes}, 13 - types::ARef, 14 14 }; 15 15 16 16 /// Trait to be implemented by DMA capable bus devices.
+2 -2
rust/kernel/error.rs
··· 158 158 } 159 159 160 160 /// Returns a string representing the error, if one exists. 161 - #[cfg(not(any(test, testlib)))] 161 + #[cfg(not(testlib))] 162 162 pub fn name(&self) -> Option<&'static CStr> { 163 163 // SAFETY: Just an FFI call, there are no extra safety requirements. 164 164 let ptr = unsafe { bindings::errname(-self.0.get()) }; ··· 175 175 /// When `testlib` is configured, this always returns `None` to avoid the dependency on a 176 176 /// kernel function so that tests that use this (e.g., by calling [`Result::unwrap`]) can still 177 177 /// run in userspace. 178 - #[cfg(any(test, testlib))] 178 + #[cfg(testlib)] 179 179 pub fn name(&self) -> Option<&'static CStr> { 180 180 None 181 181 }
+1 -1
rust/kernel/lib.rs
··· 206 206 } 207 207 } 208 208 209 - #[cfg(not(any(testlib, test)))] 209 + #[cfg(not(testlib))] 210 210 #[panic_handler] 211 211 fn panic(info: &core::panic::PanicInfo<'_>) -> ! { 212 212 pr_emerg!("{}\n", info);
+3 -3
rust/kernel/sync/arc.rs
··· 373 373 } 374 374 } 375 375 376 - // SAFETY: The pointer returned by `into_foreign` comes from a well aligned 377 - // pointer to `ArcInner<T>`. 376 + // SAFETY: The pointer returned by `into_foreign` was originally allocated as an 377 + // `KBox<ArcInner<T>>`, so that type is what determines the alignment. 378 378 unsafe impl<T: 'static> ForeignOwnable for Arc<T> { 379 - const FOREIGN_ALIGN: usize = core::mem::align_of::<ArcInner<T>>(); 379 + const FOREIGN_ALIGN: usize = <KBox<ArcInner<T>> as ForeignOwnable>::FOREIGN_ALIGN; 380 380 381 381 type Borrowed<'a> = ArcBorrow<'a, T>; 382 382 type BorrowedMut<'a> = Self::Borrowed<'a>;
+1 -1
samples/rust/rust_dma.rs
··· 10 10 dma::{CoherentAllocation, Device, DmaMask}, 11 11 pci, 12 12 prelude::*, 13 - types::ARef, 13 + sync::aref::ARef, 14 14 }; 15 15 16 16 struct DmaSampleDriver {