@@ -28,8 +28,12 @@ pub struct LegacyFrameAllocator<I, D> {
2828 memory_map : I ,
2929 current_descriptor : Option < D > ,
3030 next_frame : PhysFrame ,
31+ min_frame : PhysFrame ,
3132}
3233
34+ /// Start address of the first frame that is not part of the lower 1MB of frames
35+ const LOWER_MEMORY_END_PAGE : u64 = 0x100_000 ;
36+
3337impl < I , D > LegacyFrameAllocator < I , D >
3438where
3539 I : ExactSizeIterator < Item = D > + Clone ,
@@ -40,20 +44,26 @@ where
4044 /// Skips the frame at physical address zero to avoid potential problems. For example
4145 /// identity-mapping the frame at address zero is not valid in Rust, because Rust's `core`
4246 /// library assumes that references can never point to virtual address `0`.
47+ /// Also skips the lower 1MB of frames, there are use cases that require lower conventional memory access (Such as SMP SIPI).
4348 pub fn new ( memory_map : I ) -> Self {
4449 // 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 ) ) ;
50+ // Also skip at least the lower 1MB of frames, there are use cases that require lower conventional memory access (Such as SMP SIPI).
51+ let start_frame = PhysFrame :: containing_address ( PhysAddr :: new ( LOWER_MEMORY_END_PAGE ) ) ;
4652 Self :: new_starting_at ( start_frame, memory_map)
4753 }
4854
4955 /// Creates a new frame allocator based on the given legacy memory regions. Skips any frames
50- /// before the given `frame`.
56+ /// before the given `frame` or `0x10000`(1MB) whichever is higher, there are use cases that require
57+ /// lower conventional memory access (Such as SMP SIPI).
5158 pub fn new_starting_at ( frame : PhysFrame , memory_map : I ) -> Self {
59+ let lower_mem_end = PhysFrame :: containing_address ( PhysAddr :: new ( LOWER_MEMORY_END_PAGE ) ) ;
60+ let frame = core:: cmp:: max ( frame, lower_mem_end) ;
5261 Self {
5362 original : memory_map. clone ( ) ,
5463 memory_map,
5564 current_descriptor : None ,
5665 next_frame : frame,
66+ min_frame : frame,
5767 }
5868 }
5969
7181 if self . next_frame <= end_frame {
7282 let ret = self . next_frame ;
7383 self . next_frame += 1 ;
84+
7485 Some ( ret)
7586 } else {
7687 None
@@ -125,14 +136,44 @@ where
125136 let next_free = self . next_frame . start_address ( ) ;
126137 let kind = match descriptor. kind ( ) {
127138 MemoryRegionKind :: Usable => {
128- if end <= next_free {
139+ if end <= next_free && start >= self . min_frame . start_address ( ) {
129140 MemoryRegionKind :: Bootloader
130141 } else if descriptor. start ( ) >= next_free {
131142 MemoryRegionKind :: Usable
143+ } else if end <= self . min_frame . start_address ( ) {
144+ // treat regions before min_frame as usable
145+ // this allows for access to the lower 1MB of frames
146+ MemoryRegionKind :: Usable
147+ } else if end <= next_free {
148+ // part of the region is used -> add it separately
149+ // first part of the region is in lower 1MB, later part is used
150+ let free_region = MemoryRegion {
151+ start : descriptor. start ( ) . as_u64 ( ) ,
152+ end : self . min_frame . start_address ( ) . as_u64 ( ) ,
153+ kind : MemoryRegionKind :: Usable ,
154+ } ;
155+ Self :: add_region ( free_region, regions, & mut next_index) ;
156+
157+ // add bootloader part normally
158+ start = self . min_frame . start_address ( ) ;
159+ MemoryRegionKind :: Bootloader
132160 } else {
161+ if start < self . min_frame . start_address ( ) {
162+ // part of the region is in lower memory
163+ let lower_region = MemoryRegion {
164+ start : start. as_u64 ( ) ,
165+ end : self . min_frame . start_address ( ) . as_u64 ( ) ,
166+ kind : MemoryRegionKind :: Usable ,
167+ } ;
168+ Self :: add_region ( lower_region, regions, & mut next_index) ;
169+
170+ start = self . min_frame . start_address ( ) ;
171+ }
172+
133173 // part of the region is used -> add it separately
174+ // first part of the region is used, later part is free
134175 let used_region = MemoryRegion {
135- start : descriptor . start ( ) . as_u64 ( ) ,
176+ start : start. as_u64 ( ) ,
136177 end : next_free. as_u64 ( ) ,
137178 kind : MemoryRegionKind :: Bootloader ,
138179 } ;
0 commit comments