Remap the kernel
(allocator: &mut A, boot_info: &BootInformation)
| 195 | |
| 196 | /// Remap the kernel |
| 197 | pub fn remap_the_kernel<A>(allocator: &mut A, boot_info: &BootInformation) -> ActivePageTable |
| 198 | where A: FrameAllocator |
| 199 | { |
| 200 | use core::ops::Range; |
| 201 | |
| 202 | let mut temporary_page = TemporaryPage::new(Page { number: 0xcafebabe }, allocator); |
| 203 | |
| 204 | let mut active_table = unsafe { ActivePageTable::new() }; |
| 205 | let mut new_table = { |
| 206 | let frame = allocator.allocate_frame().expect("no more frames"); |
| 207 | InactivePageTable::new(frame, &mut active_table, &mut temporary_page) |
| 208 | }; |
| 209 | |
| 210 | active_table.with(&mut new_table, &mut temporary_page, |mapper| { |
| 211 | let elf_sections_tag = boot_info.elf_sections_tag() |
| 212 | .expect("Memory map tag required"); |
| 213 | |
| 214 | // identity map the allocated kernel sections |
| 215 | for section in elf_sections_tag.sections() { |
| 216 | if !section.is_allocated() { |
| 217 | // section is not loaded to memory |
| 218 | continue; |
| 219 | } |
| 220 | |
| 221 | assert!(section.addr as usize % PAGE_SIZE == 0, |
| 222 | "sections need to be page aligned"); |
| 223 | println!("mapping section at addr: {:#x}, size: {:#x}", |
| 224 | section.addr, |
| 225 | section.size); |
| 226 | |
| 227 | let flags = EntryFlags::from_elf_section_flags(section); |
| 228 | |
| 229 | let start_frame = Frame::containing_address(section.start_address()); |
| 230 | let end_frame = Frame::containing_address(section.end_address() - 1); |
| 231 | for frame in Frame::range_inclusive(start_frame, end_frame) { |
| 232 | mapper.identity_map(frame, flags, allocator); |
| 233 | } |
| 234 | } |
| 235 | |
| 236 | // identity map the VGA text buffer |
| 237 | let vga_buffer_frame = Frame::containing_address(0xb8000); |
| 238 | mapper.identity_map(vga_buffer_frame, WRITABLE, allocator); |
| 239 | |
| 240 | // identity map the multiboot info structure |
| 241 | let multiboot_start = Frame::containing_address(boot_info.start_address()); |
| 242 | let multiboot_end = Frame::containing_address(boot_info.end_address() - 1); |
| 243 | for frame in Frame::range_inclusive(multiboot_start, multiboot_end) { |
| 244 | mapper.identity_map(frame, PRESENT, allocator); |
| 245 | } |
| 246 | }); |
| 247 | |
| 248 | // switch context to start using the new page table |
| 249 | let old_table = active_table.switch(new_table); |
| 250 | |
| 251 | // turn the old p4 page into a guard page |
| 252 | let old_p4_page = Page::containing_address(old_table.p4_frame.start_address()); |
| 253 | active_table.unmap(old_p4_page, allocator); |
| 254 | println!("guard page at {:#x}", old_p4_page.start_address()); |
no test coverage detected