From a48ec82f20a06c7b7052122b5d8e3f070aea42d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20W=C4=99c=C5=82awski?= Date: Sun, 17 Dec 2017 16:53:20 +0100 Subject: [PATCH 1/7] Use unused bits 52-61 in first entry of each page table as counter for number of page table entries --- src/arch/x86_64/paging/entry.rs | 10 ++++++++++ src/arch/x86_64/paging/mapper.rs | 9 +++++++-- src/arch/x86_64/paging/table.rs | 28 ++++++++++++++++++++++++---- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/arch/x86_64/paging/entry.rs b/src/arch/x86_64/paging/entry.rs index 1673819..ea657e6 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 79b9f36..c2cc592 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 4e9ae6d..1950719 100644 --- a/src/arch/x86_64/paging/table.rs +++ b/src/arch/x86_64/paging/table.rs @@ -46,10 +46,8 @@ pub struct Table { impl Table 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 Table 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 Table where L: HierarchicalLevel { @@ -76,6 +95,7 @@ impl Table 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(); } From ab687852d388622b852b399d653054380b187d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20W=C4=99c=C5=82awski?= Date: Sun, 17 Dec 2017 17:19:06 +0100 Subject: [PATCH 2/7] Convert entry count to u64, remove unnecessary parentheses --- src/arch/x86_64/paging/entry.rs | 2 +- src/arch/x86_64/paging/table.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/x86_64/paging/entry.rs b/src/arch/x86_64/paging/entry.rs index ea657e6..38ec68e 100644 --- a/src/arch/x86_64/paging/entry.rs +++ b/src/arch/x86_64/paging/entry.rs @@ -67,6 +67,6 @@ impl Entry { /// 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)); + self.0 = (self.0 & 0xc00fffff_ffffffff) | (count << 52); } } diff --git a/src/arch/x86_64/paging/table.rs b/src/arch/x86_64/paging/table.rs index 1950719..4f6e4ac 100644 --- a/src/arch/x86_64/paging/table.rs +++ b/src/arch/x86_64/paging/table.rs @@ -61,7 +61,7 @@ impl Table where L: TableLevel { /// 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"); + assert!(count <= ENTRY_COUNT as u64, "count can't be greater than ENTRY_COUNT"); self.entries[0].set_counter_bits(count); } From 82bae0b314e42e4007d1c40cfc597b58992a0787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20W=C4=99c=C5=82awski?= Date: Sun, 17 Dec 2017 18:22:27 +0100 Subject: [PATCH 3/7] entry::set doesn't reset counter, counter mask is a const --- src/arch/x86_64/paging/entry.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/arch/x86_64/paging/entry.rs b/src/arch/x86_64/paging/entry.rs index 38ec68e..f5d567f 100644 --- a/src/arch/x86_64/paging/entry.rs +++ b/src/arch/x86_64/paging/entry.rs @@ -24,6 +24,7 @@ bitflags! { } pub const ADDRESS_MASK: usize = 0x000f_ffff_ffff_f000; +pub const COUNTER_MASK: u64 = 0x3ff00000_00000000; impl Entry { /// Is the entry unused? @@ -57,16 +58,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 & 0x3ff00000_00000000) >> 52 + (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 & 0xc00fffff_ffffffff) | (count << 52); + self.0 = (self.0 & !COUNTER_MASK) | (count << 52); } } From 2d041bbb51ce1be75c055a6d9f8f57d7614efe2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20W=C4=99c=C5=82awski?= Date: Sun, 17 Dec 2017 18:45:41 +0100 Subject: [PATCH 4/7] don't change counter in set_unused --- src/arch/x86_64/paging/entry.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/arch/x86_64/paging/entry.rs b/src/arch/x86_64/paging/entry.rs index f5d567f..d9898bf 100644 --- a/src/arch/x86_64/paging/entry.rs +++ b/src/arch/x86_64/paging/entry.rs @@ -29,12 +29,12 @@ pub const COUNTER_MASK: u64 = 0x3ff00000_00000000; impl Entry { /// 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 From 08a4c33b77c75a1b04846cbad2214b3672ae87b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20W=C4=99c=C5=82awski?= Date: Sun, 17 Dec 2017 19:46:19 +0100 Subject: [PATCH 5/7] New entries are set to zero --- src/arch/x86_64/paging/entry.rs | 5 +++++ src/arch/x86_64/paging/table.rs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/arch/x86_64/paging/entry.rs b/src/arch/x86_64/paging/entry.rs index d9898bf..af8fc75 100644 --- a/src/arch/x86_64/paging/entry.rs +++ b/src/arch/x86_64/paging/entry.rs @@ -27,6 +27,11 @@ pub const ADDRESS_MASK: usize = 0x000f_ffff_ffff_f000; pub const COUNTER_MASK: u64 = 0x3ff00000_00000000; impl Entry { + /// Zero entry + pub fn set_zero(&mut self) { + self.0 = 0; + } + /// Is the entry unused? pub fn is_unused(&self) -> bool { self.0 == (self.0 & COUNTER_MASK) diff --git a/src/arch/x86_64/paging/table.rs b/src/arch/x86_64/paging/table.rs index 4f6e4ac..3299a12 100644 --- a/src/arch/x86_64/paging/table.rs +++ b/src/arch/x86_64/paging/table.rs @@ -55,7 +55,7 @@ impl Table where L: TableLevel { pub fn zero(&mut self) { for entry in self.entries.iter_mut() { - entry.set_unused(); + entry.set_zero(); } } From a8ecfc86ddb52e7f5c3c00414729c180b2a41267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20W=C4=99c=C5=82awski?= Date: Sun, 17 Dec 2017 19:54:52 +0100 Subject: [PATCH 6/7] Better comment and mask representation --- src/arch/x86_64/paging/entry.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/arch/x86_64/paging/entry.rs b/src/arch/x86_64/paging/entry.rs index af8fc75..f031f62 100644 --- a/src/arch/x86_64/paging/entry.rs +++ b/src/arch/x86_64/paging/entry.rs @@ -24,14 +24,14 @@ bitflags! { } pub const ADDRESS_MASK: usize = 0x000f_ffff_ffff_f000; -pub const COUNTER_MASK: u64 = 0x3ff00000_00000000; +pub const COUNTER_MASK: u64 = 0x3ff0_0000_0000_0000; impl Entry { - /// Zero entry + /// Clear entry pub fn set_zero(&mut self) { self.0 = 0; } - + /// Is the entry unused? pub fn is_unused(&self) -> bool { self.0 == (self.0 & COUNTER_MASK) From 3c466892de025d4e46f9fe72b56e2c7f4beb5a79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20W=C4=99c=C5=82awski?= Date: Sun, 17 Dec 2017 20:29:35 +0100 Subject: [PATCH 7/7] change assert to debug_assert --- src/arch/x86_64/paging/table.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/x86_64/paging/table.rs b/src/arch/x86_64/paging/table.rs index 3299a12..6784560 100644 --- a/src/arch/x86_64/paging/table.rs +++ b/src/arch/x86_64/paging/table.rs @@ -61,7 +61,7 @@ impl Table where L: TableLevel { /// Set number of entries in first table entry fn set_entry_count(&mut self, count: u64) { - assert!(count <= ENTRY_COUNT as u64, "count can't be greater than ENTRY_COUNT"); + debug_assert!(count <= ENTRY_COUNT as u64, "count can't be greater than ENTRY_COUNT"); self.entries[0].set_counter_bits(count); }