diff --git a/src/interrupts/mod.rs b/src/interrupts/mod.rs
index 23a7b97..d0b0b8c 100644
--- a/src/interrupts/mod.rs
+++ b/src/interrupts/mod.rs
@@ -1,5 +1,5 @@
use x86_64::VirtualAddress;
-use arch::idt::{Idt, ExceptionStackFrame};
+use arch::idt::{Idt, ExceptionStackFrame, PageFaultErrorCode};
use x86_64::structures::tss::TaskStateSegment;
use memory::{MemoryController, as_ref_in_real};
use spin::Once;
@@ -16,6 +16,7 @@ const DOUBLE_FAULT_IST_INDEX: usize = 0;
pub unsafe fn init_idt() {
IDT.breakpoint.set_handler_fn(*as_ref_in_real(&breakpoint_handler));
IDT.double_fault.set_handler_fn(*as_ref_in_real(&double_fault_handler));
+ IDT.page_fault.set_handler_fn(*as_ref_in_real(&page_fault_handler));
// .set_stack_index(DOUBLE_FAULT_IST_INDEX as u16);
IDT.load();
}
@@ -67,3 +68,12 @@ extern "x86-interrupt" fn double_fault_handler(
println!("\nEXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
loop {}
}
+
+extern "x86-interrupt" fn page_fault_handler(
+ stack_frame: &mut ExceptionStackFrame, _error_code: PageFaultErrorCode)
+{
+ use x86_64::registers::control_regs::cr2;
+ let addr = cr2();
+ println!("\nEXCEPTION: PAGE FAULT\n{:#?}\nAddress: {:#x}", stack_frame, addr);
+ loop {}
+}
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index b30f33a..00c0c80 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -49,10 +49,10 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) {
// ATTENTION: we have a very small stack and no guard page
println!("Hello World{}", "!");
unsafe{ interrupts::init_idt(); }
- unsafe{ let a = *(0xdeadbeaf as *const u8); } // double fault
+ // unsafe{ let a = *(0xdeadbeaf as *const u8); } // page fault
let boot_info = unsafe { multiboot2::load(multiboot_information_address) };
- arch::init();
+ arch::init();
// set up guard page and map the heap pages
let mut memory_controller = memory::init(boot_info);
diff --git a/src/memory/mod.rs b/src/memory/mod.rs
index 6c58db0..97968b4 100644
--- a/src/memory/mod.rs
+++ b/src/memory/mod.rs
@@ -1,5 +1,5 @@
pub use self::area_frame_allocator::AreaFrameAllocator;
-pub use self::paging::remap_the_kernel;
+pub use self::paging::*;
pub use self::stack_allocator::Stack;
pub use self::address::*;
@@ -46,8 +46,7 @@ pub fn init(boot_info: &BootInformation) -> MemoryController {
boot_info_start, boot_info_end,
memory_map_tag.memory_areas());
- let mut active_table = paging::remap_the_kernel(&mut frame_allocator,
- boot_info);
+ let mut active_table = remap_the_kernel(&mut frame_allocator, boot_info);
println!("{:?}", active_table);
@@ -76,6 +75,76 @@ pub fn init(boot_info: &BootInformation) -> MemoryController {
}
}
+pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation)
+ -> ActivePageTable
+ where A: FrameAllocator
+{
+ let mut temporary_page = TemporaryPage::new(Page::containing_address(0xcafebabe), allocator);
+
+ let mut active_table = unsafe { ActivePageTable::new() };
+ let mut new_table = {
+ let frame = allocator.allocate_frame().expect("no more frames");
+ InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
+ };
+
+ active_table.with(&mut new_table, &mut temporary_page, |mapper| {
+ let elf_sections_tag = boot_info.elf_sections_tag()
+ .expect("Memory map 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,
+ "sections need to be page aligned");
+
+ println!("mapping section at addr: {:#x}, size: {:#x}",
+ section.addr, section.size);
+
+ let flags = EntryFlags::from_elf_section_flags(section);
+
+ fn to_physical_frame(addr: usize) -> Frame {
+ Frame::containing_address(
+ if addr < KERNEL_OFFSET { addr }
+ else { addr - KERNEL_OFFSET })
+ }
+
+ let start_frame = to_physical_frame(section.start_address());
+ let end_frame = to_physical_frame(section.end_address() - 1);
+
+ for frame in Frame::range_inclusive(start_frame, end_frame) {
+ let page = Page::containing_address(frame.start_address().to_kernel_virtual());
+ mapper.map_to(page, frame, flags, allocator);
+ }
+ }
+
+ // identity map the VGA text buffer
+ let vga_buffer_frame = Frame::containing_address(0xb8000);
+ mapper.identity_map(vga_buffer_frame, WRITABLE, allocator);
+
+ // identity map the multiboot info structure
+ let multiboot_start = Frame::containing_address(boot_info.start_address());
+ let multiboot_end = Frame::containing_address(boot_info.end_address() - 1);
+ for frame in Frame::range_inclusive(multiboot_start, multiboot_end) {
+ mapper.identity_map(frame, PRESENT, allocator);
+ }
+ debug!("{:?}", mapper);
+ });
+
+ let old_table = active_table.switch(new_table);
+ println!("NEW TABLE!!!");
+
+ // turn the old p4 page into a guard page
+ let old_p4_page = Page::containing_address(
+ old_table.p4_frame.start_address().to_identity_virtual()
+ );
+ active_table.unmap(old_p4_page, allocator);
+ println!("guard page at {:#x}", old_p4_page.start_address());
+
+ active_table
+}
+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Frame {
number: usize,
diff --git a/src/memory/paging/mod.rs b/src/memory/paging/mod.rs
index e217e6d..1cb45cf 100644
--- a/src/memory/paging/mod.rs
+++ b/src/memory/paging/mod.rs
@@ -2,9 +2,7 @@ pub use self::entry::*;
pub use self::mapper::Mapper;
use core::ops::{Deref, DerefMut, Add};
use super::*;
-use multiboot2::BootInformation;
-use self::temporary_page::TemporaryPage;
-use consts::KERNEL_OFFSET;
+pub use self::temporary_page::TemporaryPage;
mod entry;
mod table;
@@ -99,7 +97,7 @@ impl DerefMut for ActivePageTable {
}
impl ActivePageTable {
- unsafe fn new() -> ActivePageTable {
+ pub unsafe fn new() -> ActivePageTable {
ActivePageTable {
mapper: Mapper::new(),
}
@@ -153,7 +151,7 @@ impl ActivePageTable {
}
pub struct InactivePageTable {
- p4_frame: Frame,
+ pub(in memory) p4_frame: Frame,
}
impl InactivePageTable {
@@ -175,79 +173,6 @@ impl InactivePageTable {
}
}
-pub fn remap_the_kernel(allocator: &mut A, boot_info: &BootInformation)
- -> ActivePageTable
- where A: FrameAllocator
-{
- let mut temporary_page = TemporaryPage::new(Page { number: 0xcafebabe },
- allocator);
-
- let mut active_table = unsafe { ActivePageTable::new() };
- let mut new_table = {
- let frame = allocator.allocate_frame().expect("no more frames");
- InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
- };
-
- active_table.with(&mut new_table, &mut temporary_page, |mapper| {
- let elf_sections_tag = boot_info.elf_sections_tag()
- .expect("Memory map tag required");
-
- for section in elf_sections_tag.sections() {
- use self::entry::WRITABLE;
-
- if !section.is_allocated() {
- // section is not loaded to memory
- continue;
- }
- assert!(section.start_address() % PAGE_SIZE == 0,
- "sections need to be page aligned");
-
- println!("mapping section at addr: {:#x}, size: {:#x}",
- section.addr, section.size);
-
- let flags = EntryFlags::from_elf_section_flags(section);
-
- fn to_physical_frame(addr: usize) -> Frame {
- Frame::containing_address(
- if addr < KERNEL_OFFSET { addr }
- else { addr - KERNEL_OFFSET })
- }
-
- let start_frame = to_physical_frame(section.start_address());
- let end_frame = to_physical_frame(section.end_address() - 1);
-
- for frame in Frame::range_inclusive(start_frame, end_frame) {
- let page = Page::containing_address(frame.start_address().to_kernel_virtual());
- mapper.map_to(page, frame, flags, allocator);
- }
- }
-
- // identity map the VGA text buffer
- let vga_buffer_frame = Frame::containing_address(0xb8000);
- mapper.identity_map(vga_buffer_frame, WRITABLE, allocator);
-
- // identity map the multiboot info structure
- let multiboot_start = Frame::containing_address(boot_info.start_address());
- let multiboot_end = Frame::containing_address(boot_info.end_address() - 1);
- for frame in Frame::range_inclusive(multiboot_start, multiboot_end) {
- mapper.identity_map(frame, PRESENT, allocator);
- }
- debug!("{:?}", mapper as *const Mapper);
- });
-
- let old_table = active_table.switch(new_table);
- println!("NEW TABLE!!!");
-
- // turn the old p4 page into a guard page
- let old_p4_page = Page::containing_address(
- old_table.p4_frame.start_address().to_identity_virtual()
- );
- active_table.unmap(old_p4_page, allocator);
- println!("guard page at {:#x}", old_p4_page.start_address());
-
- active_table
-}
-
use core::fmt;
use core::fmt::Debug;