diff --git a/src/kvm.rs b/src/kvm.rs index 8024d88..f004243 100644 --- a/src/kvm.rs +++ b/src/kvm.rs @@ -88,11 +88,8 @@ struct PageMapper { impl PageTableVisitor for PageMapper { type Output = Result<(), &'static str>; - fn check_va(&mut self, va: VirtAddr) -> Self::Output { - if va >= VirtAddr::new(MAXVA) { - return Err("map_page: virtual address over MAX address") - } - Ok(()) + fn is_valid_va(&self, va: VirtAddr) -> bool { + va < VirtAddr::new(MAXVA) } fn leaf(&mut self, pte: &mut PageTableEntry) -> Self::Output { @@ -123,11 +120,8 @@ struct PageUnmapper { impl PageTableVisitor for PageUnmapper { type Output = Result<(), &'static str>; - fn check_va(&mut self, va: VirtAddr) -> Self::Output { - if va >= VirtAddr::new(MAXVA) { - return Err("unmap_page: virtual address over MAX address") - } - Ok(()) + fn is_valid_va(&self, va: VirtAddr) -> bool { + va < VirtAddr::new(MAXVA) } fn leaf(&mut self, pte: &mut PageTableEntry) -> Self::Output { @@ -161,12 +155,12 @@ fn map_pages(page_table: &mut PageTable, va: VirtAddr, mut pa: PhysAddr, size: u loop { let mapper = PageMapper { pa, perm }; - let mut walker = PageTableWalkerMut { + let mut walker = PageTableWalkerMut::new( page_table, - va: page_addr, - level: PageTableLevel::Two, - extra: mapper - }; + page_addr, + PageTableLevel::Two, + mapper + ).ok_or("map_page: virtual address over MAX address")?; walker.visit_mut()?; if page_addr == va_end { @@ -252,12 +246,12 @@ fn unmap_pages(page_table: &mut PageTable, va: VirtAddr, npages: u64, do_free: b let mut addr = va; while addr < va + npages * PAGESIZE { let unmapper = PageUnmapper { do_free }; - let mut walker = PageTableWalkerMut { + let mut walker = PageTableWalkerMut::new( page_table, - va: addr, - level: PageTableLevel::Two, - extra: unmapper, - }; + addr, + PageTableLevel::Two, + unmapper, + ).ok_or("unmap_page: virtual address over MAX address")?; walker.visit_mut()?; addr += PAGESIZE; diff --git a/src/vm/page_table_walker.rs b/src/vm/page_table_walker.rs index 1d059a3..e9d1cff 100644 --- a/src/vm/page_table_walker.rs +++ b/src/vm/page_table_walker.rs @@ -11,14 +11,23 @@ pub struct PageTableWalkerMut<'a, Extra> { pub trait PageTableVisitor { type Output : core::ops::Try; - fn check_va(&mut self, va: VirtAddr) -> Self::Output; + fn is_valid_va(&self, va: VirtAddr) -> bool; fn leaf(&mut self, pte: &mut PageTableEntry) -> Self::Output; fn nonleaf(&mut self, pte: &mut PageTableEntry) -> Self::Output; } -impl PageTableWalkerMut<'_, Extra> { +impl<'a, Extra: PageTableVisitor> PageTableWalkerMut<'a, Extra> { + pub fn new(page_table: &'a mut PageTable, va: VirtAddr, level: PageTableLevel, extra: Extra) -> Option { + extra.is_valid_va(va).then( + move || Self { + page_table, + va, + level, + extra + } + ) + } pub fn visit_mut(&mut self) -> Extra::Output { - let _ = self.extra.check_va(self.va)?; let index = self.va.get_index(self.level); let pte = &mut self.page_table[index];