Merge pull request #66 from weclaw1/page_table_optimization
Page table optimization
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user