Move remap_the_kernel() out of `paging` mod. Add page fault handler.

master
WangRunji 7 years ago
parent 9b4d9a4a1f
commit 230d5a0287

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

@ -49,7 +49,7 @@ 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();

@ -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<A>(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,

@ -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<A>(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;

Loading…
Cancel
Save