Merge pull request #66 from weclaw1/page_table_optimization

Page table optimization
This commit is contained in:
Jeremy Soller
2017-12-17 19:19:15 -07:00
committed by GitHub
3 changed files with 51 additions and 10 deletions

View File

@@ -24,16 +24,22 @@ bitflags! {
}
pub const ADDRESS_MASK: usize = 0x000f_ffff_ffff_f000;
pub const COUNTER_MASK: u64 = 0x3ff0_0000_0000_0000;
impl Entry {
/// Clear entry
pub fn set_zero(&mut self) {
self.0 = 0;
}
/// Is the entry unused?
pub fn is_unused(&self) -> bool {
self.0 == 0
self.0 == (self.0 & COUNTER_MASK)
}
/// Make the entry unused
pub fn set_unused(&mut self) {
self.0 = 0;
self.0 = self.0 & COUNTER_MASK;
}
/// Get the address this page references
@@ -57,6 +63,16 @@ impl Entry {
pub fn set(&mut self, frame: Frame, flags: EntryFlags) {
debug_assert!(frame.start_address().get() & !ADDRESS_MASK == 0);
self.0 = (frame.start_address().get() as u64) | flags.bits();
self.0 = (frame.start_address().get() as u64) | flags.bits() | (self.0 & COUNTER_MASK);
}
/// Get bits 52-61 in entry, used as counter for page table
pub fn counter_bits(&self) -> u64 {
(self.0 & COUNTER_MASK) >> 52
}
/// Set bits 52-61 in entry, used as counter for page table
pub fn set_counter_bits(&mut self, count: u64) {
self.0 = (self.0 & !COUNTER_MASK) | (count << 52);
}
}

View File

@@ -107,6 +107,7 @@ impl Mapper {
page.start_address().get(),
p1[page.p1_index()].address().get(), p1[page.p1_index()].flags(),
frame.start_address().get(), flags);
p1.increment_entry_count();
p1[page.p1_index()].set(frame, flags | EntryFlags::PRESENT);
MapperFlush::new(page)
}
@@ -146,6 +147,7 @@ impl Mapper {
panic!("unmap_inner({:X}): frame not found", page.start_address().get())
};
p1.decrement_entry_count();
p1[page.p1_index()].set_unused();
if keep_parents || ! p1.is_unused() {
@@ -157,13 +159,14 @@ impl Mapper {
if let Some(p1_frame) = p2[page.p2_index()].pointed_frame() {
//println!("Free p1 {:?}", p1_frame);
p2.decrement_entry_count();
p2[page.p2_index()].set_unused();
deallocate_frames(p1_frame, 1);
} else {
panic!("unmap_inner({:X}): p1_frame not found", page.start_address().get());
}
if keep_parents || ! p2.is_unused() {
if ! p2.is_unused() {
return frame;
}
} else {
@@ -172,13 +175,14 @@ impl Mapper {
if let Some(p2_frame) = p3[page.p3_index()].pointed_frame() {
//println!("Free p2 {:?}", p2_frame);
p3.decrement_entry_count();
p3[page.p3_index()].set_unused();
deallocate_frames(p2_frame, 1);
} else {
panic!("unmap_inner({:X}): p2_frame not found", page.start_address().get());
}
if keep_parents || ! p3.is_unused() {
if ! p3.is_unused() {
return frame;
}
} else {
@@ -187,6 +191,7 @@ impl Mapper {
if let Some(p3_frame) = p4[page.p4_index()].pointed_frame() {
//println!("Free p3 {:?}", p3_frame);
p4.decrement_entry_count();
p4[page.p4_index()].set_unused();
deallocate_frames(p3_frame, 1);
} else {

View File

@@ -46,10 +46,8 @@ pub struct Table<L: TableLevel> {
impl<L> Table<L> where L: TableLevel {
pub fn is_unused(&self) -> bool {
for entry in self.entries.iter() {
if ! entry.is_unused() {
return false;
}
if self.entry_count() > 0 {
return false;
}
true
@@ -57,9 +55,30 @@ impl<L> Table<L> where L: TableLevel {
pub fn zero(&mut self) {
for entry in self.entries.iter_mut() {
entry.set_unused();
entry.set_zero();
}
}
/// Set number of entries in first table entry
fn set_entry_count(&mut self, count: u64) {
debug_assert!(count <= ENTRY_COUNT as u64, "count can't be greater than ENTRY_COUNT");
self.entries[0].set_counter_bits(count);
}
/// Get number of entries in first table entry
fn entry_count(&self) -> u64 {
self.entries[0].counter_bits()
}
pub fn increment_entry_count(&mut self) {
let current_count = self.entry_count();
self.set_entry_count(current_count + 1);
}
pub fn decrement_entry_count(&mut self) {
let current_count = self.entry_count();
self.set_entry_count(current_count - 1);
}
}
impl<L> Table<L> where L: HierarchicalLevel {
@@ -76,6 +95,7 @@ impl<L> Table<L> where L: HierarchicalLevel {
assert!(!self[index].flags().contains(EntryFlags::HUGE_PAGE),
"next_table_create does not support huge pages");
let frame = allocate_frames(1).expect("no frames available");
self.increment_entry_count();
self[index].set(frame, EntryFlags::PRESENT | EntryFlags::WRITABLE | EntryFlags::USER_ACCESSIBLE /* Allow users to go down the page table, implement permissions at the page level */);
self.next_table_mut(index).unwrap().zero();
}