Skip to content

Commit 0e8dd0d

Browse files
committed
Guard the lower 1MB of memory
This also adds a new fuction to ignore the attempts to guard the lower 1MB if it's really required.
1 parent fffa7ce commit 0e8dd0d

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

Diff for: api/src/info.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,14 @@ impl MemoryRegion {
141141
/// Represents the different types of memory.
142142
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
143143
#[non_exhaustive]
144-
#[repr(C)]
144+
#[repr(C, u64)]
145145
pub enum MemoryRegionKind {
146146
/// Unused conventional memory, can be used by the kernel.
147147
Usable,
148148
/// Memory mappings created by the bootloader, including the page table and boot info mappings.
149149
///
150150
/// This memory should _not_ be used by the kernel.
151-
Bootloader,
151+
Bootloader = 0x8FFFFFFF,
152152
/// An unknown memory region reported by the UEFI firmware.
153153
///
154154
/// Contains the UEFI memory type tag.

Diff for: common/src/legacy_memory_region.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub struct LegacyFrameAllocator<I, D> {
2828
memory_map: I,
2929
current_descriptor: Option<D>,
3030
next_frame: PhysFrame,
31+
start_frame: PhysFrame,
3132
}
3233

3334
impl<I, D> LegacyFrameAllocator<I, D>
@@ -42,18 +43,32 @@ where
4243
/// library assumes that references can never point to virtual address `0`.
4344
pub fn new(memory_map: I) -> Self {
4445
// skip frame 0 because the rust core library does not see 0 as a valid address
45-
let start_frame = PhysFrame::containing_address(PhysAddr::new(0x1000));
46-
Self::new_starting_at(start_frame, memory_map)
46+
// also skip the first 1MB of frames, there are use cases that require lower conventional memory access. (Such as SMP SIPI)
47+
let start_frame = PhysFrame::containing_address(PhysAddr::new(0x100000));
48+
unsafe { Self::unsafe_new_starting_at(start_frame, memory_map) }
4749
}
4850

4951
/// Creates a new frame allocator based on the given legacy memory regions. Skips any frames
50-
/// before the given `frame`.
52+
/// before the given `frame`, or 0x100000, whichever is higher.
5153
pub fn new_starting_at(frame: PhysFrame, memory_map: I) -> Self {
54+
if frame.start_address().as_u64() < 0x100000 {
55+
// Skip the first 1MB of frames, regardless of what was requested.
56+
// there are use cases that require lower conventional memory access. (Such as SMP SIPI)
57+
return Self::new(memory_map);
58+
}
59+
60+
return unsafe { Self::unsafe_new_starting_at(frame, memory_map) };
61+
}
62+
63+
/// Creates a new frame allocator based on the given legacy memory regions. Skips any frames
64+
/// before the given `frame`, without attempting to protect the lower 1MB of memory.
65+
pub unsafe fn unsafe_new_starting_at(frame: PhysFrame, memory_map: I) -> Self {
5266
Self {
5367
original: memory_map.clone(),
5468
memory_map,
5569
current_descriptor: None,
5670
next_frame: frame,
71+
start_frame: frame,
5772
}
5873
}
5974

@@ -121,9 +136,11 @@ where
121136
let next_free = self.next_frame.start_address();
122137
let kind = match descriptor.kind() {
123138
MemoryRegionKind::Usable => {
124-
if end <= next_free {
139+
if end <= next_free && end > self.start_frame.start_address() {
125140
MemoryRegionKind::Bootloader
126-
} else if descriptor.start() >= next_free {
141+
} else if descriptor.start() >= next_free
142+
|| end <= self.start_frame.start_address()
143+
{
127144
MemoryRegionKind::Usable
128145
} else {
129146
// part of the region is used -> add it separately

Diff for: uefi/src/memory_descriptor.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ impl LegacyMemoryRegion for UefiMemoryDescriptor {
2020
fn kind(&self) -> MemoryRegionKind {
2121
match self.0.ty {
2222
MemoryType::CONVENTIONAL => MemoryRegionKind::Usable,
23+
MemoryType::LOADER_CODE => MemoryRegionKind::Usable,
24+
// We load the kernel under this type, probably not wise to mark it free after boot, even if it is.
25+
// Or perhaps we should use a different memory type (Such as the OS Loader range from the EFI spec (0x80000000-0xFFFFFFFF))?
26+
MemoryType::LOADER_DATA => MemoryRegionKind::Bootloader,
27+
MemoryType::BOOT_SERVICES_CODE => MemoryRegionKind::Usable,
28+
MemoryType::BOOT_SERVICES_DATA => MemoryRegionKind::Usable,
2329
other => MemoryRegionKind::UnknownUefi(other.0),
2430
}
2531
}
@@ -28,7 +34,6 @@ impl LegacyMemoryRegion for UefiMemoryDescriptor {
2834
match self.0.ty {
2935
MemoryType::CONVENTIONAL => true,
3036
MemoryType::LOADER_CODE
31-
| MemoryType::LOADER_DATA
3237
| MemoryType::BOOT_SERVICES_CODE
3338
| MemoryType::BOOT_SERVICES_DATA => {
3439
// we don't need this data anymore after the bootloader

0 commit comments

Comments
 (0)