diff --git a/src/paging/mapper.rs b/src/paging/mapper.rs index ff861440bfb3219e356d375b9872c7366eb11a55..f66d1c5cf46aae4c9c401428a1f0fa5f731bc507 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 8a33987bc0c15c7830609f0544ad2ff4f4c16b90..f97f268ed3be18f52f4e2a110f9c71b654fc5510 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();