Skip to content

Commit d0f13fb

Browse files
feat(physicalmem): respect memory reservations
Co-authored-by: Martin Kröning <martin.kroening@eonerc.rwth-aachen.de>
1 parent 7d8352a commit d0f13fb

1 file changed

Lines changed: 58 additions & 1 deletion

File tree

src/mm/physicalmem.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use core::sync::atomic::{AtomicUsize, Ordering};
22

33
use align_address::Align;
4-
use free_list::{FreeList, PageRange};
4+
use free_list::{FreeList, PageRange, PageRangeError};
55
use hermit_sync::InterruptTicketMutex;
66
use memory_addresses::{PhysAddr, VirtAddr};
77

@@ -97,9 +97,66 @@ fn detect_from_fdt() -> Result<(), ()> {
9797
debug!("Claimed physical memory: {range:#x?}");
9898
}
9999

100+
let reserve = |reservation: PageRange| {
101+
debug!("Memory reservation: {reservation:#x?}");
102+
// While there are still overlaps between this reservation and any available ranges,
103+
// allocate that overlap to mark it as not available.
104+
while let Ok(reserved) = PHYSICAL_FREE_LIST
105+
.lock()
106+
.allocate_with(|range| reservation.and(range))
107+
{
108+
debug!("Reserved {reserved:#x?}");
109+
}
110+
};
111+
112+
for reservation in fdt.memory_reservations() {
113+
let start = reservation.address().addr();
114+
let end = start + reservation.size();
115+
let reservation = PageRange::new(start, end).unwrap();
116+
reserve(reservation);
117+
}
118+
119+
let kernel_start = if env::is_uefi() {
120+
super::kernel_start_address().as_usize()
121+
} else {
122+
// FIXME: Memory before the kernel causes trouble on non-uefi systems.
123+
// It is unclear, which exact regions cause problems.
124+
0
125+
};
126+
let kernel_end = super::kernel_end_address().as_usize();
127+
let kernel_region = PageRange::new(kernel_start, kernel_end).unwrap();
128+
reserve(kernel_region);
129+
130+
let fdt_start = env::boot_info().hardware_info.device_tree.unwrap().get();
131+
let fdt_start = usize::try_from(fdt_start).unwrap();
132+
let fdt_end = fdt_start + fdt.total_size();
133+
let fdt_region = PageRange::containing(fdt_start, fdt_end).unwrap();
134+
reserve(fdt_region);
135+
100136
Ok(())
101137
}
102138

139+
// FIXME: upstream these
140+
trait PageRangeExt: Sized {
141+
fn containing(start: usize, end: usize) -> Result<Self, PageRangeError>;
142+
143+
fn and(self, rhs: Self) -> Option<Self>;
144+
}
145+
146+
impl PageRangeExt for PageRange {
147+
fn containing(start: usize, end: usize) -> Result<Self, PageRangeError> {
148+
let start = start.align_down(free_list::PAGE_SIZE);
149+
let end = end.align_up(free_list::PAGE_SIZE);
150+
Self::new(start, end)
151+
}
152+
153+
fn and(self, rhs: Self) -> Option<Self> {
154+
let start = self.start().max(rhs.start());
155+
let end = self.end().min(rhs.end());
156+
Self::new(start, end).ok()
157+
}
158+
}
159+
103160
#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
104161
fn detect_from_limits() -> Result<(), ()> {
105162
let limit = crate::arch::kernel::get_limit();

0 commit comments

Comments
 (0)