140fe15e0SLoGin use core::{ 240fe15e0SLoGin fmt::{self, Debug, Error, Formatter}, 340fe15e0SLoGin marker::PhantomData, 440fe15e0SLoGin mem, 540fe15e0SLoGin ops::Add, 640fe15e0SLoGin sync::atomic::{compiler_fence, Ordering}, 740fe15e0SLoGin }; 840fe15e0SLoGin 956cc4dbeSJomo use alloc::sync::Arc; 1056cc4dbeSJomo use hashbrown::{HashMap, HashSet}; 1156cc4dbeSJomo 1240fe15e0SLoGin use crate::{ 1340fe15e0SLoGin arch::{interrupt::ipi::send_ipi, MMArch}, 1440fe15e0SLoGin exception::ipi::{IpiKind, IpiTarget}, 1540fe15e0SLoGin kerror, kwarn, 1656cc4dbeSJomo libs::spinlock::{SpinLock, SpinLockGuard}, 1740fe15e0SLoGin }; 1840fe15e0SLoGin 1940fe15e0SLoGin use super::{ 2056cc4dbeSJomo allocator::page_frame::FrameAllocator, syscall::ProtFlags, ucontext::LockedVMA, 2156cc4dbeSJomo MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, 2240fe15e0SLoGin }; 2340fe15e0SLoGin 24*23ef2b33SLoGin pub const PAGE_4K_SHIFT: usize = 12; 25*23ef2b33SLoGin #[allow(dead_code)] 26*23ef2b33SLoGin pub const PAGE_2M_SHIFT: usize = 21; 27*23ef2b33SLoGin pub const PAGE_1G_SHIFT: usize = 30; 28*23ef2b33SLoGin 2956cc4dbeSJomo /// 全局物理页信息管理器 3056cc4dbeSJomo pub static mut PAGE_MANAGER: Option<SpinLock<PageManager>> = None; 3156cc4dbeSJomo 3256cc4dbeSJomo /// 初始化PAGE_MANAGER 3356cc4dbeSJomo pub fn page_manager_init() { 3456cc4dbeSJomo kinfo!("page_manager_init"); 3556cc4dbeSJomo let page_manager = SpinLock::new(PageManager::new()); 3656cc4dbeSJomo 3756cc4dbeSJomo compiler_fence(Ordering::SeqCst); 3856cc4dbeSJomo unsafe { PAGE_MANAGER = Some(page_manager) }; 3956cc4dbeSJomo compiler_fence(Ordering::SeqCst); 4056cc4dbeSJomo 4156cc4dbeSJomo kinfo!("page_manager_init done"); 4256cc4dbeSJomo } 4356cc4dbeSJomo 4456cc4dbeSJomo pub fn page_manager_lock_irasave() -> SpinLockGuard<'static, PageManager> { 4556cc4dbeSJomo unsafe { PAGE_MANAGER.as_ref().unwrap().lock_irqsave() } 4656cc4dbeSJomo } 4756cc4dbeSJomo 4856cc4dbeSJomo // 物理页管理器 4956cc4dbeSJomo pub struct PageManager { 5056cc4dbeSJomo phys2page: HashMap<PhysAddr, Page>, 5156cc4dbeSJomo } 5256cc4dbeSJomo 5356cc4dbeSJomo impl PageManager { 5456cc4dbeSJomo pub fn new() -> Self { 5556cc4dbeSJomo Self { 5656cc4dbeSJomo phys2page: HashMap::new(), 5756cc4dbeSJomo } 5856cc4dbeSJomo } 5956cc4dbeSJomo 6056cc4dbeSJomo pub fn get_mut(&mut self, paddr: &PhysAddr) -> &mut Page { 6156cc4dbeSJomo self.phys2page.get_mut(paddr).unwrap() 6256cc4dbeSJomo } 6356cc4dbeSJomo 6456cc4dbeSJomo pub fn insert(&mut self, paddr: PhysAddr, page: Page) { 6556cc4dbeSJomo self.phys2page.insert(paddr, page); 6656cc4dbeSJomo } 6756cc4dbeSJomo 6856cc4dbeSJomo pub fn remove_page(&mut self, paddr: &PhysAddr) { 6956cc4dbeSJomo self.phys2page.remove(paddr); 7056cc4dbeSJomo } 7156cc4dbeSJomo } 7256cc4dbeSJomo 7356cc4dbeSJomo /// 物理页面信息 7456cc4dbeSJomo pub struct Page { 7556cc4dbeSJomo /// 映射计数 7656cc4dbeSJomo map_count: usize, 7756cc4dbeSJomo /// 是否为共享页 7856cc4dbeSJomo shared: bool, 7956cc4dbeSJomo /// 映射到当前page的VMA 8056cc4dbeSJomo anon_vma: HashSet<Arc<LockedVMA>>, 8156cc4dbeSJomo } 8256cc4dbeSJomo 8356cc4dbeSJomo impl Page { 8456cc4dbeSJomo pub fn new(shared: bool) -> Self { 8556cc4dbeSJomo Self { 8656cc4dbeSJomo map_count: 0, 8756cc4dbeSJomo shared, 8856cc4dbeSJomo anon_vma: HashSet::new(), 8956cc4dbeSJomo } 9056cc4dbeSJomo } 9156cc4dbeSJomo 9256cc4dbeSJomo /// 将vma加入anon_vma 9356cc4dbeSJomo pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) { 9456cc4dbeSJomo self.anon_vma.insert(vma); 9556cc4dbeSJomo self.map_count += 1; 9656cc4dbeSJomo } 9756cc4dbeSJomo 9856cc4dbeSJomo /// 将vma从anon_vma中删去 9956cc4dbeSJomo pub fn remove_vma(&mut self, vma: &LockedVMA) { 10056cc4dbeSJomo self.anon_vma.remove(vma); 10156cc4dbeSJomo self.map_count -= 1; 10256cc4dbeSJomo } 10356cc4dbeSJomo 10456cc4dbeSJomo /// 判断当前物理页是否能被回 10556cc4dbeSJomo pub fn can_deallocate(&self) -> bool { 10656cc4dbeSJomo self.map_count == 0 && !self.shared 10756cc4dbeSJomo } 10856cc4dbeSJomo } 10956cc4dbeSJomo 11040fe15e0SLoGin #[derive(Debug)] 11140fe15e0SLoGin pub struct PageTable<Arch> { 11240fe15e0SLoGin /// 当前页表表示的虚拟地址空间的起始地址 11340fe15e0SLoGin base: VirtAddr, 11440fe15e0SLoGin /// 当前页表所在的物理地址 11540fe15e0SLoGin phys: PhysAddr, 11640fe15e0SLoGin /// 当前页表的层级(请注意,最顶级页表的level为[Arch::PAGE_LEVELS - 1]) 11740fe15e0SLoGin level: usize, 11840fe15e0SLoGin phantom: PhantomData<Arch>, 11940fe15e0SLoGin } 12040fe15e0SLoGin 12140fe15e0SLoGin #[allow(dead_code)] 12240fe15e0SLoGin impl<Arch: MemoryManagementArch> PageTable<Arch> { 12340fe15e0SLoGin pub unsafe fn new(base: VirtAddr, phys: PhysAddr, level: usize) -> Self { 12440fe15e0SLoGin Self { 12540fe15e0SLoGin base, 12640fe15e0SLoGin phys, 12740fe15e0SLoGin level, 12840fe15e0SLoGin phantom: PhantomData, 12940fe15e0SLoGin } 13040fe15e0SLoGin } 13140fe15e0SLoGin 13240fe15e0SLoGin /// 获取顶级页表 13340fe15e0SLoGin /// 13440fe15e0SLoGin /// ## 参数 13540fe15e0SLoGin /// 13640fe15e0SLoGin /// - table_kind 页表类型 13740fe15e0SLoGin /// 13840fe15e0SLoGin /// ## 返回值 13940fe15e0SLoGin /// 14040fe15e0SLoGin /// 返回顶级页表 14140fe15e0SLoGin pub unsafe fn top_level_table(table_kind: PageTableKind) -> Self { 14240fe15e0SLoGin return Self::new( 14340fe15e0SLoGin VirtAddr::new(0), 14440fe15e0SLoGin Arch::table(table_kind), 14540fe15e0SLoGin Arch::PAGE_LEVELS - 1, 14640fe15e0SLoGin ); 14740fe15e0SLoGin } 14840fe15e0SLoGin 14940fe15e0SLoGin /// 获取当前页表的物理地址 15040fe15e0SLoGin #[inline(always)] 15140fe15e0SLoGin pub fn phys(&self) -> PhysAddr { 15240fe15e0SLoGin self.phys 15340fe15e0SLoGin } 15440fe15e0SLoGin 15540fe15e0SLoGin /// 当前页表表示的虚拟地址空间的起始地址 15640fe15e0SLoGin #[inline(always)] 15740fe15e0SLoGin pub fn base(&self) -> VirtAddr { 15840fe15e0SLoGin self.base 15940fe15e0SLoGin } 16040fe15e0SLoGin 16140fe15e0SLoGin /// 获取当前页表的层级 16240fe15e0SLoGin #[inline(always)] 16340fe15e0SLoGin pub fn level(&self) -> usize { 16440fe15e0SLoGin self.level 16540fe15e0SLoGin } 16640fe15e0SLoGin 16740fe15e0SLoGin /// 获取当前页表自身所在的虚拟地址 16840fe15e0SLoGin #[inline(always)] 16940fe15e0SLoGin pub unsafe fn virt(&self) -> VirtAddr { 17040fe15e0SLoGin return Arch::phys_2_virt(self.phys).unwrap(); 17140fe15e0SLoGin } 17240fe15e0SLoGin 17340fe15e0SLoGin /// 获取第i个页表项所表示的虚拟内存空间的起始地址 17440fe15e0SLoGin pub fn entry_base(&self, i: usize) -> Option<VirtAddr> { 17540fe15e0SLoGin if i < Arch::PAGE_ENTRY_NUM { 17640fe15e0SLoGin let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT; 17740fe15e0SLoGin return Some(self.base.add(i << shift)); 17840fe15e0SLoGin } else { 17940fe15e0SLoGin return None; 18040fe15e0SLoGin } 18140fe15e0SLoGin } 18240fe15e0SLoGin 18340fe15e0SLoGin /// 获取当前页表的第i个页表项所在的虚拟地址(注意与entry_base进行区分) 18440fe15e0SLoGin pub unsafe fn entry_virt(&self, i: usize) -> Option<VirtAddr> { 18540fe15e0SLoGin if i < Arch::PAGE_ENTRY_NUM { 18640fe15e0SLoGin return Some(self.virt().add(i * Arch::PAGE_ENTRY_SIZE)); 18740fe15e0SLoGin } else { 18840fe15e0SLoGin return None; 18940fe15e0SLoGin } 19040fe15e0SLoGin } 19140fe15e0SLoGin 19240fe15e0SLoGin /// 获取当前页表的第i个页表项 19340fe15e0SLoGin pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> { 19440fe15e0SLoGin let entry_virt = self.entry_virt(i)?; 1957a29d4fcSLoGin return Some(PageEntry::from_usize(Arch::read::<usize>(entry_virt))); 19640fe15e0SLoGin } 19740fe15e0SLoGin 19840fe15e0SLoGin /// 设置当前页表的第i个页表项 19940fe15e0SLoGin pub unsafe fn set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()> { 20040fe15e0SLoGin let entry_virt = self.entry_virt(i)?; 20140fe15e0SLoGin Arch::write::<usize>(entry_virt, entry.data()); 20240fe15e0SLoGin return Some(()); 20340fe15e0SLoGin } 20440fe15e0SLoGin 20540fe15e0SLoGin /// 判断当前页表的第i个页表项是否已经填写了值 20640fe15e0SLoGin /// 20740fe15e0SLoGin /// ## 参数 20840fe15e0SLoGin /// - Some(true) 如果已经填写了值 20940fe15e0SLoGin /// - Some(false) 如果未填写值 21040fe15e0SLoGin /// - None 如果i超出了页表项的范围 21140fe15e0SLoGin pub fn entry_mapped(&self, i: usize) -> Option<bool> { 21240fe15e0SLoGin let etv = unsafe { self.entry_virt(i) }?; 21340fe15e0SLoGin if unsafe { Arch::read::<usize>(etv) } != 0 { 21440fe15e0SLoGin return Some(true); 21540fe15e0SLoGin } else { 21640fe15e0SLoGin return Some(false); 21740fe15e0SLoGin } 21840fe15e0SLoGin } 21940fe15e0SLoGin 22040fe15e0SLoGin /// 根据虚拟地址,获取对应的页表项在页表中的下标 22140fe15e0SLoGin /// 22240fe15e0SLoGin /// ## 参数 22340fe15e0SLoGin /// 22440fe15e0SLoGin /// - addr: 虚拟地址 22540fe15e0SLoGin /// 22640fe15e0SLoGin /// ## 返回值 22740fe15e0SLoGin /// 22840fe15e0SLoGin /// 页表项在页表中的下标。如果addr不在当前页表所表示的虚拟地址空间中,则返回None 22940fe15e0SLoGin pub unsafe fn index_of(&self, addr: VirtAddr) -> Option<usize> { 23040fe15e0SLoGin let addr = VirtAddr::new(addr.data() & Arch::PAGE_ADDRESS_MASK); 23140fe15e0SLoGin let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT; 23240fe15e0SLoGin 23340fe15e0SLoGin let mask = (MMArch::PAGE_ENTRY_NUM << shift) - 1; 23440fe15e0SLoGin if addr < self.base || addr >= self.base.add(mask) { 23540fe15e0SLoGin return None; 23640fe15e0SLoGin } else { 23740fe15e0SLoGin return Some((addr.data() >> shift) & MMArch::PAGE_ENTRY_MASK); 23840fe15e0SLoGin } 23940fe15e0SLoGin } 24040fe15e0SLoGin 24140fe15e0SLoGin /// 获取第i个页表项指向的下一级页表 24240fe15e0SLoGin pub unsafe fn next_level_table(&self, index: usize) -> Option<Self> { 24340fe15e0SLoGin if self.level == 0 { 24440fe15e0SLoGin return None; 24540fe15e0SLoGin } 24640fe15e0SLoGin 24740fe15e0SLoGin // 返回下一级页表 24840fe15e0SLoGin return Some(PageTable::new( 24940fe15e0SLoGin self.entry_base(index)?, 25040fe15e0SLoGin self.entry(index)?.address().ok()?, 25140fe15e0SLoGin self.level - 1, 25240fe15e0SLoGin )); 25340fe15e0SLoGin } 25440fe15e0SLoGin } 25540fe15e0SLoGin 25640fe15e0SLoGin /// 页表项 25740fe15e0SLoGin #[derive(Copy, Clone)] 25840fe15e0SLoGin pub struct PageEntry<Arch> { 25940fe15e0SLoGin data: usize, 26040fe15e0SLoGin phantom: PhantomData<Arch>, 26140fe15e0SLoGin } 26240fe15e0SLoGin 26340fe15e0SLoGin impl<Arch> Debug for PageEntry<Arch> { 26440fe15e0SLoGin fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { 26540fe15e0SLoGin f.write_fmt(format_args!("PageEntry({:#x})", self.data)) 26640fe15e0SLoGin } 26740fe15e0SLoGin } 26840fe15e0SLoGin 26940fe15e0SLoGin impl<Arch: MemoryManagementArch> PageEntry<Arch> { 27040fe15e0SLoGin #[inline(always)] 2717a29d4fcSLoGin pub fn new(paddr: PhysAddr, flags: PageFlags<Arch>) -> Self { 2727a29d4fcSLoGin Self { 2737a29d4fcSLoGin data: MMArch::make_entry(paddr, flags.data()), 2747a29d4fcSLoGin phantom: PhantomData, 2757a29d4fcSLoGin } 2767a29d4fcSLoGin } 2777a29d4fcSLoGin #[inline(always)] 2787a29d4fcSLoGin pub fn from_usize(data: usize) -> Self { 27940fe15e0SLoGin Self { 28040fe15e0SLoGin data, 28140fe15e0SLoGin phantom: PhantomData, 28240fe15e0SLoGin } 28340fe15e0SLoGin } 28440fe15e0SLoGin 28540fe15e0SLoGin #[inline(always)] 28640fe15e0SLoGin pub fn data(&self) -> usize { 28740fe15e0SLoGin self.data 28840fe15e0SLoGin } 28940fe15e0SLoGin 29040fe15e0SLoGin /// 获取当前页表项指向的物理地址 29140fe15e0SLoGin /// 29240fe15e0SLoGin /// ## 返回值 29340fe15e0SLoGin /// 29440fe15e0SLoGin /// - Ok(PhysAddr) 如果当前页面存在于物理内存中, 返回物理地址 29540fe15e0SLoGin /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址 29640fe15e0SLoGin #[inline(always)] 29740fe15e0SLoGin pub fn address(&self) -> Result<PhysAddr, PhysAddr> { 2987a29d4fcSLoGin let paddr: PhysAddr = { 2997a29d4fcSLoGin #[cfg(target_arch = "x86_64")] 3007a29d4fcSLoGin { 3017a29d4fcSLoGin PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK) 3027a29d4fcSLoGin } 3037a29d4fcSLoGin 3047a29d4fcSLoGin #[cfg(target_arch = "riscv64")] 3057a29d4fcSLoGin { 306453452ccSLoGin let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 54) - 1); 3077a29d4fcSLoGin super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address() 3087a29d4fcSLoGin } 3097a29d4fcSLoGin }; 31040fe15e0SLoGin 31140fe15e0SLoGin if self.present() { 31240fe15e0SLoGin Ok(paddr) 31340fe15e0SLoGin } else { 31440fe15e0SLoGin Err(paddr) 31540fe15e0SLoGin } 31640fe15e0SLoGin } 31740fe15e0SLoGin 31840fe15e0SLoGin #[inline(always)] 31940fe15e0SLoGin pub fn flags(&self) -> PageFlags<Arch> { 32040fe15e0SLoGin unsafe { PageFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) } 32140fe15e0SLoGin } 32240fe15e0SLoGin 32340fe15e0SLoGin #[inline(always)] 32440fe15e0SLoGin pub fn set_flags(&mut self, flags: PageFlags<Arch>) { 32540fe15e0SLoGin self.data = (self.data & !Arch::ENTRY_FLAGS_MASK) | flags.data(); 32640fe15e0SLoGin } 32740fe15e0SLoGin 32840fe15e0SLoGin #[inline(always)] 32940fe15e0SLoGin pub fn present(&self) -> bool { 33040fe15e0SLoGin return self.data & Arch::ENTRY_FLAG_PRESENT != 0; 33140fe15e0SLoGin } 33240fe15e0SLoGin } 33340fe15e0SLoGin 33440fe15e0SLoGin /// 页表项的标志位 33540fe15e0SLoGin #[derive(Copy, Clone, Hash)] 33640fe15e0SLoGin pub struct PageFlags<Arch> { 33740fe15e0SLoGin data: usize, 33840fe15e0SLoGin phantom: PhantomData<Arch>, 33940fe15e0SLoGin } 34040fe15e0SLoGin 34140fe15e0SLoGin #[allow(dead_code)] 34240fe15e0SLoGin impl<Arch: MemoryManagementArch> PageFlags<Arch> { 34340fe15e0SLoGin #[inline(always)] 34440fe15e0SLoGin pub fn new() -> Self { 34540fe15e0SLoGin let mut r = unsafe { 34640fe15e0SLoGin Self::from_data( 34740fe15e0SLoGin Arch::ENTRY_FLAG_DEFAULT_PAGE 34840fe15e0SLoGin | Arch::ENTRY_FLAG_READONLY 34940fe15e0SLoGin | Arch::ENTRY_FLAG_NO_EXEC, 35040fe15e0SLoGin ) 35140fe15e0SLoGin }; 35240fe15e0SLoGin 35340fe15e0SLoGin #[cfg(target_arch = "x86_64")] 35440fe15e0SLoGin { 35540fe15e0SLoGin if crate::arch::mm::X86_64MMArch::is_xd_reserved() { 35640fe15e0SLoGin r = r.set_execute(true); 35740fe15e0SLoGin } 35840fe15e0SLoGin } 35940fe15e0SLoGin 36040fe15e0SLoGin return r; 36140fe15e0SLoGin } 36240fe15e0SLoGin 36340fe15e0SLoGin /// 根据ProtFlags生成PageFlags 36440fe15e0SLoGin /// 36540fe15e0SLoGin /// ## 参数 36640fe15e0SLoGin /// 36740fe15e0SLoGin /// - prot_flags: 页的保护标志 36840fe15e0SLoGin /// - user: 用户空间是否可访问 36940fe15e0SLoGin pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> PageFlags<Arch> { 37040fe15e0SLoGin let flags: PageFlags<Arch> = PageFlags::new() 37140fe15e0SLoGin .set_user(user) 37240fe15e0SLoGin .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC)) 37340fe15e0SLoGin .set_write(prot_flags.contains(ProtFlags::PROT_WRITE)); 37440fe15e0SLoGin 37540fe15e0SLoGin return flags; 37640fe15e0SLoGin } 37740fe15e0SLoGin 37840fe15e0SLoGin #[inline(always)] 37940fe15e0SLoGin pub fn data(&self) -> usize { 38040fe15e0SLoGin self.data 38140fe15e0SLoGin } 38240fe15e0SLoGin 38340fe15e0SLoGin #[inline(always)] 38440fe15e0SLoGin pub const unsafe fn from_data(data: usize) -> Self { 38540fe15e0SLoGin return Self { 386b5b571e0SLoGin data, 38740fe15e0SLoGin phantom: PhantomData, 38840fe15e0SLoGin }; 38940fe15e0SLoGin } 39040fe15e0SLoGin 39140fe15e0SLoGin /// 为新页表的页表项设置默认值 39240fe15e0SLoGin /// 39340fe15e0SLoGin /// 默认值为: 39440fe15e0SLoGin /// - present 39540fe15e0SLoGin /// - read only 39640fe15e0SLoGin /// - kernel space 39740fe15e0SLoGin /// - no exec 39840fe15e0SLoGin #[inline(always)] 39940fe15e0SLoGin pub fn new_page_table(user: bool) -> Self { 40040fe15e0SLoGin return unsafe { 4017a29d4fcSLoGin let r = { 4027a29d4fcSLoGin #[cfg(target_arch = "x86_64")] 4037a29d4fcSLoGin { 4047a29d4fcSLoGin Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE) 4057a29d4fcSLoGin } 4067a29d4fcSLoGin 4077a29d4fcSLoGin #[cfg(target_arch = "riscv64")] 4087a29d4fcSLoGin { 4097a29d4fcSLoGin // riscv64指向下一级页表的页表项,不应设置R/W/X权限位 4107a29d4fcSLoGin Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE) 4117a29d4fcSLoGin } 4127a29d4fcSLoGin }; 41340fe15e0SLoGin if user { 41440fe15e0SLoGin r.set_user(true) 41540fe15e0SLoGin } else { 41640fe15e0SLoGin r 41740fe15e0SLoGin } 41840fe15e0SLoGin }; 41940fe15e0SLoGin } 42040fe15e0SLoGin 42140fe15e0SLoGin /// 取得当前页表项的所有权,更新当前页表项的标志位,并返回更新后的页表项。 42240fe15e0SLoGin /// 42340fe15e0SLoGin /// ## 参数 42440fe15e0SLoGin /// - flag 要更新的标志位的值 42540fe15e0SLoGin /// - value 如果为true,那么将flag对应的位设置为1,否则设置为0 42640fe15e0SLoGin /// 42740fe15e0SLoGin /// ## 返回值 42840fe15e0SLoGin /// 42940fe15e0SLoGin /// 更新后的页表项 43040fe15e0SLoGin #[inline(always)] 43140fe15e0SLoGin #[must_use] 43240fe15e0SLoGin pub fn update_flags(mut self, flag: usize, value: bool) -> Self { 43340fe15e0SLoGin if value { 43440fe15e0SLoGin self.data |= flag; 43540fe15e0SLoGin } else { 43640fe15e0SLoGin self.data &= !flag; 43740fe15e0SLoGin } 43840fe15e0SLoGin return self; 43940fe15e0SLoGin } 44040fe15e0SLoGin 44140fe15e0SLoGin /// 判断当前页表项是否存在指定的flag(只有全部flag都存在才返回true) 44240fe15e0SLoGin #[inline(always)] 44340fe15e0SLoGin pub fn has_flag(&self, flag: usize) -> bool { 44440fe15e0SLoGin return self.data & flag == flag; 44540fe15e0SLoGin } 44640fe15e0SLoGin 44740fe15e0SLoGin #[inline(always)] 44840fe15e0SLoGin pub fn present(&self) -> bool { 44940fe15e0SLoGin return self.has_flag(Arch::ENTRY_FLAG_PRESENT); 45040fe15e0SLoGin } 45140fe15e0SLoGin 45240fe15e0SLoGin /// 设置当前页表项的权限 45340fe15e0SLoGin /// 45440fe15e0SLoGin /// @param value 如果为true,那么将当前页表项的权限设置为用户态可访问 45540fe15e0SLoGin #[must_use] 45640fe15e0SLoGin #[inline(always)] 45740fe15e0SLoGin pub fn set_user(self, value: bool) -> Self { 45840fe15e0SLoGin return self.update_flags(Arch::ENTRY_FLAG_USER, value); 45940fe15e0SLoGin } 46040fe15e0SLoGin 46140fe15e0SLoGin /// 用户态是否可以访问当前页表项 46240fe15e0SLoGin #[inline(always)] 46340fe15e0SLoGin pub fn has_user(&self) -> bool { 46440fe15e0SLoGin return self.has_flag(Arch::ENTRY_FLAG_USER); 46540fe15e0SLoGin } 46640fe15e0SLoGin 46740fe15e0SLoGin /// 设置当前页表项的可写性, 如果为true,那么将当前页表项的权限设置为可写, 否则设置为只读 46840fe15e0SLoGin /// 46940fe15e0SLoGin /// ## 返回值 47040fe15e0SLoGin /// 47140fe15e0SLoGin /// 更新后的页表项. 47240fe15e0SLoGin /// 47340fe15e0SLoGin /// **请注意,**本函数会取得当前页表项的所有权,因此返回的页表项不是原来的页表项 47440fe15e0SLoGin #[must_use] 47540fe15e0SLoGin #[inline(always)] 47640fe15e0SLoGin pub fn set_write(self, value: bool) -> Self { 4777a29d4fcSLoGin #[cfg(target_arch = "x86_64")] 4787a29d4fcSLoGin { 47940fe15e0SLoGin // 有的架构同时具有可写和不可写的标志位,因此需要同时更新 48040fe15e0SLoGin return self 48140fe15e0SLoGin .update_flags(Arch::ENTRY_FLAG_READONLY, !value) 48240fe15e0SLoGin .update_flags(Arch::ENTRY_FLAG_READWRITE, value); 48340fe15e0SLoGin } 48440fe15e0SLoGin 4857a29d4fcSLoGin #[cfg(target_arch = "riscv64")] 4867a29d4fcSLoGin { 4877a29d4fcSLoGin if value { 4887a29d4fcSLoGin return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true); 4897a29d4fcSLoGin } else { 4907a29d4fcSLoGin return self.update_flags(Arch::ENTRY_FLAG_READONLY, true); 4917a29d4fcSLoGin } 4927a29d4fcSLoGin } 4937a29d4fcSLoGin } 4947a29d4fcSLoGin 49540fe15e0SLoGin /// 当前页表项是否可写 49640fe15e0SLoGin #[inline(always)] 49740fe15e0SLoGin pub fn has_write(&self) -> bool { 49840fe15e0SLoGin // 有的架构同时具有可写和不可写的标志位,因此需要同时判断 49940fe15e0SLoGin return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY) 50040fe15e0SLoGin == Arch::ENTRY_FLAG_READWRITE; 50140fe15e0SLoGin } 50240fe15e0SLoGin 50340fe15e0SLoGin /// 设置当前页表项的可执行性, 如果为true,那么将当前页表项的权限设置为可执行, 否则设置为不可执行 50440fe15e0SLoGin #[must_use] 50540fe15e0SLoGin #[inline(always)] 50640fe15e0SLoGin pub fn set_execute(self, mut value: bool) -> Self { 50740fe15e0SLoGin #[cfg(target_arch = "x86_64")] 50840fe15e0SLoGin { 50940fe15e0SLoGin // 如果xd位被保留,那么将可执行性设置为true 51040fe15e0SLoGin if crate::arch::mm::X86_64MMArch::is_xd_reserved() { 51140fe15e0SLoGin value = true; 51240fe15e0SLoGin } 51340fe15e0SLoGin } 51440fe15e0SLoGin 51540fe15e0SLoGin // 有的架构同时具有可执行和不可执行的标志位,因此需要同时更新 51640fe15e0SLoGin return self 51740fe15e0SLoGin .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value) 51840fe15e0SLoGin .update_flags(Arch::ENTRY_FLAG_EXEC, value); 51940fe15e0SLoGin } 52040fe15e0SLoGin 52140fe15e0SLoGin /// 当前页表项是否可执行 52240fe15e0SLoGin #[inline(always)] 52340fe15e0SLoGin pub fn has_execute(&self) -> bool { 52440fe15e0SLoGin // 有的架构同时具有可执行和不可执行的标志位,因此需要同时判断 52540fe15e0SLoGin return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC) 52640fe15e0SLoGin == Arch::ENTRY_FLAG_EXEC; 52740fe15e0SLoGin } 52840fe15e0SLoGin 52940fe15e0SLoGin /// 设置当前页表项的缓存策略 53040fe15e0SLoGin /// 53140fe15e0SLoGin /// ## 参数 53240fe15e0SLoGin /// 53340fe15e0SLoGin /// - value: 如果为true,那么将当前页表项的缓存策略设置为不缓存。 53440fe15e0SLoGin #[inline(always)] 53540fe15e0SLoGin pub fn set_page_cache_disable(self, value: bool) -> Self { 53640fe15e0SLoGin return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value); 53740fe15e0SLoGin } 53840fe15e0SLoGin 53940fe15e0SLoGin /// 获取当前页表项的缓存策略 54040fe15e0SLoGin /// 54140fe15e0SLoGin /// ## 返回值 54240fe15e0SLoGin /// 54340fe15e0SLoGin /// 如果当前页表项的缓存策略为不缓存,那么返回true,否则返回false。 54440fe15e0SLoGin #[inline(always)] 54540fe15e0SLoGin pub fn has_page_cache_disable(&self) -> bool { 54640fe15e0SLoGin return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE); 54740fe15e0SLoGin } 54840fe15e0SLoGin 54940fe15e0SLoGin /// 设置当前页表项的写穿策略 55040fe15e0SLoGin /// 55140fe15e0SLoGin /// ## 参数 55240fe15e0SLoGin /// 55340fe15e0SLoGin /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。 55440fe15e0SLoGin #[inline(always)] 55540fe15e0SLoGin pub fn set_page_write_through(self, value: bool) -> Self { 55640fe15e0SLoGin return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value); 55740fe15e0SLoGin } 55840fe15e0SLoGin 55940fe15e0SLoGin /// 获取当前页表项的写穿策略 56040fe15e0SLoGin /// 56140fe15e0SLoGin /// ## 返回值 56240fe15e0SLoGin /// 56340fe15e0SLoGin /// 如果当前页表项的写穿策略为写穿,那么返回true,否则返回false。 56440fe15e0SLoGin #[inline(always)] 56540fe15e0SLoGin pub fn has_page_write_through(&self) -> bool { 56640fe15e0SLoGin return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH); 56740fe15e0SLoGin } 56840fe15e0SLoGin 56940fe15e0SLoGin /// MMIO内存的页表项标志 57040fe15e0SLoGin #[inline(always)] 57140fe15e0SLoGin pub fn mmio_flags() -> Self { 57240fe15e0SLoGin return Self::new() 57340fe15e0SLoGin .set_user(false) 57440fe15e0SLoGin .set_write(true) 57540fe15e0SLoGin .set_execute(true) 57640fe15e0SLoGin .set_page_cache_disable(true) 57740fe15e0SLoGin .set_page_write_through(true); 57840fe15e0SLoGin } 57940fe15e0SLoGin } 58040fe15e0SLoGin 58140fe15e0SLoGin impl<Arch: MemoryManagementArch> fmt::Debug for PageFlags<Arch> { 58240fe15e0SLoGin fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 58340fe15e0SLoGin f.debug_struct("PageFlags") 58440fe15e0SLoGin .field("bits", &format_args!("{:#0x}", self.data)) 58540fe15e0SLoGin .field("present", &self.present()) 58640fe15e0SLoGin .field("has_write", &self.has_write()) 58740fe15e0SLoGin .field("has_execute", &self.has_execute()) 58840fe15e0SLoGin .field("has_user", &self.has_user()) 58940fe15e0SLoGin .finish() 59040fe15e0SLoGin } 59140fe15e0SLoGin } 59240fe15e0SLoGin 59340fe15e0SLoGin /// 页表映射器 59440fe15e0SLoGin #[derive(Hash)] 59540fe15e0SLoGin pub struct PageMapper<Arch, F> { 59640fe15e0SLoGin /// 页表类型 59740fe15e0SLoGin table_kind: PageTableKind, 59840fe15e0SLoGin /// 根页表物理地址 59940fe15e0SLoGin table_paddr: PhysAddr, 60040fe15e0SLoGin /// 页分配器 60140fe15e0SLoGin frame_allocator: F, 60240fe15e0SLoGin phantom: PhantomData<fn() -> Arch>, 60340fe15e0SLoGin } 60440fe15e0SLoGin 60540fe15e0SLoGin impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> { 60640fe15e0SLoGin /// 创建新的页面映射器 60740fe15e0SLoGin /// 60840fe15e0SLoGin /// ## 参数 60940fe15e0SLoGin /// - table_kind 页表类型 61040fe15e0SLoGin /// - table_paddr 根页表物理地址 61140fe15e0SLoGin /// - allocator 页分配器 61240fe15e0SLoGin /// 61340fe15e0SLoGin /// ## 返回值 61440fe15e0SLoGin /// 61540fe15e0SLoGin /// 页面映射器 61640fe15e0SLoGin pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self { 61740fe15e0SLoGin return Self { 61840fe15e0SLoGin table_kind, 61940fe15e0SLoGin table_paddr, 62040fe15e0SLoGin frame_allocator: allocator, 62140fe15e0SLoGin phantom: PhantomData, 62240fe15e0SLoGin }; 62340fe15e0SLoGin } 62440fe15e0SLoGin 62540fe15e0SLoGin /// 创建页表,并为这个页表创建页面映射器 62640fe15e0SLoGin pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> { 62740fe15e0SLoGin let table_paddr = allocator.allocate_one()?; 62840fe15e0SLoGin // 清空页表 62940fe15e0SLoGin let table_vaddr = Arch::phys_2_virt(table_paddr)?; 63040fe15e0SLoGin Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE); 63140fe15e0SLoGin return Some(Self::new(table_kind, table_paddr, allocator)); 63240fe15e0SLoGin } 63340fe15e0SLoGin 63440fe15e0SLoGin /// 获取当前页表的页面映射器 63540fe15e0SLoGin #[inline(always)] 63640fe15e0SLoGin pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self { 63740fe15e0SLoGin let table_paddr = Arch::table(table_kind); 63840fe15e0SLoGin return Self::new(table_kind, table_paddr, allocator); 63940fe15e0SLoGin } 64040fe15e0SLoGin 64140fe15e0SLoGin /// 判断当前页表分配器所属的页表是否是当前页表 64240fe15e0SLoGin #[inline(always)] 64340fe15e0SLoGin pub fn is_current(&self) -> bool { 64440fe15e0SLoGin return unsafe { self.table().phys() == Arch::table(self.table_kind) }; 64540fe15e0SLoGin } 64640fe15e0SLoGin 64740fe15e0SLoGin /// 将当前页表分配器所属的页表设置为当前页表 64840fe15e0SLoGin #[inline(always)] 64940fe15e0SLoGin pub unsafe fn make_current(&self) { 65040fe15e0SLoGin Arch::set_table(self.table_kind, self.table_paddr); 65140fe15e0SLoGin } 65240fe15e0SLoGin 65340fe15e0SLoGin /// 获取当前页表分配器所属的根页表的结构体 65440fe15e0SLoGin #[inline(always)] 65540fe15e0SLoGin pub fn table(&self) -> PageTable<Arch> { 65640fe15e0SLoGin // 由于只能通过new方法创建PageMapper,因此这里假定table_paddr是有效的 65740fe15e0SLoGin return unsafe { 65840fe15e0SLoGin PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1) 65940fe15e0SLoGin }; 66040fe15e0SLoGin } 66140fe15e0SLoGin 66240fe15e0SLoGin /// 获取当前PageMapper所对应的页分配器实例的引用 66340fe15e0SLoGin #[inline(always)] 66440fe15e0SLoGin #[allow(dead_code)] 66540fe15e0SLoGin pub fn allocator_ref(&self) -> &F { 66640fe15e0SLoGin return &self.frame_allocator; 66740fe15e0SLoGin } 66840fe15e0SLoGin 66940fe15e0SLoGin /// 获取当前PageMapper所对应的页分配器实例的可变引用 67040fe15e0SLoGin #[inline(always)] 67140fe15e0SLoGin pub fn allocator_mut(&mut self) -> &mut F { 67240fe15e0SLoGin return &mut self.frame_allocator; 67340fe15e0SLoGin } 67440fe15e0SLoGin 67540fe15e0SLoGin /// 从当前PageMapper的页分配器中分配一个物理页,并将其映射到指定的虚拟地址 67640fe15e0SLoGin pub unsafe fn map( 67740fe15e0SLoGin &mut self, 67840fe15e0SLoGin virt: VirtAddr, 67940fe15e0SLoGin flags: PageFlags<Arch>, 68040fe15e0SLoGin ) -> Option<PageFlush<Arch>> { 68140fe15e0SLoGin compiler_fence(Ordering::SeqCst); 68240fe15e0SLoGin let phys: PhysAddr = self.frame_allocator.allocate_one()?; 68340fe15e0SLoGin compiler_fence(Ordering::SeqCst); 68456cc4dbeSJomo 68556cc4dbeSJomo page_manager_lock_irasave().insert(phys, Page::new(false)); 68640fe15e0SLoGin return self.map_phys(virt, phys, flags); 68740fe15e0SLoGin } 68840fe15e0SLoGin 68940fe15e0SLoGin /// 映射一个物理页到指定的虚拟地址 69040fe15e0SLoGin pub unsafe fn map_phys( 69140fe15e0SLoGin &mut self, 69240fe15e0SLoGin virt: VirtAddr, 69340fe15e0SLoGin phys: PhysAddr, 69440fe15e0SLoGin flags: PageFlags<Arch>, 69540fe15e0SLoGin ) -> Option<PageFlush<Arch>> { 69640fe15e0SLoGin // 验证虚拟地址和物理地址是否对齐 69740fe15e0SLoGin if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) { 69840fe15e0SLoGin kerror!( 69940fe15e0SLoGin "Try to map unaligned page: virt={:?}, phys={:?}", 70040fe15e0SLoGin virt, 70140fe15e0SLoGin phys 70240fe15e0SLoGin ); 70340fe15e0SLoGin return None; 70440fe15e0SLoGin } 7057a29d4fcSLoGin 70640fe15e0SLoGin let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 70740fe15e0SLoGin 70840fe15e0SLoGin // TODO: 验证flags是否合法 70940fe15e0SLoGin 71040fe15e0SLoGin // 创建页表项 7117a29d4fcSLoGin let entry = PageEntry::new(phys, flags); 71240fe15e0SLoGin let mut table = self.table(); 71340fe15e0SLoGin loop { 71440fe15e0SLoGin let i = table.index_of(virt)?; 71540fe15e0SLoGin assert!(i < Arch::PAGE_ENTRY_NUM); 71640fe15e0SLoGin if table.level() == 0 { 71740fe15e0SLoGin // todo: 检查是否已经映射 71840fe15e0SLoGin // 现在不检查的原因是,刚刚启动系统时,内核会映射一些页。 719b5b571e0SLoGin if table.entry_mapped(i)? { 72040fe15e0SLoGin kwarn!("Page {:?} already mapped", virt); 72140fe15e0SLoGin } 7227a29d4fcSLoGin 72340fe15e0SLoGin compiler_fence(Ordering::SeqCst); 7247a29d4fcSLoGin 72540fe15e0SLoGin table.set_entry(i, entry); 72640fe15e0SLoGin compiler_fence(Ordering::SeqCst); 72740fe15e0SLoGin return Some(PageFlush::new(virt)); 72840fe15e0SLoGin } else { 72940fe15e0SLoGin let next_table = table.next_level_table(i); 73040fe15e0SLoGin if let Some(next_table) = next_table { 73140fe15e0SLoGin table = next_table; 73240fe15e0SLoGin // kdebug!("Mapping {:?} to next level table...", virt); 73340fe15e0SLoGin } else { 73440fe15e0SLoGin // 分配下一级页表 73540fe15e0SLoGin let frame = self.frame_allocator.allocate_one()?; 7367a29d4fcSLoGin 73740fe15e0SLoGin // 清空这个页帧 73840fe15e0SLoGin MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 73940fe15e0SLoGin 74040fe15e0SLoGin // 设置页表项的flags 7417a29d4fcSLoGin let flags: PageFlags<Arch> = 74240fe15e0SLoGin PageFlags::new_page_table(virt.kind() == PageTableKind::User); 74340fe15e0SLoGin 74440fe15e0SLoGin // kdebug!("Flags: {:?}", flags); 74540fe15e0SLoGin 74640fe15e0SLoGin // 把新分配的页表映射到当前页表 7477a29d4fcSLoGin table.set_entry(i, PageEntry::new(frame, flags)); 74840fe15e0SLoGin 74940fe15e0SLoGin // 获取新分配的页表 75040fe15e0SLoGin table = table.next_level_table(i)?; 75140fe15e0SLoGin } 75240fe15e0SLoGin } 75340fe15e0SLoGin } 75440fe15e0SLoGin } 75540fe15e0SLoGin 75640fe15e0SLoGin /// 将物理地址映射到具有线性偏移量的虚拟地址 75740fe15e0SLoGin #[allow(dead_code)] 75840fe15e0SLoGin pub unsafe fn map_linearly( 75940fe15e0SLoGin &mut self, 76040fe15e0SLoGin phys: PhysAddr, 76140fe15e0SLoGin flags: PageFlags<Arch>, 76240fe15e0SLoGin ) -> Option<(VirtAddr, PageFlush<Arch>)> { 76340fe15e0SLoGin let virt: VirtAddr = Arch::phys_2_virt(phys)?; 76440fe15e0SLoGin return self.map_phys(virt, phys, flags).map(|flush| (virt, flush)); 76540fe15e0SLoGin } 76640fe15e0SLoGin 76740fe15e0SLoGin /// 修改虚拟地址的页表项的flags,并返回页表项刷新器 76840fe15e0SLoGin /// 76940fe15e0SLoGin /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效 77040fe15e0SLoGin /// 77140fe15e0SLoGin /// ## 参数 77240fe15e0SLoGin /// - virt 虚拟地址 77340fe15e0SLoGin /// - flags 新的页表项的flags 77440fe15e0SLoGin /// 77540fe15e0SLoGin /// ## 返回值 77640fe15e0SLoGin /// 77740fe15e0SLoGin /// 如果修改成功,返回刷新器,否则返回None 77840fe15e0SLoGin pub unsafe fn remap( 77940fe15e0SLoGin &mut self, 78040fe15e0SLoGin virt: VirtAddr, 78140fe15e0SLoGin flags: PageFlags<Arch>, 78240fe15e0SLoGin ) -> Option<PageFlush<Arch>> { 78340fe15e0SLoGin return self 78440fe15e0SLoGin .visit(virt, |p1, i| { 78540fe15e0SLoGin let mut entry = p1.entry(i)?; 78640fe15e0SLoGin entry.set_flags(flags); 78740fe15e0SLoGin p1.set_entry(i, entry); 78840fe15e0SLoGin Some(PageFlush::new(virt)) 78940fe15e0SLoGin }) 79040fe15e0SLoGin .flatten(); 79140fe15e0SLoGin } 79240fe15e0SLoGin 79340fe15e0SLoGin /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags 79440fe15e0SLoGin /// 79540fe15e0SLoGin /// ## 参数 79640fe15e0SLoGin /// 79740fe15e0SLoGin /// - virt 虚拟地址 79840fe15e0SLoGin /// 79940fe15e0SLoGin /// ## 返回值 80040fe15e0SLoGin /// 80140fe15e0SLoGin /// 如果查找成功,返回物理地址和页表项的flags,否则返回None 80240fe15e0SLoGin pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, PageFlags<Arch>)> { 80340fe15e0SLoGin let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??; 80440fe15e0SLoGin let paddr = entry.address().ok()?; 80540fe15e0SLoGin let flags = entry.flags(); 80640fe15e0SLoGin return Some((paddr, flags)); 80740fe15e0SLoGin } 80840fe15e0SLoGin 80940fe15e0SLoGin /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器 81040fe15e0SLoGin /// 81140fe15e0SLoGin /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效 81240fe15e0SLoGin /// 81340fe15e0SLoGin /// ## 参数 81440fe15e0SLoGin /// 81540fe15e0SLoGin /// - virt 虚拟地址 81640fe15e0SLoGin /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 81740fe15e0SLoGin /// 81840fe15e0SLoGin /// ## 返回值 81940fe15e0SLoGin /// 如果取消成功,返回刷新器,否则返回None 8202dd9f0c7SLoGin #[allow(dead_code)] 82140fe15e0SLoGin pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> { 82240fe15e0SLoGin let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?; 82340fe15e0SLoGin self.frame_allocator.free_one(paddr); 82440fe15e0SLoGin return Some(flusher); 82540fe15e0SLoGin } 82640fe15e0SLoGin 82740fe15e0SLoGin /// 取消虚拟地址的映射,并返回物理地址和页表项的flags 82840fe15e0SLoGin /// 82940fe15e0SLoGin /// ## 参数 83040fe15e0SLoGin /// 83140fe15e0SLoGin /// - vaddr 虚拟地址 83240fe15e0SLoGin /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 83340fe15e0SLoGin /// 83440fe15e0SLoGin /// ## 返回值 83540fe15e0SLoGin /// 83640fe15e0SLoGin /// 如果取消成功,返回物理地址和页表项的flags,否则返回None 83740fe15e0SLoGin pub unsafe fn unmap_phys( 83840fe15e0SLoGin &mut self, 83940fe15e0SLoGin virt: VirtAddr, 84040fe15e0SLoGin unmap_parents: bool, 84140fe15e0SLoGin ) -> Option<(PhysAddr, PageFlags<Arch>, PageFlush<Arch>)> { 84240fe15e0SLoGin if !virt.check_aligned(Arch::PAGE_SIZE) { 84340fe15e0SLoGin kerror!("Try to unmap unaligned page: virt={:?}", virt); 84440fe15e0SLoGin return None; 84540fe15e0SLoGin } 84640fe15e0SLoGin 847b5b571e0SLoGin let table = self.table(); 848b5b571e0SLoGin return unmap_phys_inner(virt, &table, unmap_parents, self.allocator_mut()) 84940fe15e0SLoGin .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt))); 85040fe15e0SLoGin } 85140fe15e0SLoGin 85240fe15e0SLoGin /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F 85340fe15e0SLoGin fn visit<T>( 85440fe15e0SLoGin &self, 85540fe15e0SLoGin virt: VirtAddr, 85640fe15e0SLoGin f: impl FnOnce(&mut PageTable<Arch>, usize) -> T, 85740fe15e0SLoGin ) -> Option<T> { 85840fe15e0SLoGin let mut table = self.table(); 85940fe15e0SLoGin unsafe { 86040fe15e0SLoGin loop { 86140fe15e0SLoGin let i = table.index_of(virt)?; 86240fe15e0SLoGin if table.level() == 0 { 86340fe15e0SLoGin return Some(f(&mut table, i)); 86440fe15e0SLoGin } else { 86540fe15e0SLoGin table = table.next_level_table(i)?; 86640fe15e0SLoGin } 86740fe15e0SLoGin } 86840fe15e0SLoGin } 86940fe15e0SLoGin } 87040fe15e0SLoGin } 87140fe15e0SLoGin 87240fe15e0SLoGin /// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】 87340fe15e0SLoGin /// 87440fe15e0SLoGin /// ## 参数 87540fe15e0SLoGin /// 87640fe15e0SLoGin /// - vaddr 虚拟地址 87740fe15e0SLoGin /// - table 页表 87840fe15e0SLoGin /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 87940fe15e0SLoGin /// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内) 88040fe15e0SLoGin /// 88140fe15e0SLoGin /// ## 返回值 88240fe15e0SLoGin /// 88340fe15e0SLoGin /// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None 88440fe15e0SLoGin unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>( 88540fe15e0SLoGin vaddr: VirtAddr, 886840045afSLoGin table: &PageTable<Arch>, 88740fe15e0SLoGin unmap_parents: bool, 88840fe15e0SLoGin allocator: &mut impl FrameAllocator, 88940fe15e0SLoGin ) -> Option<(PhysAddr, PageFlags<Arch>)> { 89040fe15e0SLoGin // 获取页表项的索引 89140fe15e0SLoGin let i = table.index_of(vaddr)?; 89240fe15e0SLoGin 89340fe15e0SLoGin // 如果当前是最后一级页表,直接取消页面映射 89440fe15e0SLoGin if table.level() == 0 { 89540fe15e0SLoGin let entry = table.entry(i)?; 8967a29d4fcSLoGin table.set_entry(i, PageEntry::from_usize(0)); 89740fe15e0SLoGin return Some((entry.address().ok()?, entry.flags())); 89840fe15e0SLoGin } 89940fe15e0SLoGin 900b5b571e0SLoGin let subtable = table.next_level_table(i)?; 90140fe15e0SLoGin // 递归地取消映射 902b5b571e0SLoGin let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator)?; 90340fe15e0SLoGin 90440fe15e0SLoGin // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables, 90540fe15e0SLoGin // as these mappings may become out of sync 90640fe15e0SLoGin if unmap_parents { 90740fe15e0SLoGin // 如果子页表已经没有映射的页面了,就取消子页表的映射 90840fe15e0SLoGin 90940fe15e0SLoGin // 检查子页表中是否还有映射的页面 91040fe15e0SLoGin let x = (0..Arch::PAGE_ENTRY_NUM) 91140fe15e0SLoGin .map(|k| subtable.entry(k).expect("invalid page entry")) 91240fe15e0SLoGin .any(|e| e.present()); 91340fe15e0SLoGin if !x { 91440fe15e0SLoGin // 如果没有,就取消子页表的映射 9157a29d4fcSLoGin table.set_entry(i, PageEntry::from_usize(0)); 91640fe15e0SLoGin // 释放子页表 91740fe15e0SLoGin allocator.free_one(subtable.phys()); 91840fe15e0SLoGin } 91940fe15e0SLoGin } 92040fe15e0SLoGin 92140fe15e0SLoGin return Some(result); 92240fe15e0SLoGin } 92340fe15e0SLoGin 92440fe15e0SLoGin impl<Arch, F: Debug> Debug for PageMapper<Arch, F> { 92540fe15e0SLoGin fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 92640fe15e0SLoGin f.debug_struct("PageMapper") 92740fe15e0SLoGin .field("table_paddr", &self.table_paddr) 92840fe15e0SLoGin .field("frame_allocator", &self.frame_allocator) 92940fe15e0SLoGin .finish() 93040fe15e0SLoGin } 93140fe15e0SLoGin } 93240fe15e0SLoGin 93340fe15e0SLoGin /// 页表刷新器的trait 9347ae679ddSLoGin pub trait Flusher<Arch: MemoryManagementArch> { 93540fe15e0SLoGin /// 取消对指定的page flusher的刷新 93640fe15e0SLoGin fn consume(&mut self, flush: PageFlush<Arch>); 93740fe15e0SLoGin } 93840fe15e0SLoGin 93940fe15e0SLoGin /// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法, 94040fe15e0SLoGin /// 否则会造成对页表的更改被忽略,这是不安全的 94140fe15e0SLoGin #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 9427ae679ddSLoGin pub struct PageFlush<Arch: MemoryManagementArch> { 94340fe15e0SLoGin virt: VirtAddr, 94440fe15e0SLoGin phantom: PhantomData<Arch>, 94540fe15e0SLoGin } 94640fe15e0SLoGin 94740fe15e0SLoGin impl<Arch: MemoryManagementArch> PageFlush<Arch> { 94840fe15e0SLoGin pub fn new(virt: VirtAddr) -> Self { 94940fe15e0SLoGin return Self { 95040fe15e0SLoGin virt, 95140fe15e0SLoGin phantom: PhantomData, 95240fe15e0SLoGin }; 95340fe15e0SLoGin } 95440fe15e0SLoGin 95540fe15e0SLoGin pub fn flush(self) { 95640fe15e0SLoGin unsafe { Arch::invalidate_page(self.virt) }; 95740fe15e0SLoGin } 95840fe15e0SLoGin 95940fe15e0SLoGin /// 忽略掉这个刷新器 96040fe15e0SLoGin pub unsafe fn ignore(self) { 96140fe15e0SLoGin mem::forget(self); 96240fe15e0SLoGin } 96340fe15e0SLoGin } 96440fe15e0SLoGin 9657ae679ddSLoGin impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> { 9667ae679ddSLoGin fn drop(&mut self) { 9677ae679ddSLoGin unsafe { 9687ae679ddSLoGin MMArch::invalidate_page(self.virt); 9697ae679ddSLoGin } 9707ae679ddSLoGin } 9717ae679ddSLoGin } 9727ae679ddSLoGin 97340fe15e0SLoGin /// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法, 97440fe15e0SLoGin /// 否则会造成对页表的更改被忽略,这是不安全的 97540fe15e0SLoGin #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 97640fe15e0SLoGin pub struct PageFlushAll<Arch: MemoryManagementArch> { 97740fe15e0SLoGin phantom: PhantomData<fn() -> Arch>, 97840fe15e0SLoGin } 97940fe15e0SLoGin 98040fe15e0SLoGin #[allow(dead_code)] 98140fe15e0SLoGin impl<Arch: MemoryManagementArch> PageFlushAll<Arch> { 98240fe15e0SLoGin pub fn new() -> Self { 98340fe15e0SLoGin return Self { 98440fe15e0SLoGin phantom: PhantomData, 98540fe15e0SLoGin }; 98640fe15e0SLoGin } 98740fe15e0SLoGin 98840fe15e0SLoGin pub fn flush(self) { 98940fe15e0SLoGin unsafe { Arch::invalidate_all() }; 99040fe15e0SLoGin } 99140fe15e0SLoGin 99240fe15e0SLoGin /// 忽略掉这个刷新器 99340fe15e0SLoGin pub unsafe fn ignore(self) { 99440fe15e0SLoGin mem::forget(self); 99540fe15e0SLoGin } 99640fe15e0SLoGin } 99740fe15e0SLoGin 99840fe15e0SLoGin impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> { 99940fe15e0SLoGin /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了) 100040fe15e0SLoGin fn consume(&mut self, flush: PageFlush<Arch>) { 100140fe15e0SLoGin unsafe { flush.ignore() }; 100240fe15e0SLoGin } 100340fe15e0SLoGin } 100440fe15e0SLoGin 100540fe15e0SLoGin impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T { 100640fe15e0SLoGin /// 允许一个flusher consume掉另一个flusher 100740fe15e0SLoGin fn consume(&mut self, flush: PageFlush<Arch>) { 100840fe15e0SLoGin <T as Flusher<Arch>>::consume(self, flush); 100940fe15e0SLoGin } 101040fe15e0SLoGin } 101140fe15e0SLoGin 101240fe15e0SLoGin impl<Arch: MemoryManagementArch> Flusher<Arch> for () { 101340fe15e0SLoGin fn consume(&mut self, _flush: PageFlush<Arch>) {} 101440fe15e0SLoGin } 101540fe15e0SLoGin 101640fe15e0SLoGin impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> { 101740fe15e0SLoGin fn drop(&mut self) { 101840fe15e0SLoGin unsafe { 101940fe15e0SLoGin Arch::invalidate_all(); 102040fe15e0SLoGin } 102140fe15e0SLoGin } 102240fe15e0SLoGin } 102340fe15e0SLoGin 102440fe15e0SLoGin /// 未在当前CPU上激活的页表的刷新器 102540fe15e0SLoGin /// 102640fe15e0SLoGin /// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表 102740fe15e0SLoGin /// 102840fe15e0SLoGin /// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销) 102940fe15e0SLoGin #[derive(Debug)] 103040fe15e0SLoGin pub struct InactiveFlusher; 103140fe15e0SLoGin 103240fe15e0SLoGin impl InactiveFlusher { 103340fe15e0SLoGin pub fn new() -> Self { 103440fe15e0SLoGin return Self {}; 103540fe15e0SLoGin } 103640fe15e0SLoGin } 103740fe15e0SLoGin 103840fe15e0SLoGin impl Flusher<MMArch> for InactiveFlusher { 103940fe15e0SLoGin fn consume(&mut self, flush: PageFlush<MMArch>) { 104040fe15e0SLoGin unsafe { 104140fe15e0SLoGin flush.ignore(); 104240fe15e0SLoGin } 104340fe15e0SLoGin } 104440fe15e0SLoGin } 104540fe15e0SLoGin 104640fe15e0SLoGin impl Drop for InactiveFlusher { 104740fe15e0SLoGin fn drop(&mut self) { 104840fe15e0SLoGin // 发送刷新页表的IPI 104940fe15e0SLoGin send_ipi(IpiKind::FlushTLB, IpiTarget::Other); 105040fe15e0SLoGin } 105140fe15e0SLoGin } 105240fe15e0SLoGin 105340fe15e0SLoGin /// # 把一个地址向下对齐到页大小 105440fe15e0SLoGin pub fn round_down_to_page_size(addr: usize) -> usize { 105540fe15e0SLoGin addr & !(MMArch::PAGE_SIZE - 1) 105640fe15e0SLoGin } 105740fe15e0SLoGin 105840fe15e0SLoGin /// # 把一个地址向上对齐到页大小 105940fe15e0SLoGin pub fn round_up_to_page_size(addr: usize) -> usize { 106040fe15e0SLoGin round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1) 106140fe15e0SLoGin } 1062