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