Use unused bits 52-61 in first entry of each page table as counter for number of page table entries
This commit is contained in:
@@ -59,4 +59,14 @@ impl Entry {
|
||||
debug_assert!(frame.start_address().get() & !ADDRESS_MASK == 0);
|
||||
self.0 = (frame.start_address().get() as u64) | flags.bits();
|
||||
}
|
||||
|
||||
/// Get bits 52-61 in entry, used as counter for page table
|
||||
pub fn counter_bits(&self) -> u64 {
|
||||
(self.0 & 0x3ff00000_00000000) >> 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 & 0xc00fffff_ffffffff) | (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
|
||||
@@ -60,6 +58,27 @@ impl<L> Table<L> where L: TableLevel {
|
||||
entry.set_unused();
|
||||
}
|
||||
}
|
||||
|
||||
/// Set number of entries in first table entry
|
||||
fn set_entry_count(&mut self, count: u64) {
|
||||
assert!(count <= ENTRY_COUNT, "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