|
1 | 1 | use core::sync::atomic::{AtomicUsize, Ordering}; |
2 | 2 |
|
3 | 3 | use align_address::Align; |
4 | | -use free_list::{FreeList, PageRange}; |
| 4 | +use free_list::{FreeList, PageRange, PageRangeError}; |
5 | 5 | use hermit_sync::InterruptTicketMutex; |
6 | 6 | use memory_addresses::{PhysAddr, VirtAddr}; |
7 | 7 |
|
@@ -97,9 +97,66 @@ fn detect_from_fdt() -> Result<(), ()> { |
97 | 97 | debug!("Claimed physical memory: {range:#x?}"); |
98 | 98 | } |
99 | 99 |
|
| 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 | + |
100 | 136 | Ok(()) |
101 | 137 | } |
102 | 138 |
|
| 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 | + |
103 | 160 | #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] |
104 | 161 | fn detect_from_limits() -> Result<(), ()> { |
105 | 162 | let limit = crate::arch::kernel::get_limit(); |
|
0 commit comments