Skip to content

Commit 8e92c99

Browse files
author
Danilo Krummrich
committed
rust: alloc: vmalloc: implement Vmalloc::to_page()
Implement an abstraction of vmalloc_to_page() for subsequent use in the AsPageIter implementation of VBox and VVec. Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Tested-by: Alexandre Courbot <acourbot@nvidia.com> Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com> Link: https://lore.kernel.org/r/20250820145434.94745-3-dakr@kernel.org Signed-off-by: Danilo Krummrich <dakr@kernel.org>
1 parent 467971a commit 8e92c99

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

rust/kernel/alloc/allocator.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use core::ptr::NonNull;
1515

1616
use crate::alloc::{AllocError, Allocator};
1717
use crate::bindings;
18+
use crate::page;
1819
use crate::pr_warn;
1920

2021
/// The contiguous kernel allocator.
@@ -140,6 +141,54 @@ unsafe impl Allocator for Kmalloc {
140141
}
141142
}
142143

144+
impl Vmalloc {
145+
/// Convert a pointer to a [`Vmalloc`] allocation to a [`page::BorrowedPage`].
146+
///
147+
/// # Examples
148+
///
149+
/// ```
150+
/// # use core::ptr::{NonNull, from_mut};
151+
/// # use kernel::{page, prelude::*};
152+
/// use kernel::alloc::allocator::Vmalloc;
153+
///
154+
/// let mut vbox = VBox::<[u8; page::PAGE_SIZE]>::new_uninit(GFP_KERNEL)?;
155+
///
156+
/// {
157+
/// // SAFETY: By the type invariant of `Box` the inner pointer of `vbox` is non-null.
158+
/// let ptr = unsafe { NonNull::new_unchecked(from_mut(&mut *vbox)) };
159+
///
160+
/// // SAFETY:
161+
/// // `ptr` is a valid pointer to a `Vmalloc` allocation.
162+
/// // `ptr` is valid for the entire lifetime of `page`.
163+
/// let page = unsafe { Vmalloc::to_page(ptr.cast()) };
164+
///
165+
/// // SAFETY: There is no concurrent read or write to the same page.
166+
/// unsafe { page.fill_zero_raw(0, page::PAGE_SIZE)? };
167+
/// }
168+
/// # Ok::<(), Error>(())
169+
/// ```
170+
///
171+
/// # Safety
172+
///
173+
/// - `ptr` must be a valid pointer to a [`Vmalloc`] allocation.
174+
/// - `ptr` must remain valid for the entire duration of `'a`.
175+
pub unsafe fn to_page<'a>(ptr: NonNull<u8>) -> page::BorrowedPage<'a> {
176+
// SAFETY: `ptr` is a valid pointer to `Vmalloc` memory.
177+
let page = unsafe { bindings::vmalloc_to_page(ptr.as_ptr().cast()) };
178+
179+
// SAFETY: `vmalloc_to_page` returns a valid pointer to a `struct page` for a valid pointer
180+
// to `Vmalloc` memory.
181+
let page = unsafe { NonNull::new_unchecked(page) };
182+
183+
// SAFETY:
184+
// - `page` is a valid pointer to a `struct page`, given that by the safety requirements of
185+
// this function `ptr` is a valid pointer to a `Vmalloc` allocation.
186+
// - By the safety requirements of this function `ptr` is valid for the entire lifetime of
187+
// `'a`.
188+
unsafe { page::BorrowedPage::from_raw(page) }
189+
}
190+
}
191+
143192
// SAFETY: `realloc` delegates to `ReallocFunc::call`, which guarantees that
144193
// - memory remains valid until it is explicitly freed,
145194
// - passing a pointer to a valid memory allocation is OK,

0 commit comments

Comments
 (0)