@@ -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 = 0x10_000 ;
36+
3337impl < I , D > LegacyFrameAllocator < I , D >
3438where
3539 I : ExactSizeIterator < Item = D > + Clone ,
@@ -40,20 +44,25 @@ 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+ let start_frame = PhysFrame :: containing_address ( PhysAddr :: new ( LOWER_MEMORY_END_PAGE ) ) ;
4651 Self :: new_starting_at ( start_frame, memory_map)
4752 }
4853
4954 /// Creates a new frame allocator based on the given legacy memory regions. Skips any frames
50- /// before the given `frame`.
55+ /// before the given `frame` or `0x10000`(1MB) whichever is higher, there are use cases that require
56+ /// lower conventional memory access (Such as SMP SIPI).
5157 pub fn new_starting_at ( frame : PhysFrame , memory_map : I ) -> Self {
58+ let lower_mem_end = PhysFrame :: containing_address ( PhysAddr :: new ( LOWER_MEMORY_END_PAGE ) ) ;
59+ let frame = core:: cmp:: max ( frame, lower_mem_end) ;
5260 Self {
5361 original : memory_map. clone ( ) ,
5462 memory_map,
5563 current_descriptor : None ,
5664 next_frame : frame,
65+ min_frame : frame,
5766 }
5867 }
5968
7180 if self . next_frame <= end_frame {
7281 let ret = self . next_frame ;
7382 self . next_frame += 1 ;
83+
7484 Some ( ret)
7585 } else {
7686 None
@@ -125,14 +135,44 @@ where
125135 let next_free = self . next_frame . start_address ( ) ;
126136 let kind = match descriptor. kind ( ) {
127137 MemoryRegionKind :: Usable => {
128- if end <= next_free {
138+ if end <= next_free && start >= self . min_frame . start_address ( ) {
129139 MemoryRegionKind :: Bootloader
130140 } else if descriptor. start ( ) >= next_free {
131141 MemoryRegionKind :: Usable
142+ } else if end <= self . min_frame . start_address ( ) {
143+ // treat regions before min_frame as usable
144+ // this allows for access to the lower 1MB of frames
145+ MemoryRegionKind :: Usable
146+ } else if end <= next_free {
147+ // part of the region is used -> add it separately
148+ // first part of the region is in lower 1MB, later part is used
149+ let free_region = MemoryRegion {
150+ start : descriptor. start ( ) . as_u64 ( ) ,
151+ end : self . min_frame . start_address ( ) . as_u64 ( ) ,
152+ kind : MemoryRegionKind :: Usable ,
153+ } ;
154+ Self :: add_region ( free_region, regions, & mut next_index) ;
155+
156+ // add bootloader part normally
157+ start = self . min_frame . start_address ( ) ;
158+ MemoryRegionKind :: Bootloader
132159 } else {
160+ if start < self . min_frame . start_address ( ) {
161+ // part of the region is in lower memory
162+ let lower_region = MemoryRegion {
163+ start : start. as_u64 ( ) ,
164+ end : self . min_frame . start_address ( ) . as_u64 ( ) ,
165+ kind : MemoryRegionKind :: Usable ,
166+ } ;
167+ Self :: add_region ( lower_region, regions, & mut next_index) ;
168+
169+ start = self . min_frame . start_address ( ) ;
170+ }
171+
133172 // part of the region is used -> add it separately
173+ // first part of the region is used, later part is free
134174 let used_region = MemoryRegion {
135- start : descriptor . start ( ) . as_u64 ( ) ,
175+ start : start. as_u64 ( ) ,
136176 end : next_free. as_u64 ( ) ,
137177 kind : MemoryRegionKind :: Bootloader ,
138178 } ;
0 commit comments