@@ -28,8 +28,12 @@ pub struct LegacyFrameAllocator<I, D> {
28
28
memory_map : I ,
29
29
current_descriptor : Option < D > ,
30
30
next_frame : PhysFrame ,
31
+ min_frame : PhysFrame ,
31
32
}
32
33
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
+
33
37
impl < I , D > LegacyFrameAllocator < I , D >
34
38
where
35
39
I : ExactSizeIterator < Item = D > + Clone ,
@@ -40,20 +44,25 @@ where
40
44
/// Skips the frame at physical address zero to avoid potential problems. For example
41
45
/// identity-mapping the frame at address zero is not valid in Rust, because Rust's `core`
42
46
/// 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).
43
48
pub fn new ( memory_map : I ) -> Self {
44
49
// 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 ) ) ;
46
51
Self :: new_starting_at ( start_frame, memory_map)
47
52
}
48
53
49
54
/// 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).
51
57
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) ;
52
60
Self {
53
61
original : memory_map. clone ( ) ,
54
62
memory_map,
55
63
current_descriptor : None ,
56
64
next_frame : frame,
65
+ min_frame : frame,
57
66
}
58
67
}
59
68
71
80
if self . next_frame <= end_frame {
72
81
let ret = self . next_frame ;
73
82
self . next_frame += 1 ;
83
+
74
84
Some ( ret)
75
85
} else {
76
86
None
@@ -125,14 +135,44 @@ where
125
135
let next_free = self . next_frame . start_address ( ) ;
126
136
let kind = match descriptor. kind ( ) {
127
137
MemoryRegionKind :: Usable => {
128
- if end <= next_free {
138
+ if end <= next_free && start >= self . min_frame . start_address ( ) {
129
139
MemoryRegionKind :: Bootloader
130
140
} else if descriptor. start ( ) >= next_free {
131
141
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
132
159
} 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
+
133
172
// part of the region is used -> add it separately
173
+ // first part of the region is used, later part is free
134
174
let used_region = MemoryRegion {
135
- start : descriptor . start ( ) . as_u64 ( ) ,
175
+ start : start. as_u64 ( ) ,
136
176
end : next_free. as_u64 ( ) ,
137
177
kind : MemoryRegionKind :: Bootloader ,
138
178
} ;
0 commit comments