@@ -15,6 +15,7 @@ use core::ptr::NonNull;
15
15
16
16
use crate :: alloc:: { AllocError , Allocator } ;
17
17
use crate :: bindings;
18
+ use crate :: pr_warn;
18
19
19
20
/// The contiguous kernel allocator.
20
21
///
@@ -24,6 +25,15 @@ use crate::bindings;
24
25
/// For more details see [self].
25
26
pub struct Kmalloc ;
26
27
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
+
27
37
/// Returns a proper size to alloc a new object aligned to `new_layout`'s alignment.
28
38
fn aligned_size ( new_layout : Layout ) -> usize {
29
39
// Customized layouts from `Layout::from_size_align()` can have size < align, so pad first.
@@ -63,6 +73,9 @@ impl ReallocFunc {
63
73
// INVARIANT: `krealloc` satisfies the type invariants.
64
74
const KREALLOC : Self = Self ( bindings:: krealloc) ;
65
75
76
+ // INVARIANT: `vrealloc` satisfies the type invariants.
77
+ const VREALLOC : Self = Self ( bindings:: vrealloc) ;
78
+
66
79
/// # Safety
67
80
///
68
81
/// This method has the same safety requirements as [`Allocator::realloc`].
@@ -168,6 +181,30 @@ unsafe impl GlobalAlloc for Kmalloc {
168
181
}
169
182
}
170
183
184
+ // SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees that
185
+ // - memory remains valid until it is explicitly freed,
186
+ // - passing a pointer to a valid memory allocation is OK,
187
+ // - `realloc` satisfies the guarantees, since `ReallocFunc::call` has the same.
188
+ unsafe impl Allocator for Vmalloc {
189
+ #[ inline]
190
+ unsafe fn realloc (
191
+ ptr : Option < NonNull < u8 > > ,
192
+ layout : Layout ,
193
+ old_layout : Layout ,
194
+ flags : Flags ,
195
+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
196
+ // TODO: Support alignments larger than PAGE_SIZE.
197
+ if layout. align ( ) > bindings:: PAGE_SIZE {
198
+ pr_warn ! ( "Vmalloc does not support alignments larger than PAGE_SIZE yet.\n " ) ;
199
+ return Err ( AllocError ) ;
200
+ }
201
+
202
+ // SAFETY: If not `None`, `ptr` is guaranteed to point to valid memory, which was previously
203
+ // allocated with this `Allocator`.
204
+ unsafe { ReallocFunc :: VREALLOC . call ( ptr, layout, old_layout, flags) }
205
+ }
206
+ }
207
+
171
208
#[ global_allocator]
172
209
static ALLOCATOR : Kmalloc = Kmalloc ;
173
210
0 commit comments