From 2b5fabb2fdcfc0458f741c1ee52b2d693b80aca4 Mon Sep 17 00:00:00 2001 From: bunnie Date: Mon, 8 Apr 2024 12:40:42 +0800 Subject: [PATCH] add swap pt routines --- loader/src/bootconfig.rs | 67 +++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/loader/src/bootconfig.rs b/loader/src/bootconfig.rs index 3e0428125..7c6141ccc 100644 --- a/loader/src/bootconfig.rs +++ b/loader/src/bootconfig.rs @@ -62,11 +62,6 @@ pub struct BootConfig { #[cfg(feature = "swap")] pub swap: Option<&'static SwapDescriptor>, - /// Swap root page table. Array of root page tables, one per process. - /// Kernel does not get swap, so the first entry belongs to PID 2. - #[cfg(feature = "swap")] - pub swap_page_table: &'static mut [&'static mut PageTable], - /// Offset of the current free page in swap #[cfg(feature = "swap")] pub swap_free_page: usize, @@ -92,8 +87,6 @@ impl Default for BootConfig { #[cfg(feature = "swap")] swap: None, #[cfg(feature = "swap")] - swap_page_table: Default::default(), - #[cfg(feature = "swap")] swap_free_page: 0, } } @@ -182,6 +175,66 @@ impl BootConfig { } } + fn alloc_swap(&mut self) -> *mut usize { + self.init_size += PAGE_SIZE; + let pg = self.get_top(); + unsafe { + // Grab the page address and zero it out + bzero(pg as *mut usize, pg.add(PAGE_SIZE / mem::size_of::()) as *mut usize); + } + pg as *mut usize + } + + #[cfg(feature = "swap")] + pub fn map_swap(&mut self, swap_phys: usize, virt: usize, owner: XousPid) { + if SDBG { + println!(" swap pa {:x} -> va {:x}", swap_phys, virt); + } + let ppn1 = (swap_phys >> 22) & ((1 << 12) - 1); + let ppn0 = (swap_phys >> 12) & ((1 << 10) - 1); + + let vpn1 = (virt >> 22) & ((1 << 10) - 1); + let vpn0 = (virt >> 12) & ((1 << 10) - 1); + assert!(owner != 0); + let l1_pt = unsafe { + core::slice::from_raw_parts_mut( + self.processes[owner as usize - 1].swap_root as *mut usize, + mem::size_of::() / mem::size_of::(), + ) + }; + + // Allocate a new level 1 pagetable entry if one doesn't exist. + if l1_pt[vpn1] & FLG_VALID == 0 { + let na = self.alloc_swap() as usize; + if SDBG { + println!( + "Swap Level 1 page table is invalid ({:08x}) @ {:08x} -- allocating a new one @ {:08x}", + unsafe { l1_pt.as_ptr().add(vpn1) } as usize, + l1_pt[vpn1], + na + ); + } + // Mark this entry as a leaf node (WRX as 0), and indicate + // it is a valid page by setting "V". + l1_pt[vpn1] = ((na >> 12) << 10) | FLG_VALID; + } + + let l0_pt_idx = unsafe { &mut (*(((l1_pt[vpn1] << 2) & !((1 << 12) - 1)) as *mut PageTable)) }; + let l0_pt = &mut l0_pt_idx.entries; + + // Ensure the entry hasn't already been mapped to a different address. + if l0_pt[vpn0] & 1 != 0 && (l0_pt[vpn0] & 0xffff_fc00) != ((ppn1 << 20) | (ppn0 << 10)) { + panic!( + "Swap page {:08x} was already allocated to {:08x}, so cannot map to {:08x}!", + swap_phys, + (l0_pt[vpn0] >> 10) << 12, + virt + ); + } + let previous_flags = l0_pt[vpn0] & 0xf; + l0_pt[vpn0] = (ppn1 << 20) | (ppn0 << 10) | previous_flags | FLG_VALID; + } + pub fn map_page_32( &mut self, root: &mut PageTable,