Setup independent page tables, map heap to a single location

This commit is contained in:
Jeremy Soller 2016-08-19 14:53:16 -06:00
parent 7aafc165ec
commit 0501b2580d
11 changed files with 161 additions and 96 deletions

View file

@ -32,7 +32,10 @@ impl Mapper {
let mut p2 = p3.next_table_create(page.p3_index());
let mut p1 = p2.next_table_create(page.p2_index());
assert!(p1[page.p1_index()].is_unused());
assert!(p1[page.p1_index()].is_unused(),
"Set to {:X}: {:?}, requesting {:X}: {:?}",
p1[page.p1_index()].address().get(), p1[page.p1_index()].flags(),
frame.start_address().get(), flags);
p1[page.p1_index()].set(frame, flags | entry::PRESENT);
}

View file

@ -35,6 +35,14 @@ pub unsafe fn init(stack_start: usize, stack_end: usize) -> ActivePageTable {
static mut __data_start: u8;
/// The ending byte of the _.data_ segment.
static mut __data_end: u8;
/// The starting byte of the thread data segment
static mut __tdata_start: u8;
/// The ending byte of the thread data segment
static mut __tdata_end: u8;
/// The starting byte of the thread BSS segment
static mut __tbss_start: u8;
/// The ending byte of the thread BSS segment
static mut __tbss_end: u8;
/// The starting byte of the _.bss_ (uninitialized data) segment.
static mut __bss_start: u8;
/// The ending byte of the _.bss_ (uninitialized data) segment.
@ -51,64 +59,73 @@ pub unsafe fn init(stack_start: usize, stack_end: usize) -> ActivePageTable {
};
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let mut remap = |start: usize, end: usize, flags: EntryFlags| {
let start_frame = Frame::containing_address(PhysicalAddress::new(start));
let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1));
for frame in Frame::range_inclusive(start_frame, end_frame) {
mapper.identity_map(frame, flags);
}
};
{
let mut remap = |start: usize, end: usize, flags: EntryFlags| {
let start_frame = Frame::containing_address(PhysicalAddress::new(start));
let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1));
for frame in Frame::range_inclusive(start_frame, end_frame) {
mapper.identity_map(frame, flags);
}
};
// Remap stack writable, no execute
remap(stack_start, stack_end, PRESENT | WRITABLE | NO_EXECUTE);
// Remap stack writable, no execute
remap(stack_start, stack_end, PRESENT | NO_EXECUTE | WRITABLE);
// Remap a section with `flags`
let mut remap_section = |start: &u8, end: &u8, flags: EntryFlags| {
remap(start as *const _ as usize, end as *const _ as usize, flags);
};
// Remap text read-only
remap_section(& __text_start, & __text_end, PRESENT);
// Remap rodata read-only, no execute
remap_section(& __rodata_start, & __rodata_end, PRESENT | NO_EXECUTE);
// Remap data writable, no execute
remap_section(& __data_start, & __data_end, PRESENT | NO_EXECUTE | WRITABLE);
// Remap bss writable, no execute
remap_section(& __bss_start, & __bss_end, PRESENT | NO_EXECUTE | WRITABLE);
});
active_table.switch(new_table);
active_table
}
/// Initialize paging for AP
pub unsafe fn init_ap(stack_start: usize, stack_end: usize, bsp_page_table: usize) -> ActivePageTable {
let mut active_table = ActivePageTable::new();
let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(0x8_0000_0000)));
let mut new_table = {
let frame = Frame::containing_address(PhysicalAddress::new(bsp_page_table));
InactivePageTable {
p4_frame: frame
// Remap a section with `flags`
let mut remap_section = |start: &u8, end: &u8, flags: EntryFlags| {
remap(start as *const _ as usize, end as *const _ as usize, flags);
};
// Remap text read-only
remap_section(& __text_start, & __text_end, PRESENT);
// Remap rodata read-only, no execute
remap_section(& __rodata_start, & __rodata_end, PRESENT | NO_EXECUTE);
// Remap data writable, no execute
remap_section(& __data_start, & __data_end, PRESENT | NO_EXECUTE | WRITABLE);
// Remap bss writable, no execute
remap_section(& __bss_start, & __bss_end, PRESENT | NO_EXECUTE | WRITABLE);
}
};
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
let mut remap = |start: usize, end: usize, flags: EntryFlags| {
let start_frame = Frame::containing_address(PhysicalAddress::new(start));
let end_frame = Frame::containing_address(PhysicalAddress::new(end - 1));
for frame in Frame::range_inclusive(start_frame, end_frame) {
mapper.identity_map(frame, flags);
}
};
// Remap stack writable, no execute
remap(stack_start, stack_end, PRESENT | WRITABLE | NO_EXECUTE);
});
active_table.switch(new_table);
// Map and copy TDATA
{
temporary_page.map(allocate_frame().expect("no more frames"), PRESENT | NO_EXECUTE | WRITABLE, &mut active_table);
let start = & __tbss_start as *const _ as usize;
let end = & __tbss_end as *const _ as usize;
let start_page = Page::containing_address(VirtualAddress::new(start));
let end_page = Page::containing_address(VirtualAddress::new(end - 1));
for page in Page::range_inclusive(start_page, end_page) {
// Copy master to temporary page
{
let frame = Frame::containing_address(PhysicalAddress::new(page.start_address().get()));
active_table.identity_map(frame, PRESENT | NO_EXECUTE);
::externs::memcpy(temporary_page.start_address().get() as *mut u8, page.start_address().get() as *const u8, 4096);
active_table.unmap(page);
}
// Copy temporary page to CPU copy
{
active_table.map(page, PRESENT | NO_EXECUTE | WRITABLE);
::externs::memcpy(page.start_address().get() as *mut u8, temporary_page.start_address().get() as *const u8, 4096);
}
}
temporary_page.unmap(&mut active_table);
}
// Map and clear TBSS
{
let start = & __tbss_start as *const _ as usize;
let end = & __tbss_end as *const _ as usize;
let start_page = Page::containing_address(VirtualAddress::new(start));
let end_page = Page::containing_address(VirtualAddress::new(end - 1));
for page in Page::range_inclusive(start_page, end_page) {
active_table.map(page, PRESENT | NO_EXECUTE | WRITABLE);
::externs::memset(page.start_address().get() as *mut u8, 0, 4096);
}
}
active_table
}
@ -237,19 +254,19 @@ impl Page {
VirtualAddress::new(self.number * PAGE_SIZE)
}
fn p4_index(&self) -> usize {
pub fn p4_index(&self) -> usize {
(self.number >> 27) & 0o777
}
fn p3_index(&self) -> usize {
pub fn p3_index(&self) -> usize {
(self.number >> 18) & 0o777
}
fn p2_index(&self) -> usize {
pub fn p2_index(&self) -> usize {
(self.number >> 9) & 0o777
}
fn p1_index(&self) -> usize {
pub fn p1_index(&self) -> usize {
(self.number >> 0) & 0o777
}

View file

@ -63,10 +63,10 @@ impl<L> Table<L> where L: HierarchicalLevel {
pub fn next_table_create(&mut self, index: usize) -> &mut Table<L::NextLevel> {
if self.next_table(index).is_none() {
assert!(!self.entries[index].flags().contains(HUGE_PAGE),
assert!(!self[index].flags().contains(HUGE_PAGE),
"mapping code does not support huge pages");
let frame = allocate_frame().expect("no frames available");
self.entries[index].set(frame, PRESENT | WRITABLE);
self[index].set(frame, PRESENT | WRITABLE);
self.next_table_mut(index).unwrap().zero();
}
self.next_table_mut(index).unwrap()

View file

@ -18,6 +18,10 @@ impl TemporaryPage {
}
}
pub fn start_address (&self) -> VirtualAddress {
self.page.start_address()
}
/// Maps the temporary page to the given frame in the active table.
/// Returns the start address of the temporary page.
pub fn map(&mut self, frame: Frame, flags: EntryFlags, active_table: &mut ActivePageTable) -> VirtualAddress {