From c83ab3c3a292f9bcbc09b069a308f20fb49df8c1 Mon Sep 17 00:00:00 2001 From: Erin Date: Sun, 4 Jun 2017 17:51:17 -0500 Subject: [PATCH] Remap the kernel! (finally) --- src/arch/x86_64/memory/mod.rs | 2 +- src/arch/x86_64/memory/paging/mod.rs | 46 ++++++++++++++++++++++++++++++++++++ src/lib.rs | 5 ++-- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/src/arch/x86_64/memory/mod.rs b/src/arch/x86_64/memory/mod.rs index 346e82f..ef208a7 100644 --- a/src/arch/x86_64/memory/mod.rs +++ b/src/arch/x86_64/memory/mod.rs @@ -7,7 +7,7 @@ mod paging; pub use self::area_frame_allocator::AreaFrameAllocator; -pub use self::paging::test_paging; +pub use self::paging::remap_kernel; /// The physical size of each frame. pub const PAGE_SIZE: usize = 4096; diff --git a/src/arch/x86_64/memory/paging/mod.rs b/src/arch/x86_64/memory/paging/mod.rs index d293fb4..4823a56 100644 --- a/src/arch/x86_64/memory/paging/mod.rs +++ b/src/arch/x86_64/memory/paging/mod.rs @@ -3,12 +3,15 @@ //! Extremely ripped off from Phil Oppermann's tutorials, because I don't feel like writing //! a paging system off the top of my head today. +use core::ops::{Deref, DerefMut}; +use multiboot2::BootInformation; use super::PAGE_SIZE; use super::{Frame, FrameAllocator}; mod entry; mod table; mod mapper; +mod temporary_page; use self::entry::*; use self::table::{Table, Level4}; @@ -148,6 +151,49 @@ impl Page { } } +/// Remap the kernel +pub fn remap_kernel(allocator: &mut A, boot_info: &BootInformation) + where A: FrameAllocator { + + let mut scratch_page = TemporaryPage::new(Page { index: 0xabadcafe }, + allocator); + + let mut active_table = unsafe {ActivePageTable::new()}; + let mut new_table = { + let frame = allocator.alloc_frame() + .expect("Attempted to allocate a frame for a new page table, but no frames are available!"); + InactivePageTable::new(frame, &mut active_table, &mut scratch_page) + }; + + active_table.with(&mut new_table, &mut scratch_page, |mapper| { + let elf_sections_tag = boot_info.elf_sections_tag() + .expect("ELF sections tag required!"); + for section in elf_sections_tag.sections() { + if !section.is_allocated() { + // section is not loaded to memory + continue; + } + + assert!(section.start_address() % PAGE_SIZE == 0, "ELF sections must be page-aligned!"); + debug!("Mapping section at addr: {:#x}, size: {:#x}", + section.addr, section.size); + + let flags = WRITABLE; + let start_frame = Frame::containing_address(section.start_address()); + let end_frame = Frame::containing_address(section.end_address() - 1); + for frame in Frame::range_inclusive(start_frame, end_frame) { + mapper.identity_map(frame, flags, allocator); + } + } + + let vga_buffer_frame = Frame::containing_address(0xb8000); + mapper.identity_map(vga_buffer_frame, WRITABLE, allocator); + }); + + let old_table = active_table.switch(new_table); + info!("Successfully switched to new page table."); +} + /// Temporary function to test paging pub fn test_paging(allocator: &mut A) where A: FrameAllocator { let mut page_table = unsafe {ActivePageTable::new()}; diff --git a/src/lib.rs b/src/lib.rs index fcfc4e5..0bd9d73 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,8 +63,9 @@ pub extern fn kernel_main(multiboot_info_pointer: usize) { kernel_start as usize, kernel_end as usize, multiboot_start, multiboot_end, memory_map_tag.memory_areas()); - memory::test_paging(&mut frame_allocator); - println!("-- memory paging test finished --"); + memory::remap_kernel(&mut frame_allocator, boot_info); + + println!("-- remap_kernel finished! --"); loop {} }