@@ -15,6 +15,7 @@ use core::ptr::NonNull;
1515
1616use crate :: alloc:: { AllocError , Allocator } ;
1717use crate :: bindings;
18+ use crate :: pr_warn;
1819
1920/// The contiguous kernel allocator.
2021///
@@ -24,6 +25,26 @@ use crate::bindings;
2425/// For more details see [self].
2526pub struct Kmalloc ;
2627
28+ /// The virtually contiguous kernel allocator.
29+ ///
30+ /// `Vmalloc` allocates pages from the page level allocator and maps them into the contiguous kernel
31+ /// virtual space. It is typically used for large allocations. The memory allocated with this
32+ /// allocator is not physically contiguous.
33+ ///
34+ /// For more details see [self].
35+ pub struct Vmalloc ;
36+
37+ /// Returns a proper size to alloc a new object aligned to `new_layout`'s alignment.
38+ fn aligned_size ( new_layout : Layout ) -> usize {
39+ // Customized layouts from `Layout::from_size_align()` can have size < align, so pad first.
40+ let layout = new_layout. pad_to_align ( ) ;
41+
42+ // Note that `layout.size()` (after padding) is guaranteed to be a multiple of `layout.align()`
43+ // which together with the slab guarantees means the `krealloc` will return a properly aligned
44+ // object (see comments in `kmalloc()` for more information).
45+ layout. size ( )
46+ }
47+
2748/// Calls `krealloc` with a proper size to alloc a new object aligned to `new_layout`'s alignment.
2849///
2950/// # Safety
@@ -58,6 +79,9 @@ impl ReallocFunc {
5879 // INVARIANT: `krealloc` satisfies the type invariants.
5980 const KREALLOC : Self = Self ( bindings:: krealloc) ;
6081
82+ // INVARIANT: `vrealloc` satisfies the type invariants.
83+ const VREALLOC : Self = Self ( bindings:: vrealloc) ;
84+
6185 /// # Safety
6286 ///
6387 /// This method has the same safety requirements as [`Allocator::realloc`].
@@ -153,6 +177,29 @@ unsafe impl GlobalAlloc for Kmalloc {
153177 }
154178}
155179
180+ // SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees that
181+ // - memory remains valid until it is explicitly freed,
182+ // - passing a pointer to a valid memory allocation is OK,
183+ // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same.
184+ unsafe impl Allocator for Vmalloc {
185+ #[ inline]
186+ unsafe fn realloc (
187+ ptr : Option < NonNull < u8 > > ,
188+ layout : Layout ,
189+ flags : Flags ,
190+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
191+ // TODO: Support alignments larger than PAGE_SIZE.
192+ if layout. align ( ) > bindings:: PAGE_SIZE {
193+ pr_warn ! ( "Vmalloc does not support alignments larger than PAGE_SIZE yet.\n " ) ;
194+ return Err ( AllocError ) ;
195+ }
196+
197+ // SAFETY: If not `None`, `ptr` is guaranteed to point to valid memory, which was previously
198+ // allocated with this `Allocator`.
199+ unsafe { ReallocFunc :: VREALLOC . call ( ptr, layout, flags) }
200+ }
201+ }
202+
156203#[ global_allocator]
157204static ALLOCATOR : Kmalloc = Kmalloc ;
158205
0 commit comments