Skip to content

Commit bfc748f

Browse files
Danilo Krummrichfbq
authored andcommitted
rust: alloc: implement Allocator for Kmalloc
Implement `Allocator` for `Kmalloc`, the kernel's default allocator, typically used for objects smaller than page size. All memory allocations made with `Kmalloc` end up in `krealloc()`. It serves as allocator for the subsequently introduced types `KBox` and `KVec`. Signed-off-by: Danilo Krummrich <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 350a30c commit bfc748f

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

rust/kernel/alloc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
55
#[cfg(not(test))]
66
#[cfg(not(testlib))]
7-
mod allocator;
7+
pub mod allocator;
88
pub mod box_ext;
99
pub mod vec_ext;
1010

rust/kernel/alloc/allocator.rs

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,28 @@
11
// SPDX-License-Identifier: GPL-2.0
22

33
//! Allocator support.
4+
//!
5+
//! Documentation for the kernel's memory allocators can found in the "Memory Allocation Guide"
6+
//! linked below. For instance, this includes the concept of "get free page" (GFP) flags and the
7+
//! typical application of the different kernel allocators.
8+
//!
9+
//! Reference: <https://docs.kernel.org/core-api/memory-allocation.html>
410
511
use super::{flags::*, Flags};
612
use core::alloc::{GlobalAlloc, Layout};
713
use core::ptr;
14+
use core::ptr::NonNull;
815

9-
struct Kmalloc;
16+
use crate::alloc::{AllocError, Allocator};
17+
use crate::bindings;
18+
19+
/// The contiguous kernel allocator.
20+
///
21+
/// `Kmalloc` is typically used for physically contiguous allocations up to page size, but also
22+
/// supports larger allocations up to `bindings::KMALLOC_MAX_SIZE`, which is hardware specific.
23+
///
24+
/// For more details see [self].
25+
pub struct Kmalloc;
1026

1127
/// Returns a proper size to alloc a new object aligned to `new_layout`'s alignment.
1228
fn aligned_size(new_layout: Layout) -> usize {
@@ -36,6 +52,60 @@ pub(crate) unsafe fn krealloc_aligned(ptr: *mut u8, new_layout: Layout, flags: F
3652
unsafe { bindings::krealloc(ptr as *const core::ffi::c_void, size, flags.0) as *mut u8 }
3753
}
3854

55+
/// # Invariants
56+
///
57+
/// One of the following `krealloc`, `vrealloc`, `kvrealloc`.
58+
struct ReallocFunc(
59+
unsafe extern "C" fn(*const core::ffi::c_void, usize, u32) -> *mut core::ffi::c_void,
60+
);
61+
62+
impl ReallocFunc {
63+
// INVARIANT: `krealloc` satisfies the type invariants.
64+
const KREALLOC: Self = Self(bindings::krealloc);
65+
66+
/// # Safety
67+
///
68+
/// This method has the same safety requirements as [`Allocator::realloc`].
69+
unsafe fn call(
70+
&self,
71+
ptr: Option<NonNull<u8>>,
72+
layout: Layout,
73+
flags: Flags,
74+
) -> Result<NonNull<[u8]>, AllocError> {
75+
let size = aligned_size(layout);
76+
let ptr = match ptr {
77+
Some(ptr) => ptr.as_ptr(),
78+
None => ptr::null(),
79+
};
80+
81+
// SAFETY: `ptr` is either NULL or valid by the safety requirements of this function.
82+
let raw_ptr = unsafe {
83+
// If `size == 0` and `ptr != NULL` the memory behind the pointer is freed.
84+
self.0(ptr.cast(), size, flags.0).cast()
85+
};
86+
87+
let ptr = if size == 0 {
88+
NonNull::dangling()
89+
} else {
90+
NonNull::new(raw_ptr).ok_or(AllocError)?
91+
};
92+
93+
Ok(NonNull::slice_from_raw_parts(ptr, size))
94+
}
95+
}
96+
97+
unsafe impl Allocator for Kmalloc {
98+
#[inline]
99+
unsafe fn realloc(
100+
ptr: Option<NonNull<u8>>,
101+
layout: Layout,
102+
flags: Flags,
103+
) -> Result<NonNull<[u8]>, AllocError> {
104+
// SAFETY: `ReallocFunc::call` has the same safety requirements as `Allocator::realloc`.
105+
unsafe { ReallocFunc::KREALLOC.call(ptr, layout, flags) }
106+
}
107+
}
108+
39109
unsafe impl GlobalAlloc for Kmalloc {
40110
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
41111
// SAFETY: `ptr::null_mut()` is null and `layout` has a non-zero size by the function safety

0 commit comments

Comments
 (0)