Skip to content

Commit 2e2a098

Browse files
authoredSep 25, 2022
Merge pull request #263 from Freax13/fix-large-phys-mem-mapping
fix `get_free_address` for large sizes (0.10)
2 parents 9d733ab + 32ce601 commit 2e2a098

File tree

2 files changed

+24
-19
lines changed

2 files changed

+24
-19
lines changed
 

‎src/binary/level_4_entries.rs

+23-18
Original file line numberDiff line numberDiff line change
@@ -131,19 +131,18 @@ impl UsedLevel4Entries {
131131
}
132132
}
133133

134-
/// Returns an unused level 4 entry and marks it as used. If `CONFIG.aslr` is
135-
/// enabled, this will return a random available entry.
134+
/// Returns the first index of a `num` contiguous unused level 4 entries and marks them as
135+
/// used. If `CONFIG.aslr` is enabled, this will return random contiguous available entries.
136136
///
137137
/// Since this method marks each returned index as used, it can be used multiple times
138138
/// to determine multiple unused virtual memory regions.
139-
pub fn get_free_entry(&mut self) -> PageTableIndex {
140-
// Create an iterator over all available p4 indices.
139+
pub fn get_free_entries(&mut self, num: u64) -> PageTableIndex {
140+
// Create an iterator over all available p4 indices with `num` contiguous free entries.
141141
let mut free_entries = self
142142
.entry_state
143-
.iter()
144-
.copied()
143+
.windows(num.into_usize())
145144
.enumerate()
146-
.filter(|(_, used)| !used)
145+
.filter(|(_, entries)| entries.iter().all(|used| !used))
147146
.map(|(idx, _)| idx);
148147

149148
// Choose the free entry index.
@@ -154,30 +153,36 @@ impl UsedLevel4Entries {
154153
// Choose the first index.
155154
free_entries.next()
156155
};
157-
let idx = idx_opt.expect("no usable level 4 entry found");
156+
let idx = idx_opt.expect("no usable level 4 entries found");
158157

159-
// Mark the entry as used.
160-
self.entry_state[idx] = true;
158+
// Mark the entries as used.
159+
for i in 0..num.into_usize() {
160+
self.entry_state[idx + i] = true;
161+
}
161162

162163
PageTableIndex::new(idx.try_into().unwrap())
163164
}
164165

165-
/// Returns a virtual address in an unused level 4 entry and marks it as used.
166+
/// Returns a virtual address in one or more unused level 4 entries and marks them as used.
166167
///
167-
/// This function calls [`get_free_entry`] internally, so all of its docs applies here
168+
/// This function calls [`get_free_entries`] internally, so all of its docs applies here
168169
/// too.
169170
pub fn get_free_address(&mut self, size: u64, alignment: u64) -> VirtAddr {
170171
assert!(alignment.is_power_of_two());
171172

172-
let base =
173-
Page::from_page_table_indices_1gib(self.get_free_entry(), PageTableIndex::new(0))
174-
.start_address();
173+
const LEVEL_4_SIZE: u64 = 4096 * 512 * 512 * 512;
174+
175+
let level_4_entries = (size + (LEVEL_4_SIZE - 1)) / LEVEL_4_SIZE;
176+
let base = Page::from_page_table_indices_1gib(
177+
self.get_free_entries(level_4_entries),
178+
PageTableIndex::new(0),
179+
)
180+
.start_address();
175181

176182
let offset = if let Some(rng) = self.rng.as_mut() {
177183
// Choose a random offset.
178-
const LEVEL_4_SIZE: u64 = 4096 * 512 * 512 * 512;
179-
let end = LEVEL_4_SIZE - size;
180-
let uniform_range = Uniform::from(0..end / alignment);
184+
let max_offset = LEVEL_4_SIZE - (size % LEVEL_4_SIZE);
185+
let uniform_range = Uniform::from(0..max_offset / alignment);
181186
uniform_range.sample(rng) * alignment
182187
} else {
183188
0

‎src/binary/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ where
257257
let index = CONFIG
258258
.recursive_index
259259
.map(PageTableIndex::new)
260-
.unwrap_or_else(|| used_entries.get_free_entry());
260+
.unwrap_or_else(|| used_entries.get_free_entries(1));
261261

262262
let entry = &mut kernel_page_table.level_4_table()[index];
263263
if !entry.is_unused() {

0 commit comments

Comments
 (0)