From 800e6c6de758062909bd346459e2ac61d73a1a1a Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Sat, 15 Apr 2017 19:22:17 -0600 Subject: [PATCH] Free page tables during unmap, if empty --- src/paging/mapper.rs | 70 ++++++++++++++++++++++++++++++++++---------- src/paging/table.rs | 10 +++++++ 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/src/paging/mapper.rs b/src/paging/mapper.rs index ff861440..f66d1c5c 100644 --- a/src/paging/mapper.rs +++ b/src/paging/mapper.rs @@ -133,29 +133,69 @@ impl Mapper { self.map_to(page, frame, flags) } + fn unmap_inner(&mut self, page: &Page) -> Frame { + let frame; + + let p4 = self.p4_mut(); + { + let p3 = p4.next_table_mut(page.p4_index()).expect("unmap_inner: p3 not found"); + { + let p2 = p3.next_table_mut(page.p3_index()).expect("unmap_inner: p2 not found"); + { + let p1 = p2.next_table_mut(page.p2_index()).expect("unmap_inner: p1 not found"); + + frame = p1[page.p1_index()].pointed_frame().expect("unmap_inner: frame not found"); + p1[page.p1_index()].set_unused(); + + if ! p1.is_unused() { + return frame; + } + } + + { + let p1_frame = p2[page.p2_index()].pointed_frame().expect("unmap_inner: p1 frame not found"); + println!("Free p1 {:?}", p1_frame); + p2[page.p2_index()].set_unused(); + deallocate_frames(p1_frame, 1); + } + + if ! p2.is_unused() { + return frame; + } + } + + { + let p2_frame = p3[page.p3_index()].pointed_frame().expect("unmap_inner: p2 frame not found"); + println!("Free p2 {:?}", p2_frame); + p3[page.p3_index()].set_unused(); + deallocate_frames(p2_frame, 1); + } + + if ! p3.is_unused() { + return frame; + } + } + + { + let p3_frame = p4[page.p4_index()].pointed_frame().expect("unmap_inner: p3 frame not found"); + println!("Free p3 {:?}", p3_frame); + p4[page.p2_index()].set_unused(); + deallocate_frames(p3_frame, 1); + } + + frame + } + /// Unmap a page pub fn unmap(&mut self, page: Page) -> MapperFlush { - let p1 = self.p4_mut() - .next_table_mut(page.p4_index()) - .and_then(|p3| p3.next_table_mut(page.p3_index())) - .and_then(|p2| p2.next_table_mut(page.p2_index())) - .expect("unmap does not support huge pages"); - let frame = p1[page.p1_index()].pointed_frame().unwrap(); - p1[page.p1_index()].set_unused(); - // TODO free p(1,2,3) table if empty + let frame = self.unmap_inner(&page); deallocate_frames(frame, 1); MapperFlush::new(page) } /// Unmap a page, return frame without free pub fn unmap_return(&mut self, page: Page) -> (MapperFlush, Frame) { - let p1 = self.p4_mut() - .next_table_mut(page.p4_index()) - .and_then(|p3| p3.next_table_mut(page.p3_index())) - .and_then(|p2| p2.next_table_mut(page.p2_index())) - .expect("unmap_return does not support huge pages"); - let frame = p1[page.p1_index()].pointed_frame().unwrap(); - p1[page.p1_index()].set_unused(); + let frame = self.unmap_inner(&page); (MapperFlush::new(page), frame) } diff --git a/src/paging/table.rs b/src/paging/table.rs index 8a33987b..f97f268e 100644 --- a/src/paging/table.rs +++ b/src/paging/table.rs @@ -45,6 +45,16 @@ 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; + } + } + + true + } + pub fn zero(&mut self) { for entry in self.entries.iter_mut() { entry.set_unused(); -- GitLab