Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 79e88d3

Browse files
committed
uefi: allocator: use shortcut for PAGE_SIZE
Allocating page-aligned memory via the global allocator is not uncommon for UEFI OS loaders. Therefore, it is feasible to use a shortcut in the allocator, and directly use boot::allocate_pages() rather than boot::allocate_pool().
1 parent 34508cf commit 79e88d3

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

‎uefi/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
- The `Display` impl for `CStr8` now excludes the trailing null character.
2929
- `VariableKeys` initializes with a larger name buffer to work around firmware
3030
bugs on some devices.
31+
- The UEFI `allocator::Allocator` has been optimized for page-aligned
32+
allocations.
3133

3234

3335
# uefi - 0.34.1 (2025年02月07日)

‎uefi/src/allocator.rs

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,13 @@
1212
//! will panic.
1313
1414
use crate::boot;
15+
use crate::boot::AllocateType;
1516
use crate::mem::memory_map::MemoryType;
1617
use crate::proto::loaded_image::LoadedImage;
1718
use core::alloc::{GlobalAlloc, Layout};
1819
use core::ptr::{self, NonNull};
1920
use core::sync::atomic::{AtomicU32, Ordering};
21+
use uefi_raw::table::boot::PAGE_SIZE;
2022

2123
/// Get the memory type to use for allocation.
2224
///
@@ -79,7 +81,7 @@ fn alloc_pool_aligned(memory_type: MemoryType, size: usize, align: usize) -> *mu
7981
}
8082
}
8183

82-
/// Allocator which uses the UEFI pool allocation functions.
84+
/// Allocator which uses the UEFI allocation functions.
8385
///
8486
/// The allocator can only be used as long as the UEFI boot services are
8587
/// available and have not been exited.
@@ -110,24 +112,51 @@ unsafe impl GlobalAlloc for Allocator {
110112
.map(|ptr| ptr.as_ptr())
111113
.unwrap_or(ptr::null_mut())
112114
}
115+
// Allocating pages is actually very expected in UEFI OS loaders, so
116+
// it makes sense to provide this optimization.
117+
// In Rust, each allocation's size must be at least the alignment,
118+
// as specified in the Rust type layout [0]. Therefore, we don't
119+
// have a risk of wasting memory. Further, using page-alignment for
120+
// small allocations is quiet unusual.
121+
// [0]: https://doc.rust-lang.org/reference/type-layout.html
122+
PAGE_SIZE => {
123+
log::trace!("Taking PAGE_SIZE shortcut");
124+
let count = size.div_ceil(PAGE_SIZE);
125+
boot::allocate_pages(AllocateType::AnyPages, memory_type, count)
126+
.map(|ptr| ptr.as_ptr())
127+
.unwrap_or(ptr::null_mut())
128+
}
113129
9.. => {
114130
alloc_pool_aligned(memory_type, size, align)
115131
}
116132
}
117133
}
118134

119135
/// Deallocate memory using [`boot::free_pool`].
120-
unsafe fn dealloc(&self, mut ptr: *mut u8, layout: Layout) {
121-
if layout.align() > 8 {
122-
// Retrieve the pointer to the full allocation that was packed right
123-
// before the aligned allocation in `alloc`.
124-
ptr = unsafe { (ptr as *const *mut u8).sub(1).read() };
125-
}
126-
127-
// OK to unwrap: `ptr` is required to be a valid allocation by the trait API.
136+
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
128137
let ptr = NonNull::new(ptr).unwrap();
129-
130-
// Warning: this will panic after exiting boot services.
131-
unsafe { boot::free_pool(ptr) }.unwrap();
138+
match layout.align() {
139+
0..=8 /* UEFI default alignment */ => {
140+
// Warning: this will panic after exiting boot services.
141+
unsafe { boot::free_pool(ptr) }.unwrap();
142+
}
143+
/* Corresponds the the alloc() match arm. */
144+
PAGE_SIZE => {
145+
log::trace!("Taking PAGE_SIZE shortcut");
146+
let count = layout.size().div_ceil(PAGE_SIZE);
147+
unsafe {
148+
boot::free_pages(ptr, count).unwrap()
149+
}
150+
}
151+
9.. => {
152+
let ptr = ptr.as_ptr().cast::<*mut u8>();
153+
// Retrieve the pointer to the full allocation that was packed right
154+
// before the aligned allocation in `alloc`.
155+
let actual_alloc_ptr = unsafe { ptr.sub(1).read() };
156+
let ptr = NonNull::new(actual_alloc_ptr).unwrap();
157+
// Warning: this will panic after exiting boot services.
158+
unsafe { boot::free_pool(ptr) }.unwrap();
159+
}
160+
}
132161
}
133162
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /