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 {}
}