diff --git a/src/arch/x86_64/paging/entry.rs b/src/arch/x86_64/paging/entry.rs index 167381947ea001488ecad5b4077412d18172e711..ea657e6e0d21aec6702f88b3048bfc76281e8862 100644 --- a/src/arch/x86_64/paging/entry.rs +++ b/src/arch/x86_64/paging/entry.rs @@ -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)); + } } diff --git a/src/arch/x86_64/paging/mapper.rs b/src/arch/x86_64/paging/mapper.rs index 79b9f3609b22119e2e508c67f6373a8482264c6b..c2cc5923fd413dc5f8648105426ab8449d29c314 100644 --- a/src/arch/x86_64/paging/mapper.rs +++ b/src/arch/x86_64/paging/mapper.rs @@ -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 { diff --git a/src/arch/x86_64/paging/table.rs b/src/arch/x86_64/paging/table.rs index 4e9ae6ddcf1ef3600585ab1a35b8f18697d6658c..1950719faf8ef4b4e76f1be10a5cd4bab87ad663 100644 --- a/src/arch/x86_64/paging/table.rs +++ b/src/arch/x86_64/paging/table.rs @@ -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(); }