|  | 
| 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,64 @@ 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 | +		if let Ok(reserved) = PHYSICAL_FREE_LIST | 
|  | 103 | +			.lock() | 
|  | 104 | +			.allocate_with(|range| reservation.and(range)) | 
|  | 105 | +		{ | 
|  | 106 | +			debug!("Reserved {reserved:#x?}"); | 
|  | 107 | +		} | 
|  | 108 | +	}; | 
|  | 109 | + | 
|  | 110 | +	for reservation in fdt.memory_reservations() { | 
|  | 111 | +		let start = reservation.address().addr(); | 
|  | 112 | +		let end = start + reservation.size(); | 
|  | 113 | +		let reservation = PageRange::new(start, end).unwrap(); | 
|  | 114 | +		reserve(reservation); | 
|  | 115 | +	} | 
|  | 116 | + | 
|  | 117 | +	let kernel_start = if env::is_uefi() { | 
|  | 118 | +		super::kernel_start_address().as_usize() | 
|  | 119 | +	} else { | 
|  | 120 | +		// FIXME: Memory before the kernel causes trouble on non-uefi systems. | 
|  | 121 | +		// It is unclear, which exact regions cause problems. | 
|  | 122 | +		0 | 
|  | 123 | +	}; | 
|  | 124 | +	let kernel_end = super::kernel_end_address().as_usize(); | 
|  | 125 | +	let kernel_region = PageRange::new(kernel_start, kernel_end).unwrap(); | 
|  | 126 | +	reserve(kernel_region); | 
|  | 127 | + | 
|  | 128 | +	let fdt_start = env::boot_info().hardware_info.device_tree.unwrap().get(); | 
|  | 129 | +	let fdt_start = usize::try_from(fdt_start).unwrap(); | 
|  | 130 | +	let fdt_end = fdt_start + fdt.total_size(); | 
|  | 131 | +	let fdt_region = PageRange::containing(fdt_start, fdt_end).unwrap(); | 
|  | 132 | +	reserve(fdt_region); | 
|  | 133 | + | 
| 100 | 134 | 	Ok(()) | 
| 101 | 135 | } | 
| 102 | 136 | 
 | 
|  | 137 | +// FIXME: upstream these | 
|  | 138 | +trait PageRangeExt: Sized { | 
|  | 139 | +	fn containing(start: usize, end: usize) -> Result<Self, PageRangeError>; | 
|  | 140 | + | 
|  | 141 | +	fn and(self, rhs: Self) -> Option<Self>; | 
|  | 142 | +} | 
|  | 143 | + | 
|  | 144 | +impl PageRangeExt for PageRange { | 
|  | 145 | +	fn containing(start: usize, end: usize) -> Result<Self, PageRangeError> { | 
|  | 146 | +		let start = start.align_down(free_list::PAGE_SIZE); | 
|  | 147 | +		let end = end.align_up(free_list::PAGE_SIZE); | 
|  | 148 | +		Self::new(start, end) | 
|  | 149 | +	} | 
|  | 150 | + | 
|  | 151 | +	fn and(self, rhs: Self) -> Option<Self> { | 
|  | 152 | +		let start = self.start().max(rhs.start()); | 
|  | 153 | +		let end = self.end().min(rhs.end()); | 
|  | 154 | +		Self::new(start, end).ok() | 
|  | 155 | +	} | 
|  | 156 | +} | 
|  | 157 | + | 
| 103 | 158 | #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] | 
| 104 | 159 | fn detect_from_limits() -> Result<(), ()> { | 
| 105 | 160 | 	let limit = crate::arch::kernel::get_limit(); | 
|  | 
0 commit comments