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}; 112eab6dd7S曾俊 use log::{error, info}; 1256cc4dbeSJomo 1340fe15e0SLoGin use crate::{ 1440fe15e0SLoGin arch::{interrupt::ipi::send_ipi, MMArch}, 1540fe15e0SLoGin exception::ipi::{IpiKind, IpiTarget}, 166fc066acSJomo ipc::shm::ShmId, 1756cc4dbeSJomo libs::spinlock::{SpinLock, SpinLockGuard}, 1840fe15e0SLoGin }; 1940fe15e0SLoGin 2040fe15e0SLoGin use super::{ 21a17651b1SMemoryShore allocator::page_frame::{FrameAllocator, PageFrameCount}, 22a17651b1SMemoryShore syscall::ProtFlags, 23a17651b1SMemoryShore ucontext::LockedVMA, 2456cc4dbeSJomo MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, 2540fe15e0SLoGin }; 2640fe15e0SLoGin 2723ef2b33SLoGin pub const PAGE_4K_SHIFT: usize = 12; 2823ef2b33SLoGin #[allow(dead_code)] 2923ef2b33SLoGin pub const PAGE_2M_SHIFT: usize = 21; 3023ef2b33SLoGin pub const PAGE_1G_SHIFT: usize = 30; 3123ef2b33SLoGin 32370472f7SLoGin pub const PAGE_4K_SIZE: usize = 1 << PAGE_4K_SHIFT; 33370472f7SLoGin pub const PAGE_2M_SIZE: usize = 1 << PAGE_2M_SHIFT; 34370472f7SLoGin 3556cc4dbeSJomo /// 全局物理页信息管理器 3656cc4dbeSJomo pub static mut PAGE_MANAGER: Option<SpinLock<PageManager>> = None; 3756cc4dbeSJomo 3856cc4dbeSJomo /// 初始化PAGE_MANAGER 3956cc4dbeSJomo pub fn page_manager_init() { 402eab6dd7S曾俊 info!("page_manager_init"); 4156cc4dbeSJomo let page_manager = SpinLock::new(PageManager::new()); 4256cc4dbeSJomo 4356cc4dbeSJomo compiler_fence(Ordering::SeqCst); 4456cc4dbeSJomo unsafe { PAGE_MANAGER = Some(page_manager) }; 4556cc4dbeSJomo compiler_fence(Ordering::SeqCst); 4656cc4dbeSJomo 472eab6dd7S曾俊 info!("page_manager_init done"); 4856cc4dbeSJomo } 4956cc4dbeSJomo 506fc066acSJomo pub fn page_manager_lock_irqsave() -> SpinLockGuard<'static, PageManager> { 5156cc4dbeSJomo unsafe { PAGE_MANAGER.as_ref().unwrap().lock_irqsave() } 5256cc4dbeSJomo } 5356cc4dbeSJomo 5456cc4dbeSJomo // 物理页管理器 5556cc4dbeSJomo pub struct PageManager { 5656cc4dbeSJomo phys2page: HashMap<PhysAddr, Page>, 5756cc4dbeSJomo } 5856cc4dbeSJomo 5956cc4dbeSJomo impl PageManager { 6056cc4dbeSJomo pub fn new() -> Self { 6156cc4dbeSJomo Self { 6256cc4dbeSJomo phys2page: HashMap::new(), 6356cc4dbeSJomo } 6456cc4dbeSJomo } 6556cc4dbeSJomo 666fc066acSJomo pub fn contains(&self, paddr: &PhysAddr) -> bool { 676fc066acSJomo self.phys2page.contains_key(paddr) 686fc066acSJomo } 696fc066acSJomo 706fc066acSJomo pub fn get(&self, paddr: &PhysAddr) -> Option<&Page> { 716fc066acSJomo self.phys2page.get(paddr) 726fc066acSJomo } 736fc066acSJomo 7456cc4dbeSJomo pub fn get_mut(&mut self, paddr: &PhysAddr) -> &mut Page { 75a17651b1SMemoryShore self.phys2page 76a17651b1SMemoryShore .get_mut(paddr) 77a17651b1SMemoryShore .unwrap_or_else(|| panic!("{:?}", paddr)) 7856cc4dbeSJomo } 7956cc4dbeSJomo 8056cc4dbeSJomo pub fn insert(&mut self, paddr: PhysAddr, page: Page) { 8156cc4dbeSJomo self.phys2page.insert(paddr, page); 8256cc4dbeSJomo } 8356cc4dbeSJomo 8456cc4dbeSJomo pub fn remove_page(&mut self, paddr: &PhysAddr) { 8556cc4dbeSJomo self.phys2page.remove(paddr); 8656cc4dbeSJomo } 8756cc4dbeSJomo } 8856cc4dbeSJomo 8956cc4dbeSJomo /// 物理页面信息 9056cc4dbeSJomo pub struct Page { 9156cc4dbeSJomo /// 映射计数 9256cc4dbeSJomo map_count: usize, 9356cc4dbeSJomo /// 是否为共享页 9456cc4dbeSJomo shared: bool, 956fc066acSJomo /// 映射计数为0时,是否可回收 966fc066acSJomo free_when_zero: bool, 976fc066acSJomo /// 共享页id(如果是共享页) 986fc066acSJomo shm_id: Option<ShmId>, 9956cc4dbeSJomo /// 映射到当前page的VMA 10056cc4dbeSJomo anon_vma: HashSet<Arc<LockedVMA>>, 10156cc4dbeSJomo } 10256cc4dbeSJomo 10356cc4dbeSJomo impl Page { 10456cc4dbeSJomo pub fn new(shared: bool) -> Self { 1056fc066acSJomo let dealloc_when_zero = !shared; 10656cc4dbeSJomo Self { 10756cc4dbeSJomo map_count: 0, 10856cc4dbeSJomo shared, 1096fc066acSJomo free_when_zero: dealloc_when_zero, 1106fc066acSJomo shm_id: None, 11156cc4dbeSJomo anon_vma: HashSet::new(), 11256cc4dbeSJomo } 11356cc4dbeSJomo } 11456cc4dbeSJomo 11556cc4dbeSJomo /// 将vma加入anon_vma 11656cc4dbeSJomo pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) { 11756cc4dbeSJomo self.anon_vma.insert(vma); 11856cc4dbeSJomo self.map_count += 1; 11956cc4dbeSJomo } 12056cc4dbeSJomo 12156cc4dbeSJomo /// 将vma从anon_vma中删去 12256cc4dbeSJomo pub fn remove_vma(&mut self, vma: &LockedVMA) { 12356cc4dbeSJomo self.anon_vma.remove(vma); 12456cc4dbeSJomo self.map_count -= 1; 12556cc4dbeSJomo } 12656cc4dbeSJomo 12756cc4dbeSJomo /// 判断当前物理页是否能被回 12856cc4dbeSJomo pub fn can_deallocate(&self) -> bool { 1296fc066acSJomo self.map_count == 0 && self.free_when_zero 1306fc066acSJomo } 1316fc066acSJomo 1326fc066acSJomo pub fn shared(&self) -> bool { 1336fc066acSJomo self.shared 1346fc066acSJomo } 1356fc066acSJomo 1366fc066acSJomo pub fn shm_id(&self) -> Option<ShmId> { 1376fc066acSJomo self.shm_id 1386fc066acSJomo } 1396fc066acSJomo 1406fc066acSJomo pub fn set_shm_id(&mut self, shm_id: ShmId) { 1416fc066acSJomo self.shm_id = Some(shm_id); 1426fc066acSJomo } 1436fc066acSJomo 1446fc066acSJomo pub fn set_dealloc_when_zero(&mut self, dealloc_when_zero: bool) { 1456fc066acSJomo self.free_when_zero = dealloc_when_zero; 1466fc066acSJomo } 1476fc066acSJomo 148a17651b1SMemoryShore #[inline(always)] 1496fc066acSJomo pub fn anon_vma(&self) -> &HashSet<Arc<LockedVMA>> { 1506fc066acSJomo &self.anon_vma 15156cc4dbeSJomo } 152a17651b1SMemoryShore 153a17651b1SMemoryShore #[inline(always)] 154a17651b1SMemoryShore pub fn map_count(&self) -> usize { 155a17651b1SMemoryShore self.map_count 156a17651b1SMemoryShore } 15756cc4dbeSJomo } 15856cc4dbeSJomo 15940fe15e0SLoGin #[derive(Debug)] 16040fe15e0SLoGin pub struct PageTable<Arch> { 16140fe15e0SLoGin /// 当前页表表示的虚拟地址空间的起始地址 16240fe15e0SLoGin base: VirtAddr, 16340fe15e0SLoGin /// 当前页表所在的物理地址 16440fe15e0SLoGin phys: PhysAddr, 16540fe15e0SLoGin /// 当前页表的层级(请注意,最顶级页表的level为[Arch::PAGE_LEVELS - 1]) 16640fe15e0SLoGin level: usize, 16740fe15e0SLoGin phantom: PhantomData<Arch>, 16840fe15e0SLoGin } 16940fe15e0SLoGin 17040fe15e0SLoGin #[allow(dead_code)] 17140fe15e0SLoGin impl<Arch: MemoryManagementArch> PageTable<Arch> { 17240fe15e0SLoGin pub unsafe fn new(base: VirtAddr, phys: PhysAddr, level: usize) -> Self { 17340fe15e0SLoGin Self { 17440fe15e0SLoGin base, 17540fe15e0SLoGin phys, 17640fe15e0SLoGin level, 17740fe15e0SLoGin phantom: PhantomData, 17840fe15e0SLoGin } 17940fe15e0SLoGin } 18040fe15e0SLoGin 18140fe15e0SLoGin /// 获取顶级页表 18240fe15e0SLoGin /// 18340fe15e0SLoGin /// ## 参数 18440fe15e0SLoGin /// 18540fe15e0SLoGin /// - table_kind 页表类型 18640fe15e0SLoGin /// 18740fe15e0SLoGin /// ## 返回值 18840fe15e0SLoGin /// 18940fe15e0SLoGin /// 返回顶级页表 19040fe15e0SLoGin pub unsafe fn top_level_table(table_kind: PageTableKind) -> Self { 19140fe15e0SLoGin return Self::new( 19240fe15e0SLoGin VirtAddr::new(0), 19340fe15e0SLoGin Arch::table(table_kind), 19440fe15e0SLoGin Arch::PAGE_LEVELS - 1, 19540fe15e0SLoGin ); 19640fe15e0SLoGin } 19740fe15e0SLoGin 19840fe15e0SLoGin /// 获取当前页表的物理地址 19940fe15e0SLoGin #[inline(always)] 20040fe15e0SLoGin pub fn phys(&self) -> PhysAddr { 20140fe15e0SLoGin self.phys 20240fe15e0SLoGin } 20340fe15e0SLoGin 20440fe15e0SLoGin /// 当前页表表示的虚拟地址空间的起始地址 20540fe15e0SLoGin #[inline(always)] 20640fe15e0SLoGin pub fn base(&self) -> VirtAddr { 20740fe15e0SLoGin self.base 20840fe15e0SLoGin } 20940fe15e0SLoGin 21040fe15e0SLoGin /// 获取当前页表的层级 21140fe15e0SLoGin #[inline(always)] 21240fe15e0SLoGin pub fn level(&self) -> usize { 21340fe15e0SLoGin self.level 21440fe15e0SLoGin } 21540fe15e0SLoGin 21640fe15e0SLoGin /// 获取当前页表自身所在的虚拟地址 21740fe15e0SLoGin #[inline(always)] 21840fe15e0SLoGin pub unsafe fn virt(&self) -> VirtAddr { 21940fe15e0SLoGin return Arch::phys_2_virt(self.phys).unwrap(); 22040fe15e0SLoGin } 22140fe15e0SLoGin 22240fe15e0SLoGin /// 获取第i个页表项所表示的虚拟内存空间的起始地址 22340fe15e0SLoGin pub fn entry_base(&self, i: usize) -> Option<VirtAddr> { 22440fe15e0SLoGin if i < Arch::PAGE_ENTRY_NUM { 22540fe15e0SLoGin let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT; 22640fe15e0SLoGin return Some(self.base.add(i << shift)); 22740fe15e0SLoGin } else { 22840fe15e0SLoGin return None; 22940fe15e0SLoGin } 23040fe15e0SLoGin } 23140fe15e0SLoGin 23240fe15e0SLoGin /// 获取当前页表的第i个页表项所在的虚拟地址(注意与entry_base进行区分) 23340fe15e0SLoGin pub unsafe fn entry_virt(&self, i: usize) -> Option<VirtAddr> { 23440fe15e0SLoGin if i < Arch::PAGE_ENTRY_NUM { 23540fe15e0SLoGin return Some(self.virt().add(i * Arch::PAGE_ENTRY_SIZE)); 23640fe15e0SLoGin } else { 23740fe15e0SLoGin return None; 23840fe15e0SLoGin } 23940fe15e0SLoGin } 24040fe15e0SLoGin 24140fe15e0SLoGin /// 获取当前页表的第i个页表项 24240fe15e0SLoGin pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> { 24340fe15e0SLoGin let entry_virt = self.entry_virt(i)?; 2447a29d4fcSLoGin return Some(PageEntry::from_usize(Arch::read::<usize>(entry_virt))); 24540fe15e0SLoGin } 24640fe15e0SLoGin 24740fe15e0SLoGin /// 设置当前页表的第i个页表项 24840fe15e0SLoGin pub unsafe fn set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()> { 24940fe15e0SLoGin let entry_virt = self.entry_virt(i)?; 25040fe15e0SLoGin Arch::write::<usize>(entry_virt, entry.data()); 25140fe15e0SLoGin return Some(()); 25240fe15e0SLoGin } 25340fe15e0SLoGin 25440fe15e0SLoGin /// 判断当前页表的第i个页表项是否已经填写了值 25540fe15e0SLoGin /// 25640fe15e0SLoGin /// ## 参数 25740fe15e0SLoGin /// - Some(true) 如果已经填写了值 25840fe15e0SLoGin /// - Some(false) 如果未填写值 25940fe15e0SLoGin /// - None 如果i超出了页表项的范围 26040fe15e0SLoGin pub fn entry_mapped(&self, i: usize) -> Option<bool> { 26140fe15e0SLoGin let etv = unsafe { self.entry_virt(i) }?; 26240fe15e0SLoGin if unsafe { Arch::read::<usize>(etv) } != 0 { 26340fe15e0SLoGin return Some(true); 26440fe15e0SLoGin } else { 26540fe15e0SLoGin return Some(false); 26640fe15e0SLoGin } 26740fe15e0SLoGin } 26840fe15e0SLoGin 26940fe15e0SLoGin /// 根据虚拟地址,获取对应的页表项在页表中的下标 27040fe15e0SLoGin /// 27140fe15e0SLoGin /// ## 参数 27240fe15e0SLoGin /// 27340fe15e0SLoGin /// - addr: 虚拟地址 27440fe15e0SLoGin /// 27540fe15e0SLoGin /// ## 返回值 27640fe15e0SLoGin /// 27740fe15e0SLoGin /// 页表项在页表中的下标。如果addr不在当前页表所表示的虚拟地址空间中,则返回None 278a17651b1SMemoryShore pub fn index_of(&self, addr: VirtAddr) -> Option<usize> { 27940fe15e0SLoGin let addr = VirtAddr::new(addr.data() & Arch::PAGE_ADDRESS_MASK); 28040fe15e0SLoGin let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT; 28140fe15e0SLoGin 28240fe15e0SLoGin let mask = (MMArch::PAGE_ENTRY_NUM << shift) - 1; 28340fe15e0SLoGin if addr < self.base || addr >= self.base.add(mask) { 28440fe15e0SLoGin return None; 28540fe15e0SLoGin } else { 28640fe15e0SLoGin return Some((addr.data() >> shift) & MMArch::PAGE_ENTRY_MASK); 28740fe15e0SLoGin } 28840fe15e0SLoGin } 28940fe15e0SLoGin 29040fe15e0SLoGin /// 获取第i个页表项指向的下一级页表 29140fe15e0SLoGin pub unsafe fn next_level_table(&self, index: usize) -> Option<Self> { 29240fe15e0SLoGin if self.level == 0 { 29340fe15e0SLoGin return None; 29440fe15e0SLoGin } 29540fe15e0SLoGin 29640fe15e0SLoGin // 返回下一级页表 29740fe15e0SLoGin return Some(PageTable::new( 29840fe15e0SLoGin self.entry_base(index)?, 29940fe15e0SLoGin self.entry(index)?.address().ok()?, 30040fe15e0SLoGin self.level - 1, 30140fe15e0SLoGin )); 30240fe15e0SLoGin } 303a17651b1SMemoryShore 304a17651b1SMemoryShore /// 拷贝页表 305a17651b1SMemoryShore /// ## 参数 306a17651b1SMemoryShore /// 307a17651b1SMemoryShore /// - `allocator`: 物理页框分配器 308a17651b1SMemoryShore /// - `copy_on_write`: 是否写时复制 309a17651b1SMemoryShore pub unsafe fn clone( 310a17651b1SMemoryShore &self, 311a17651b1SMemoryShore allocator: &mut impl FrameAllocator, 312a17651b1SMemoryShore copy_on_write: bool, 313a17651b1SMemoryShore ) -> Option<PageTable<Arch>> { 314a17651b1SMemoryShore // 分配新页面作为新的页表 315a17651b1SMemoryShore let phys = allocator.allocate_one()?; 316a17651b1SMemoryShore let frame = MMArch::phys_2_virt(phys).unwrap(); 317a17651b1SMemoryShore MMArch::write_bytes(frame, 0, MMArch::PAGE_SIZE); 318a17651b1SMemoryShore let new_table = PageTable::new(self.base, phys, self.level); 319a17651b1SMemoryShore if self.level == 0 { 320a17651b1SMemoryShore for i in 0..Arch::PAGE_ENTRY_NUM { 321a17651b1SMemoryShore if let Some(mut entry) = self.entry(i) { 322a17651b1SMemoryShore if entry.present() { 323a17651b1SMemoryShore if copy_on_write { 324a17651b1SMemoryShore let mut new_flags = entry.flags().set_write(false); 325a17651b1SMemoryShore entry.set_flags(new_flags); 326a17651b1SMemoryShore self.set_entry(i, entry); 327a17651b1SMemoryShore new_flags = new_flags.set_dirty(false); 328a17651b1SMemoryShore entry.set_flags(new_flags); 329a17651b1SMemoryShore new_table.set_entry(i, entry); 330a17651b1SMemoryShore } else { 331a17651b1SMemoryShore let phys = allocator.allocate_one()?; 332a17651b1SMemoryShore let mut anon_vma_guard = page_manager_lock_irqsave(); 333a17651b1SMemoryShore anon_vma_guard.insert(phys, Page::new(false)); 334a17651b1SMemoryShore let old_phys = entry.address().unwrap(); 335a17651b1SMemoryShore let frame = MMArch::phys_2_virt(phys).unwrap().data() as *mut u8; 336a17651b1SMemoryShore frame.copy_from_nonoverlapping( 337a17651b1SMemoryShore MMArch::phys_2_virt(old_phys).unwrap().data() as *mut u8, 338a17651b1SMemoryShore MMArch::PAGE_SIZE, 339a17651b1SMemoryShore ); 340a17651b1SMemoryShore new_table.set_entry(i, PageEntry::new(phys, entry.flags())); 341a17651b1SMemoryShore } 342a17651b1SMemoryShore } 343a17651b1SMemoryShore } 344a17651b1SMemoryShore } 345a17651b1SMemoryShore } else { 346a17651b1SMemoryShore // 非一级页表拷贝时,对每个页表项对应的页表都进行拷贝 347a17651b1SMemoryShore for i in 0..MMArch::PAGE_ENTRY_NUM { 348a17651b1SMemoryShore if let Some(next_table) = self.next_level_table(i) { 349a17651b1SMemoryShore let table = next_table.clone(allocator, copy_on_write)?; 350a17651b1SMemoryShore let old_entry = self.entry(i).unwrap(); 351a17651b1SMemoryShore let entry = PageEntry::new(table.phys(), old_entry.flags()); 352a17651b1SMemoryShore new_table.set_entry(i, entry); 353a17651b1SMemoryShore } 354a17651b1SMemoryShore } 355a17651b1SMemoryShore } 356a17651b1SMemoryShore Some(new_table) 357a17651b1SMemoryShore } 35840fe15e0SLoGin } 35940fe15e0SLoGin 36040fe15e0SLoGin /// 页表项 36140fe15e0SLoGin #[derive(Copy, Clone)] 36240fe15e0SLoGin pub struct PageEntry<Arch> { 36340fe15e0SLoGin data: usize, 36440fe15e0SLoGin phantom: PhantomData<Arch>, 36540fe15e0SLoGin } 36640fe15e0SLoGin 36740fe15e0SLoGin impl<Arch> Debug for PageEntry<Arch> { 36840fe15e0SLoGin fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { 36940fe15e0SLoGin f.write_fmt(format_args!("PageEntry({:#x})", self.data)) 37040fe15e0SLoGin } 37140fe15e0SLoGin } 37240fe15e0SLoGin 37340fe15e0SLoGin impl<Arch: MemoryManagementArch> PageEntry<Arch> { 37440fe15e0SLoGin #[inline(always)] 3757a29d4fcSLoGin pub fn new(paddr: PhysAddr, flags: PageFlags<Arch>) -> Self { 3767a29d4fcSLoGin Self { 3777a29d4fcSLoGin data: MMArch::make_entry(paddr, flags.data()), 3787a29d4fcSLoGin phantom: PhantomData, 3797a29d4fcSLoGin } 3807a29d4fcSLoGin } 3817a29d4fcSLoGin #[inline(always)] 3827a29d4fcSLoGin pub fn from_usize(data: usize) -> Self { 38340fe15e0SLoGin Self { 38440fe15e0SLoGin data, 38540fe15e0SLoGin phantom: PhantomData, 38640fe15e0SLoGin } 38740fe15e0SLoGin } 38840fe15e0SLoGin 38940fe15e0SLoGin #[inline(always)] 39040fe15e0SLoGin pub fn data(&self) -> usize { 39140fe15e0SLoGin self.data 39240fe15e0SLoGin } 39340fe15e0SLoGin 39440fe15e0SLoGin /// 获取当前页表项指向的物理地址 39540fe15e0SLoGin /// 39640fe15e0SLoGin /// ## 返回值 39740fe15e0SLoGin /// 39840fe15e0SLoGin /// - Ok(PhysAddr) 如果当前页面存在于物理内存中, 返回物理地址 39940fe15e0SLoGin /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址 40040fe15e0SLoGin #[inline(always)] 40140fe15e0SLoGin pub fn address(&self) -> Result<PhysAddr, PhysAddr> { 4027a29d4fcSLoGin let paddr: PhysAddr = { 4037a29d4fcSLoGin #[cfg(target_arch = "x86_64")] 4047a29d4fcSLoGin { 4057a29d4fcSLoGin PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK) 4067a29d4fcSLoGin } 4077a29d4fcSLoGin 4087a29d4fcSLoGin #[cfg(target_arch = "riscv64")] 4097a29d4fcSLoGin { 410453452ccSLoGin let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 54) - 1); 4117a29d4fcSLoGin super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address() 4127a29d4fcSLoGin } 4137a29d4fcSLoGin }; 41440fe15e0SLoGin 41540fe15e0SLoGin if self.present() { 41640fe15e0SLoGin Ok(paddr) 41740fe15e0SLoGin } else { 41840fe15e0SLoGin Err(paddr) 41940fe15e0SLoGin } 42040fe15e0SLoGin } 42140fe15e0SLoGin 42240fe15e0SLoGin #[inline(always)] 42340fe15e0SLoGin pub fn flags(&self) -> PageFlags<Arch> { 42440fe15e0SLoGin unsafe { PageFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) } 42540fe15e0SLoGin } 42640fe15e0SLoGin 42740fe15e0SLoGin #[inline(always)] 42840fe15e0SLoGin pub fn set_flags(&mut self, flags: PageFlags<Arch>) { 42940fe15e0SLoGin self.data = (self.data & !Arch::ENTRY_FLAGS_MASK) | flags.data(); 43040fe15e0SLoGin } 43140fe15e0SLoGin 43240fe15e0SLoGin #[inline(always)] 43340fe15e0SLoGin pub fn present(&self) -> bool { 43440fe15e0SLoGin return self.data & Arch::ENTRY_FLAG_PRESENT != 0; 43540fe15e0SLoGin } 436a17651b1SMemoryShore 437a17651b1SMemoryShore #[inline(always)] 438a17651b1SMemoryShore pub fn empty(&self) -> bool { 439a17651b1SMemoryShore self.data & !(Arch::ENTRY_FLAG_DIRTY & Arch::ENTRY_FLAG_ACCESSED) == 0 440a17651b1SMemoryShore } 441a17651b1SMemoryShore 442a17651b1SMemoryShore #[inline(always)] 443a17651b1SMemoryShore pub fn protnone(&self) -> bool { 444a17651b1SMemoryShore return self.data & (Arch::ENTRY_FLAG_PRESENT | Arch::ENTRY_FLAG_GLOBAL) 445a17651b1SMemoryShore == Arch::ENTRY_FLAG_GLOBAL; 446a17651b1SMemoryShore } 447a17651b1SMemoryShore 448a17651b1SMemoryShore #[inline(always)] 449a17651b1SMemoryShore pub fn write(&self) -> bool { 450a17651b1SMemoryShore return self.data & Arch::ENTRY_FLAG_READWRITE != 0; 451a17651b1SMemoryShore } 45240fe15e0SLoGin } 45340fe15e0SLoGin 45440fe15e0SLoGin /// 页表项的标志位 45540fe15e0SLoGin #[derive(Copy, Clone, Hash)] 45640fe15e0SLoGin pub struct PageFlags<Arch> { 45740fe15e0SLoGin data: usize, 45840fe15e0SLoGin phantom: PhantomData<Arch>, 45940fe15e0SLoGin } 46040fe15e0SLoGin 461*dc9b4feaSLoGin impl<Arch: MemoryManagementArch> Default for PageFlags<Arch> { 462*dc9b4feaSLoGin fn default() -> Self { 463*dc9b4feaSLoGin Self::new() 464*dc9b4feaSLoGin } 465*dc9b4feaSLoGin } 466*dc9b4feaSLoGin 46740fe15e0SLoGin #[allow(dead_code)] 46840fe15e0SLoGin impl<Arch: MemoryManagementArch> PageFlags<Arch> { 46940fe15e0SLoGin #[inline(always)] 47040fe15e0SLoGin pub fn new() -> Self { 47140fe15e0SLoGin let mut r = unsafe { 47240fe15e0SLoGin Self::from_data( 47340fe15e0SLoGin Arch::ENTRY_FLAG_DEFAULT_PAGE 47440fe15e0SLoGin | Arch::ENTRY_FLAG_READONLY 47540fe15e0SLoGin | Arch::ENTRY_FLAG_NO_EXEC, 47640fe15e0SLoGin ) 47740fe15e0SLoGin }; 47840fe15e0SLoGin 47940fe15e0SLoGin #[cfg(target_arch = "x86_64")] 48040fe15e0SLoGin { 48140fe15e0SLoGin if crate::arch::mm::X86_64MMArch::is_xd_reserved() { 48240fe15e0SLoGin r = r.set_execute(true); 48340fe15e0SLoGin } 48440fe15e0SLoGin } 48540fe15e0SLoGin 48640fe15e0SLoGin return r; 48740fe15e0SLoGin } 48840fe15e0SLoGin 48940fe15e0SLoGin /// 根据ProtFlags生成PageFlags 49040fe15e0SLoGin /// 49140fe15e0SLoGin /// ## 参数 49240fe15e0SLoGin /// 49340fe15e0SLoGin /// - prot_flags: 页的保护标志 49440fe15e0SLoGin /// - user: 用户空间是否可访问 49540fe15e0SLoGin pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> PageFlags<Arch> { 49640fe15e0SLoGin let flags: PageFlags<Arch> = PageFlags::new() 49740fe15e0SLoGin .set_user(user) 49840fe15e0SLoGin .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC)) 49940fe15e0SLoGin .set_write(prot_flags.contains(ProtFlags::PROT_WRITE)); 50040fe15e0SLoGin 50140fe15e0SLoGin return flags; 50240fe15e0SLoGin } 50340fe15e0SLoGin 50440fe15e0SLoGin #[inline(always)] 50540fe15e0SLoGin pub fn data(&self) -> usize { 50640fe15e0SLoGin self.data 50740fe15e0SLoGin } 50840fe15e0SLoGin 50940fe15e0SLoGin #[inline(always)] 51040fe15e0SLoGin pub const unsafe fn from_data(data: usize) -> Self { 51140fe15e0SLoGin return Self { 512b5b571e0SLoGin data, 51340fe15e0SLoGin phantom: PhantomData, 51440fe15e0SLoGin }; 51540fe15e0SLoGin } 51640fe15e0SLoGin 51740fe15e0SLoGin /// 为新页表的页表项设置默认值 51840fe15e0SLoGin /// 51940fe15e0SLoGin /// 默认值为: 52040fe15e0SLoGin /// - present 52140fe15e0SLoGin /// - read only 52240fe15e0SLoGin /// - kernel space 52340fe15e0SLoGin /// - no exec 52440fe15e0SLoGin #[inline(always)] 52540fe15e0SLoGin pub fn new_page_table(user: bool) -> Self { 52640fe15e0SLoGin return unsafe { 5277a29d4fcSLoGin let r = { 5287a29d4fcSLoGin #[cfg(target_arch = "x86_64")] 5297a29d4fcSLoGin { 5307a29d4fcSLoGin Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE) 5317a29d4fcSLoGin } 5327a29d4fcSLoGin 5337a29d4fcSLoGin #[cfg(target_arch = "riscv64")] 5347a29d4fcSLoGin { 5357a29d4fcSLoGin // riscv64指向下一级页表的页表项,不应设置R/W/X权限位 5367a29d4fcSLoGin Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE) 5377a29d4fcSLoGin } 5387a29d4fcSLoGin }; 539471d65cfSLoGin 540471d65cfSLoGin #[cfg(target_arch = "x86_64")] 541471d65cfSLoGin { 54240fe15e0SLoGin if user { 54340fe15e0SLoGin r.set_user(true) 54440fe15e0SLoGin } else { 54540fe15e0SLoGin r 54640fe15e0SLoGin } 547471d65cfSLoGin } 548471d65cfSLoGin 549471d65cfSLoGin #[cfg(target_arch = "riscv64")] 550471d65cfSLoGin { 551471d65cfSLoGin r 552471d65cfSLoGin } 55340fe15e0SLoGin }; 55440fe15e0SLoGin } 55540fe15e0SLoGin 55640fe15e0SLoGin /// 取得当前页表项的所有权,更新当前页表项的标志位,并返回更新后的页表项。 55740fe15e0SLoGin /// 55840fe15e0SLoGin /// ## 参数 55940fe15e0SLoGin /// - flag 要更新的标志位的值 56040fe15e0SLoGin /// - value 如果为true,那么将flag对应的位设置为1,否则设置为0 56140fe15e0SLoGin /// 56240fe15e0SLoGin /// ## 返回值 56340fe15e0SLoGin /// 56440fe15e0SLoGin /// 更新后的页表项 56540fe15e0SLoGin #[inline(always)] 56640fe15e0SLoGin #[must_use] 56740fe15e0SLoGin pub fn update_flags(mut self, flag: usize, value: bool) -> Self { 56840fe15e0SLoGin if value { 56940fe15e0SLoGin self.data |= flag; 57040fe15e0SLoGin } else { 57140fe15e0SLoGin self.data &= !flag; 57240fe15e0SLoGin } 57340fe15e0SLoGin return self; 57440fe15e0SLoGin } 57540fe15e0SLoGin 57640fe15e0SLoGin /// 判断当前页表项是否存在指定的flag(只有全部flag都存在才返回true) 57740fe15e0SLoGin #[inline(always)] 57840fe15e0SLoGin pub fn has_flag(&self, flag: usize) -> bool { 57940fe15e0SLoGin return self.data & flag == flag; 58040fe15e0SLoGin } 58140fe15e0SLoGin 58240fe15e0SLoGin #[inline(always)] 58340fe15e0SLoGin pub fn present(&self) -> bool { 58440fe15e0SLoGin return self.has_flag(Arch::ENTRY_FLAG_PRESENT); 58540fe15e0SLoGin } 58640fe15e0SLoGin 58740fe15e0SLoGin /// 设置当前页表项的权限 58840fe15e0SLoGin /// 58940fe15e0SLoGin /// @param value 如果为true,那么将当前页表项的权限设置为用户态可访问 59040fe15e0SLoGin #[must_use] 59140fe15e0SLoGin #[inline(always)] 59240fe15e0SLoGin pub fn set_user(self, value: bool) -> Self { 59340fe15e0SLoGin return self.update_flags(Arch::ENTRY_FLAG_USER, value); 59440fe15e0SLoGin } 59540fe15e0SLoGin 59640fe15e0SLoGin /// 用户态是否可以访问当前页表项 59740fe15e0SLoGin #[inline(always)] 59840fe15e0SLoGin pub fn has_user(&self) -> bool { 59940fe15e0SLoGin return self.has_flag(Arch::ENTRY_FLAG_USER); 60040fe15e0SLoGin } 60140fe15e0SLoGin 60240fe15e0SLoGin /// 设置当前页表项的可写性, 如果为true,那么将当前页表项的权限设置为可写, 否则设置为只读 60340fe15e0SLoGin /// 60440fe15e0SLoGin /// ## 返回值 60540fe15e0SLoGin /// 60640fe15e0SLoGin /// 更新后的页表项. 60740fe15e0SLoGin /// 60840fe15e0SLoGin /// **请注意,**本函数会取得当前页表项的所有权,因此返回的页表项不是原来的页表项 60940fe15e0SLoGin #[must_use] 61040fe15e0SLoGin #[inline(always)] 61140fe15e0SLoGin pub fn set_write(self, value: bool) -> Self { 6127a29d4fcSLoGin #[cfg(target_arch = "x86_64")] 6137a29d4fcSLoGin { 61440fe15e0SLoGin // 有的架构同时具有可写和不可写的标志位,因此需要同时更新 61540fe15e0SLoGin return self 61640fe15e0SLoGin .update_flags(Arch::ENTRY_FLAG_READONLY, !value) 61740fe15e0SLoGin .update_flags(Arch::ENTRY_FLAG_READWRITE, value); 61840fe15e0SLoGin } 61940fe15e0SLoGin 6207a29d4fcSLoGin #[cfg(target_arch = "riscv64")] 6217a29d4fcSLoGin { 6227a29d4fcSLoGin if value { 6237a29d4fcSLoGin return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true); 6247a29d4fcSLoGin } else { 625471d65cfSLoGin return self 626471d65cfSLoGin .update_flags(Arch::ENTRY_FLAG_READONLY, true) 627471d65cfSLoGin .update_flags(Arch::ENTRY_FLAG_WRITEABLE, false); 6287a29d4fcSLoGin } 6297a29d4fcSLoGin } 6307a29d4fcSLoGin } 6317a29d4fcSLoGin 63240fe15e0SLoGin /// 当前页表项是否可写 63340fe15e0SLoGin #[inline(always)] 63440fe15e0SLoGin pub fn has_write(&self) -> bool { 63540fe15e0SLoGin // 有的架构同时具有可写和不可写的标志位,因此需要同时判断 63640fe15e0SLoGin return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY) 63740fe15e0SLoGin == Arch::ENTRY_FLAG_READWRITE; 63840fe15e0SLoGin } 63940fe15e0SLoGin 64040fe15e0SLoGin /// 设置当前页表项的可执行性, 如果为true,那么将当前页表项的权限设置为可执行, 否则设置为不可执行 64140fe15e0SLoGin #[must_use] 64240fe15e0SLoGin #[inline(always)] 64340fe15e0SLoGin pub fn set_execute(self, mut value: bool) -> Self { 64440fe15e0SLoGin #[cfg(target_arch = "x86_64")] 64540fe15e0SLoGin { 64640fe15e0SLoGin // 如果xd位被保留,那么将可执行性设置为true 64740fe15e0SLoGin if crate::arch::mm::X86_64MMArch::is_xd_reserved() { 64840fe15e0SLoGin value = true; 64940fe15e0SLoGin } 65040fe15e0SLoGin } 65140fe15e0SLoGin 65240fe15e0SLoGin // 有的架构同时具有可执行和不可执行的标志位,因此需要同时更新 65340fe15e0SLoGin return self 65440fe15e0SLoGin .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value) 65540fe15e0SLoGin .update_flags(Arch::ENTRY_FLAG_EXEC, value); 65640fe15e0SLoGin } 65740fe15e0SLoGin 65840fe15e0SLoGin /// 当前页表项是否可执行 65940fe15e0SLoGin #[inline(always)] 66040fe15e0SLoGin pub fn has_execute(&self) -> bool { 66140fe15e0SLoGin // 有的架构同时具有可执行和不可执行的标志位,因此需要同时判断 66240fe15e0SLoGin return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC) 66340fe15e0SLoGin == Arch::ENTRY_FLAG_EXEC; 66440fe15e0SLoGin } 66540fe15e0SLoGin 66640fe15e0SLoGin /// 设置当前页表项的缓存策略 66740fe15e0SLoGin /// 66840fe15e0SLoGin /// ## 参数 66940fe15e0SLoGin /// 67040fe15e0SLoGin /// - value: 如果为true,那么将当前页表项的缓存策略设置为不缓存。 67140fe15e0SLoGin #[inline(always)] 67240fe15e0SLoGin pub fn set_page_cache_disable(self, value: bool) -> Self { 67340fe15e0SLoGin return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value); 67440fe15e0SLoGin } 67540fe15e0SLoGin 67640fe15e0SLoGin /// 获取当前页表项的缓存策略 67740fe15e0SLoGin /// 67840fe15e0SLoGin /// ## 返回值 67940fe15e0SLoGin /// 68040fe15e0SLoGin /// 如果当前页表项的缓存策略为不缓存,那么返回true,否则返回false。 68140fe15e0SLoGin #[inline(always)] 68240fe15e0SLoGin pub fn has_page_cache_disable(&self) -> bool { 68340fe15e0SLoGin return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE); 68440fe15e0SLoGin } 68540fe15e0SLoGin 68640fe15e0SLoGin /// 设置当前页表项的写穿策略 68740fe15e0SLoGin /// 68840fe15e0SLoGin /// ## 参数 68940fe15e0SLoGin /// 69040fe15e0SLoGin /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。 69140fe15e0SLoGin #[inline(always)] 69240fe15e0SLoGin pub fn set_page_write_through(self, value: bool) -> Self { 69340fe15e0SLoGin return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value); 69440fe15e0SLoGin } 69540fe15e0SLoGin 696731bc2b3SLoGin #[inline(always)] 697731bc2b3SLoGin pub fn set_page_global(self, value: bool) -> Self { 698731bc2b3SLoGin return self.update_flags(MMArch::ENTRY_FLAG_GLOBAL, value); 699731bc2b3SLoGin } 700731bc2b3SLoGin 70140fe15e0SLoGin /// 获取当前页表项的写穿策略 70240fe15e0SLoGin /// 70340fe15e0SLoGin /// ## 返回值 70440fe15e0SLoGin /// 70540fe15e0SLoGin /// 如果当前页表项的写穿策略为写穿,那么返回true,否则返回false。 70640fe15e0SLoGin #[inline(always)] 70740fe15e0SLoGin pub fn has_page_write_through(&self) -> bool { 70840fe15e0SLoGin return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH); 70940fe15e0SLoGin } 71040fe15e0SLoGin 711a17651b1SMemoryShore /// 设置当前页表是否为脏页 712a17651b1SMemoryShore /// 713a17651b1SMemoryShore /// ## 参数 714a17651b1SMemoryShore /// 715a17651b1SMemoryShore /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。 716a17651b1SMemoryShore #[inline(always)] 717a17651b1SMemoryShore pub fn set_dirty(self, value: bool) -> Self { 718a17651b1SMemoryShore return self.update_flags(Arch::ENTRY_FLAG_DIRTY, value); 719a17651b1SMemoryShore } 720a17651b1SMemoryShore 721a17651b1SMemoryShore /// 设置当前页表被访问 722a17651b1SMemoryShore /// 723a17651b1SMemoryShore /// ## 参数 724a17651b1SMemoryShore /// 725a17651b1SMemoryShore /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。 726a17651b1SMemoryShore #[inline(always)] 727a17651b1SMemoryShore pub fn set_access(self, value: bool) -> Self { 728a17651b1SMemoryShore return self.update_flags(Arch::ENTRY_FLAG_ACCESSED, value); 729a17651b1SMemoryShore } 730a17651b1SMemoryShore 731a17651b1SMemoryShore /// 设置指向的页是否为大页 732a17651b1SMemoryShore /// 733a17651b1SMemoryShore /// ## 参数 734a17651b1SMemoryShore /// 735a17651b1SMemoryShore /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。 736a17651b1SMemoryShore #[inline(always)] 737a17651b1SMemoryShore pub fn set_huge_page(self, value: bool) -> Self { 738a17651b1SMemoryShore return self.update_flags(Arch::ENTRY_FLAG_HUGE_PAGE, value); 739a17651b1SMemoryShore } 740a17651b1SMemoryShore 74140fe15e0SLoGin /// MMIO内存的页表项标志 74240fe15e0SLoGin #[inline(always)] 74340fe15e0SLoGin pub fn mmio_flags() -> Self { 744471d65cfSLoGin #[cfg(target_arch = "x86_64")] 745471d65cfSLoGin { 746471d65cfSLoGin Self::new() 74740fe15e0SLoGin .set_user(false) 74840fe15e0SLoGin .set_write(true) 74940fe15e0SLoGin .set_execute(true) 75040fe15e0SLoGin .set_page_cache_disable(true) 751731bc2b3SLoGin .set_page_write_through(true) 752471d65cfSLoGin .set_page_global(true) 753471d65cfSLoGin } 754471d65cfSLoGin 755471d65cfSLoGin #[cfg(target_arch = "riscv64")] 756471d65cfSLoGin { 757471d65cfSLoGin Self::new() 758471d65cfSLoGin .set_user(false) 759471d65cfSLoGin .set_write(true) 760471d65cfSLoGin .set_execute(true) 761471d65cfSLoGin .set_page_global(true) 762471d65cfSLoGin } 76340fe15e0SLoGin } 76440fe15e0SLoGin } 76540fe15e0SLoGin 76640fe15e0SLoGin impl<Arch: MemoryManagementArch> fmt::Debug for PageFlags<Arch> { 76740fe15e0SLoGin fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 76840fe15e0SLoGin f.debug_struct("PageFlags") 76940fe15e0SLoGin .field("bits", &format_args!("{:#0x}", self.data)) 77040fe15e0SLoGin .field("present", &self.present()) 77140fe15e0SLoGin .field("has_write", &self.has_write()) 77240fe15e0SLoGin .field("has_execute", &self.has_execute()) 77340fe15e0SLoGin .field("has_user", &self.has_user()) 77440fe15e0SLoGin .finish() 77540fe15e0SLoGin } 77640fe15e0SLoGin } 77740fe15e0SLoGin 77840fe15e0SLoGin /// 页表映射器 77940fe15e0SLoGin #[derive(Hash)] 78040fe15e0SLoGin pub struct PageMapper<Arch, F> { 78140fe15e0SLoGin /// 页表类型 78240fe15e0SLoGin table_kind: PageTableKind, 78340fe15e0SLoGin /// 根页表物理地址 78440fe15e0SLoGin table_paddr: PhysAddr, 78540fe15e0SLoGin /// 页分配器 78640fe15e0SLoGin frame_allocator: F, 78740fe15e0SLoGin phantom: PhantomData<fn() -> Arch>, 78840fe15e0SLoGin } 78940fe15e0SLoGin 79040fe15e0SLoGin impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> { 79140fe15e0SLoGin /// 创建新的页面映射器 79240fe15e0SLoGin /// 79340fe15e0SLoGin /// ## 参数 79440fe15e0SLoGin /// - table_kind 页表类型 79540fe15e0SLoGin /// - table_paddr 根页表物理地址 79640fe15e0SLoGin /// - allocator 页分配器 79740fe15e0SLoGin /// 79840fe15e0SLoGin /// ## 返回值 79940fe15e0SLoGin /// 80040fe15e0SLoGin /// 页面映射器 80140fe15e0SLoGin pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self { 80240fe15e0SLoGin return Self { 80340fe15e0SLoGin table_kind, 80440fe15e0SLoGin table_paddr, 80540fe15e0SLoGin frame_allocator: allocator, 80640fe15e0SLoGin phantom: PhantomData, 80740fe15e0SLoGin }; 80840fe15e0SLoGin } 80940fe15e0SLoGin 81040fe15e0SLoGin /// 创建页表,并为这个页表创建页面映射器 81140fe15e0SLoGin pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> { 81240fe15e0SLoGin let table_paddr = allocator.allocate_one()?; 81340fe15e0SLoGin // 清空页表 81440fe15e0SLoGin let table_vaddr = Arch::phys_2_virt(table_paddr)?; 81540fe15e0SLoGin Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE); 81640fe15e0SLoGin return Some(Self::new(table_kind, table_paddr, allocator)); 81740fe15e0SLoGin } 81840fe15e0SLoGin 81940fe15e0SLoGin /// 获取当前页表的页面映射器 82040fe15e0SLoGin #[inline(always)] 82140fe15e0SLoGin pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self { 82240fe15e0SLoGin let table_paddr = Arch::table(table_kind); 82340fe15e0SLoGin return Self::new(table_kind, table_paddr, allocator); 82440fe15e0SLoGin } 82540fe15e0SLoGin 82640fe15e0SLoGin /// 判断当前页表分配器所属的页表是否是当前页表 82740fe15e0SLoGin #[inline(always)] 82840fe15e0SLoGin pub fn is_current(&self) -> bool { 82940fe15e0SLoGin return unsafe { self.table().phys() == Arch::table(self.table_kind) }; 83040fe15e0SLoGin } 83140fe15e0SLoGin 83240fe15e0SLoGin /// 将当前页表分配器所属的页表设置为当前页表 83340fe15e0SLoGin #[inline(always)] 83440fe15e0SLoGin pub unsafe fn make_current(&self) { 83540fe15e0SLoGin Arch::set_table(self.table_kind, self.table_paddr); 83640fe15e0SLoGin } 83740fe15e0SLoGin 83840fe15e0SLoGin /// 获取当前页表分配器所属的根页表的结构体 83940fe15e0SLoGin #[inline(always)] 84040fe15e0SLoGin pub fn table(&self) -> PageTable<Arch> { 84140fe15e0SLoGin // 由于只能通过new方法创建PageMapper,因此这里假定table_paddr是有效的 84240fe15e0SLoGin return unsafe { 84340fe15e0SLoGin PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1) 84440fe15e0SLoGin }; 84540fe15e0SLoGin } 84640fe15e0SLoGin 84740fe15e0SLoGin /// 获取当前PageMapper所对应的页分配器实例的引用 84840fe15e0SLoGin #[inline(always)] 84940fe15e0SLoGin #[allow(dead_code)] 85040fe15e0SLoGin pub fn allocator_ref(&self) -> &F { 85140fe15e0SLoGin return &self.frame_allocator; 85240fe15e0SLoGin } 85340fe15e0SLoGin 85440fe15e0SLoGin /// 获取当前PageMapper所对应的页分配器实例的可变引用 85540fe15e0SLoGin #[inline(always)] 85640fe15e0SLoGin pub fn allocator_mut(&mut self) -> &mut F { 85740fe15e0SLoGin return &mut self.frame_allocator; 85840fe15e0SLoGin } 85940fe15e0SLoGin 86040fe15e0SLoGin /// 从当前PageMapper的页分配器中分配一个物理页,并将其映射到指定的虚拟地址 86140fe15e0SLoGin pub unsafe fn map( 86240fe15e0SLoGin &mut self, 86340fe15e0SLoGin virt: VirtAddr, 86440fe15e0SLoGin flags: PageFlags<Arch>, 86540fe15e0SLoGin ) -> Option<PageFlush<Arch>> { 86640fe15e0SLoGin compiler_fence(Ordering::SeqCst); 86740fe15e0SLoGin let phys: PhysAddr = self.frame_allocator.allocate_one()?; 86840fe15e0SLoGin compiler_fence(Ordering::SeqCst); 86956cc4dbeSJomo 870de199e3cSMemoryShore unsafe { 871de199e3cSMemoryShore let vaddr = MMArch::phys_2_virt(phys).unwrap(); 872de199e3cSMemoryShore MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE); 873de199e3cSMemoryShore } 874de199e3cSMemoryShore 8756fc066acSJomo let mut page_manager_guard: SpinLockGuard<'static, PageManager> = 8766fc066acSJomo page_manager_lock_irqsave(); 8776fc066acSJomo if !page_manager_guard.contains(&phys) { 8786fc066acSJomo page_manager_guard.insert(phys, Page::new(false)) 8796fc066acSJomo } 8806fc066acSJomo 88140fe15e0SLoGin return self.map_phys(virt, phys, flags); 88240fe15e0SLoGin } 88340fe15e0SLoGin 88440fe15e0SLoGin /// 映射一个物理页到指定的虚拟地址 88540fe15e0SLoGin pub unsafe fn map_phys( 88640fe15e0SLoGin &mut self, 88740fe15e0SLoGin virt: VirtAddr, 88840fe15e0SLoGin phys: PhysAddr, 88940fe15e0SLoGin flags: PageFlags<Arch>, 89040fe15e0SLoGin ) -> Option<PageFlush<Arch>> { 89140fe15e0SLoGin // 验证虚拟地址和物理地址是否对齐 89240fe15e0SLoGin if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) { 8932eab6dd7S曾俊 error!( 89440fe15e0SLoGin "Try to map unaligned page: virt={:?}, phys={:?}", 8952eab6dd7S曾俊 virt, phys 89640fe15e0SLoGin ); 89740fe15e0SLoGin return None; 89840fe15e0SLoGin } 8997a29d4fcSLoGin 90040fe15e0SLoGin let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 90140fe15e0SLoGin 90240fe15e0SLoGin // TODO: 验证flags是否合法 90340fe15e0SLoGin 90440fe15e0SLoGin // 创建页表项 9057a29d4fcSLoGin let entry = PageEntry::new(phys, flags); 90640fe15e0SLoGin let mut table = self.table(); 90740fe15e0SLoGin loop { 90840fe15e0SLoGin let i = table.index_of(virt)?; 909471d65cfSLoGin 91040fe15e0SLoGin assert!(i < Arch::PAGE_ENTRY_NUM); 91140fe15e0SLoGin if table.level() == 0 { 91240fe15e0SLoGin compiler_fence(Ordering::SeqCst); 9137a29d4fcSLoGin 91440fe15e0SLoGin table.set_entry(i, entry); 91540fe15e0SLoGin compiler_fence(Ordering::SeqCst); 91640fe15e0SLoGin return Some(PageFlush::new(virt)); 91740fe15e0SLoGin } else { 91840fe15e0SLoGin let next_table = table.next_level_table(i); 91940fe15e0SLoGin if let Some(next_table) = next_table { 92040fe15e0SLoGin table = next_table; 9212eab6dd7S曾俊 // debug!("Mapping {:?} to next level table...", virt); 92240fe15e0SLoGin } else { 92340fe15e0SLoGin // 分配下一级页表 92440fe15e0SLoGin let frame = self.frame_allocator.allocate_one()?; 9257a29d4fcSLoGin 92640fe15e0SLoGin // 清空这个页帧 92740fe15e0SLoGin MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 92840fe15e0SLoGin // 设置页表项的flags 9297a29d4fcSLoGin let flags: PageFlags<Arch> = 93040fe15e0SLoGin PageFlags::new_page_table(virt.kind() == PageTableKind::User); 93140fe15e0SLoGin 93240fe15e0SLoGin // 把新分配的页表映射到当前页表 9337a29d4fcSLoGin table.set_entry(i, PageEntry::new(frame, flags)); 93440fe15e0SLoGin 93540fe15e0SLoGin // 获取新分配的页表 93640fe15e0SLoGin table = table.next_level_table(i)?; 93740fe15e0SLoGin } 93840fe15e0SLoGin } 93940fe15e0SLoGin } 94040fe15e0SLoGin } 94140fe15e0SLoGin 942a17651b1SMemoryShore /// 进行大页映射 943a17651b1SMemoryShore pub unsafe fn map_huge_page( 944a17651b1SMemoryShore &mut self, 945a17651b1SMemoryShore virt: VirtAddr, 946a17651b1SMemoryShore flags: PageFlags<Arch>, 947a17651b1SMemoryShore ) -> Option<PageFlush<Arch>> { 948a17651b1SMemoryShore // 验证虚拟地址是否对齐 949a17651b1SMemoryShore if !(virt.check_aligned(Arch::PAGE_SIZE)) { 9502eab6dd7S曾俊 error!("Try to map unaligned page: virt={:?}", virt); 951a17651b1SMemoryShore return None; 952a17651b1SMemoryShore } 953a17651b1SMemoryShore 954a17651b1SMemoryShore let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 955a17651b1SMemoryShore 956a17651b1SMemoryShore let mut table = self.table(); 957a17651b1SMemoryShore loop { 958a17651b1SMemoryShore let i = table.index_of(virt)?; 959a17651b1SMemoryShore assert!(i < Arch::PAGE_ENTRY_NUM); 960a17651b1SMemoryShore let next_table = table.next_level_table(i); 961a17651b1SMemoryShore if let Some(next_table) = next_table { 962a17651b1SMemoryShore table = next_table; 963a17651b1SMemoryShore } else { 964a17651b1SMemoryShore break; 965a17651b1SMemoryShore } 966a17651b1SMemoryShore } 967a17651b1SMemoryShore 968a17651b1SMemoryShore // 支持2M、1G大页,即页表层级为1、2级的页表可以映射大页 969a17651b1SMemoryShore if table.level == 0 || table.level > 2 { 970a17651b1SMemoryShore return None; 971a17651b1SMemoryShore } 972a17651b1SMemoryShore 973a17651b1SMemoryShore let (phys, count) = self.frame_allocator.allocate(PageFrameCount::new( 974a17651b1SMemoryShore Arch::PAGE_ENTRY_NUM.pow(table.level as u32), 975a17651b1SMemoryShore ))?; 976a17651b1SMemoryShore 977a17651b1SMemoryShore MMArch::write_bytes( 978a17651b1SMemoryShore MMArch::phys_2_virt(phys).unwrap(), 979a17651b1SMemoryShore 0, 980a17651b1SMemoryShore MMArch::PAGE_SIZE * count.data(), 981a17651b1SMemoryShore ); 982a17651b1SMemoryShore 983a17651b1SMemoryShore table.set_entry( 984a17651b1SMemoryShore table.index_of(virt)?, 985a17651b1SMemoryShore PageEntry::new(phys, flags.set_huge_page(true)), 986a17651b1SMemoryShore )?; 987a17651b1SMemoryShore Some(PageFlush::new(virt)) 988a17651b1SMemoryShore } 989a17651b1SMemoryShore 990a17651b1SMemoryShore /// 为虚拟地址分配指定层级的页表 991a17651b1SMemoryShore /// ## 参数 992a17651b1SMemoryShore /// 993a17651b1SMemoryShore /// - `virt`: 虚拟地址 994a17651b1SMemoryShore /// - `level`: 指定页表层级 995a17651b1SMemoryShore /// 996a17651b1SMemoryShore /// ## 返回值 997a17651b1SMemoryShore /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表 998a17651b1SMemoryShore /// - None: 对应页表不存在 999a17651b1SMemoryShore pub unsafe fn allocate_table( 1000a17651b1SMemoryShore &mut self, 1001a17651b1SMemoryShore virt: VirtAddr, 1002a17651b1SMemoryShore level: usize, 1003a17651b1SMemoryShore ) -> Option<PageTable<Arch>> { 1004a17651b1SMemoryShore let table = self.get_table(virt, level + 1)?; 1005a17651b1SMemoryShore let i = table.index_of(virt)?; 1006a17651b1SMemoryShore let frame = self.frame_allocator.allocate_one()?; 1007a17651b1SMemoryShore 1008a17651b1SMemoryShore // 清空这个页帧 1009a17651b1SMemoryShore MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 1010a17651b1SMemoryShore 1011a17651b1SMemoryShore // 设置页表项的flags 1012a17651b1SMemoryShore let flags: PageFlags<Arch> = PageFlags::new_page_table(virt.kind() == PageTableKind::User); 1013a17651b1SMemoryShore 1014a17651b1SMemoryShore table.set_entry(i, PageEntry::new(frame, flags)); 1015a17651b1SMemoryShore table.next_level_table(i) 1016a17651b1SMemoryShore } 1017a17651b1SMemoryShore 1018a17651b1SMemoryShore /// 获取虚拟地址的指定层级页表 1019a17651b1SMemoryShore /// ## 参数 1020a17651b1SMemoryShore /// 1021a17651b1SMemoryShore /// - `virt`: 虚拟地址 1022a17651b1SMemoryShore /// - `level`: 指定页表层级 1023a17651b1SMemoryShore /// 1024a17651b1SMemoryShore /// ## 返回值 1025a17651b1SMemoryShore /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表 1026a17651b1SMemoryShore /// - None: 对应页表不存在 1027a17651b1SMemoryShore pub fn get_table(&self, virt: VirtAddr, level: usize) -> Option<PageTable<Arch>> { 1028a17651b1SMemoryShore let mut table = self.table(); 1029a17651b1SMemoryShore if level > Arch::PAGE_LEVELS - 1 { 1030a17651b1SMemoryShore return None; 1031a17651b1SMemoryShore } 1032a17651b1SMemoryShore 1033a17651b1SMemoryShore unsafe { 1034a17651b1SMemoryShore loop { 1035a17651b1SMemoryShore if table.level == level { 1036a17651b1SMemoryShore return Some(table); 1037a17651b1SMemoryShore } 1038a17651b1SMemoryShore let i = table.index_of(virt)?; 1039a17651b1SMemoryShore assert!(i < Arch::PAGE_ENTRY_NUM); 1040a17651b1SMemoryShore 1041a17651b1SMemoryShore table = table.next_level_table(i)?; 1042a17651b1SMemoryShore } 1043a17651b1SMemoryShore } 1044a17651b1SMemoryShore } 1045a17651b1SMemoryShore 1046a17651b1SMemoryShore /// 获取虚拟地址在指定层级页表的PageEntry 1047a17651b1SMemoryShore /// ## 参数 1048a17651b1SMemoryShore /// 1049a17651b1SMemoryShore /// - `virt`: 虚拟地址 1050a17651b1SMemoryShore /// - `level`: 指定页表层级 1051a17651b1SMemoryShore /// 1052a17651b1SMemoryShore /// ## 返回值 1053a17651b1SMemoryShore /// - Some(PageEntry<Arch>): 虚拟地址在指定层级的页表的有效PageEntry 1054a17651b1SMemoryShore /// - None: 无对应的有效PageEntry 1055a17651b1SMemoryShore pub fn get_entry(&self, virt: VirtAddr, level: usize) -> Option<PageEntry<Arch>> { 1056a17651b1SMemoryShore let table = self.get_table(virt, level)?; 1057a17651b1SMemoryShore let i = table.index_of(virt)?; 1058a17651b1SMemoryShore let entry = unsafe { table.entry(i) }?; 1059a17651b1SMemoryShore 1060a17651b1SMemoryShore if !entry.empty() { 1061a17651b1SMemoryShore Some(entry) 1062a17651b1SMemoryShore } else { 1063a17651b1SMemoryShore None 1064a17651b1SMemoryShore } 1065a17651b1SMemoryShore 1066a17651b1SMemoryShore // let mut table = self.table(); 1067a17651b1SMemoryShore // if level > Arch::PAGE_LEVELS - 1 { 1068a17651b1SMemoryShore // return None; 1069a17651b1SMemoryShore // } 1070a17651b1SMemoryShore // unsafe { 1071a17651b1SMemoryShore // loop { 1072a17651b1SMemoryShore // let i = table.index_of(virt)?; 1073a17651b1SMemoryShore // assert!(i < Arch::PAGE_ENTRY_NUM); 1074a17651b1SMemoryShore 1075a17651b1SMemoryShore // if table.level == level { 1076a17651b1SMemoryShore // let entry = table.entry(i)?; 1077a17651b1SMemoryShore // if !entry.empty() { 1078a17651b1SMemoryShore // return Some(entry); 1079a17651b1SMemoryShore // } else { 1080a17651b1SMemoryShore // return None; 1081a17651b1SMemoryShore // } 1082a17651b1SMemoryShore // } 1083a17651b1SMemoryShore 1084a17651b1SMemoryShore // table = table.next_level_table(i)?; 1085a17651b1SMemoryShore // } 1086a17651b1SMemoryShore // } 1087a17651b1SMemoryShore } 1088a17651b1SMemoryShore 1089a17651b1SMemoryShore /// 拷贝用户空间映射 1090a17651b1SMemoryShore /// ## 参数 1091a17651b1SMemoryShore /// 1092a17651b1SMemoryShore /// - `umapper`: 要拷贝的用户空间 1093a17651b1SMemoryShore /// - `copy_on_write`: 是否写时复制 1094a17651b1SMemoryShore pub unsafe fn clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool) { 1095a17651b1SMemoryShore let old_table = umapper.table(); 1096a17651b1SMemoryShore let new_table = self.table(); 1097a17651b1SMemoryShore let allocator = self.allocator_mut(); 1098a17651b1SMemoryShore // 顶级页表的[0, PAGE_KERNEL_INDEX)项为用户空间映射 1099a17651b1SMemoryShore for entry_index in 0..Arch::PAGE_KERNEL_INDEX { 1100a17651b1SMemoryShore if let Some(next_table) = old_table.next_level_table(entry_index) { 1101a17651b1SMemoryShore let table = next_table.clone(allocator, copy_on_write).unwrap(); 1102a17651b1SMemoryShore let old_entry = old_table.entry(entry_index).unwrap(); 1103a17651b1SMemoryShore let entry = PageEntry::new(table.phys(), old_entry.flags()); 1104a17651b1SMemoryShore new_table.set_entry(entry_index, entry); 1105a17651b1SMemoryShore } 1106a17651b1SMemoryShore } 1107a17651b1SMemoryShore } 1108a17651b1SMemoryShore 110940fe15e0SLoGin /// 将物理地址映射到具有线性偏移量的虚拟地址 111040fe15e0SLoGin #[allow(dead_code)] 111140fe15e0SLoGin pub unsafe fn map_linearly( 111240fe15e0SLoGin &mut self, 111340fe15e0SLoGin phys: PhysAddr, 111440fe15e0SLoGin flags: PageFlags<Arch>, 111540fe15e0SLoGin ) -> Option<(VirtAddr, PageFlush<Arch>)> { 111640fe15e0SLoGin let virt: VirtAddr = Arch::phys_2_virt(phys)?; 111740fe15e0SLoGin return self.map_phys(virt, phys, flags).map(|flush| (virt, flush)); 111840fe15e0SLoGin } 111940fe15e0SLoGin 112040fe15e0SLoGin /// 修改虚拟地址的页表项的flags,并返回页表项刷新器 112140fe15e0SLoGin /// 112240fe15e0SLoGin /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效 112340fe15e0SLoGin /// 112440fe15e0SLoGin /// ## 参数 112540fe15e0SLoGin /// - virt 虚拟地址 112640fe15e0SLoGin /// - flags 新的页表项的flags 112740fe15e0SLoGin /// 112840fe15e0SLoGin /// ## 返回值 112940fe15e0SLoGin /// 113040fe15e0SLoGin /// 如果修改成功,返回刷新器,否则返回None 113140fe15e0SLoGin pub unsafe fn remap( 113240fe15e0SLoGin &mut self, 113340fe15e0SLoGin virt: VirtAddr, 113440fe15e0SLoGin flags: PageFlags<Arch>, 113540fe15e0SLoGin ) -> Option<PageFlush<Arch>> { 113640fe15e0SLoGin return self 113740fe15e0SLoGin .visit(virt, |p1, i| { 113840fe15e0SLoGin let mut entry = p1.entry(i)?; 1139731bc2b3SLoGin 114040fe15e0SLoGin entry.set_flags(flags); 114140fe15e0SLoGin p1.set_entry(i, entry); 114240fe15e0SLoGin Some(PageFlush::new(virt)) 114340fe15e0SLoGin }) 114440fe15e0SLoGin .flatten(); 114540fe15e0SLoGin } 114640fe15e0SLoGin 114740fe15e0SLoGin /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags 114840fe15e0SLoGin /// 114940fe15e0SLoGin /// ## 参数 115040fe15e0SLoGin /// 115140fe15e0SLoGin /// - virt 虚拟地址 115240fe15e0SLoGin /// 115340fe15e0SLoGin /// ## 返回值 115440fe15e0SLoGin /// 115540fe15e0SLoGin /// 如果查找成功,返回物理地址和页表项的flags,否则返回None 115640fe15e0SLoGin pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, PageFlags<Arch>)> { 115740fe15e0SLoGin let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??; 115840fe15e0SLoGin let paddr = entry.address().ok()?; 115940fe15e0SLoGin let flags = entry.flags(); 116040fe15e0SLoGin return Some((paddr, flags)); 116140fe15e0SLoGin } 116240fe15e0SLoGin 116340fe15e0SLoGin /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器 116440fe15e0SLoGin /// 116540fe15e0SLoGin /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效 116640fe15e0SLoGin /// 116740fe15e0SLoGin /// ## 参数 116840fe15e0SLoGin /// 116940fe15e0SLoGin /// - virt 虚拟地址 117040fe15e0SLoGin /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 117140fe15e0SLoGin /// 117240fe15e0SLoGin /// ## 返回值 117340fe15e0SLoGin /// 如果取消成功,返回刷新器,否则返回None 11742dd9f0c7SLoGin #[allow(dead_code)] 117540fe15e0SLoGin pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> { 117640fe15e0SLoGin let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?; 117740fe15e0SLoGin self.frame_allocator.free_one(paddr); 117840fe15e0SLoGin return Some(flusher); 117940fe15e0SLoGin } 118040fe15e0SLoGin 118140fe15e0SLoGin /// 取消虚拟地址的映射,并返回物理地址和页表项的flags 118240fe15e0SLoGin /// 118340fe15e0SLoGin /// ## 参数 118440fe15e0SLoGin /// 118540fe15e0SLoGin /// - vaddr 虚拟地址 118640fe15e0SLoGin /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 118740fe15e0SLoGin /// 118840fe15e0SLoGin /// ## 返回值 118940fe15e0SLoGin /// 119040fe15e0SLoGin /// 如果取消成功,返回物理地址和页表项的flags,否则返回None 119140fe15e0SLoGin pub unsafe fn unmap_phys( 119240fe15e0SLoGin &mut self, 119340fe15e0SLoGin virt: VirtAddr, 119440fe15e0SLoGin unmap_parents: bool, 119540fe15e0SLoGin ) -> Option<(PhysAddr, PageFlags<Arch>, PageFlush<Arch>)> { 119640fe15e0SLoGin if !virt.check_aligned(Arch::PAGE_SIZE) { 11972eab6dd7S曾俊 error!("Try to unmap unaligned page: virt={:?}", virt); 119840fe15e0SLoGin return None; 119940fe15e0SLoGin } 120040fe15e0SLoGin 1201b5b571e0SLoGin let table = self.table(); 1202b5b571e0SLoGin return unmap_phys_inner(virt, &table, unmap_parents, self.allocator_mut()) 120340fe15e0SLoGin .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt))); 120440fe15e0SLoGin } 120540fe15e0SLoGin 120640fe15e0SLoGin /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F 120740fe15e0SLoGin fn visit<T>( 120840fe15e0SLoGin &self, 120940fe15e0SLoGin virt: VirtAddr, 121040fe15e0SLoGin f: impl FnOnce(&mut PageTable<Arch>, usize) -> T, 121140fe15e0SLoGin ) -> Option<T> { 121240fe15e0SLoGin let mut table = self.table(); 121340fe15e0SLoGin unsafe { 121440fe15e0SLoGin loop { 121540fe15e0SLoGin let i = table.index_of(virt)?; 121640fe15e0SLoGin if table.level() == 0 { 121740fe15e0SLoGin return Some(f(&mut table, i)); 121840fe15e0SLoGin } else { 121940fe15e0SLoGin table = table.next_level_table(i)?; 122040fe15e0SLoGin } 122140fe15e0SLoGin } 122240fe15e0SLoGin } 122340fe15e0SLoGin } 122440fe15e0SLoGin } 122540fe15e0SLoGin 122640fe15e0SLoGin /// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】 122740fe15e0SLoGin /// 122840fe15e0SLoGin /// ## 参数 122940fe15e0SLoGin /// 123040fe15e0SLoGin /// - vaddr 虚拟地址 123140fe15e0SLoGin /// - table 页表 123240fe15e0SLoGin /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 123340fe15e0SLoGin /// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内) 123440fe15e0SLoGin /// 123540fe15e0SLoGin /// ## 返回值 123640fe15e0SLoGin /// 123740fe15e0SLoGin /// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None 123840fe15e0SLoGin unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>( 123940fe15e0SLoGin vaddr: VirtAddr, 1240840045afSLoGin table: &PageTable<Arch>, 124140fe15e0SLoGin unmap_parents: bool, 124240fe15e0SLoGin allocator: &mut impl FrameAllocator, 124340fe15e0SLoGin ) -> Option<(PhysAddr, PageFlags<Arch>)> { 124440fe15e0SLoGin // 获取页表项的索引 124540fe15e0SLoGin let i = table.index_of(vaddr)?; 124640fe15e0SLoGin 124740fe15e0SLoGin // 如果当前是最后一级页表,直接取消页面映射 124840fe15e0SLoGin if table.level() == 0 { 124940fe15e0SLoGin let entry = table.entry(i)?; 12507a29d4fcSLoGin table.set_entry(i, PageEntry::from_usize(0)); 125140fe15e0SLoGin return Some((entry.address().ok()?, entry.flags())); 125240fe15e0SLoGin } 125340fe15e0SLoGin 1254b5b571e0SLoGin let subtable = table.next_level_table(i)?; 125540fe15e0SLoGin // 递归地取消映射 1256b5b571e0SLoGin let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator)?; 125740fe15e0SLoGin 125840fe15e0SLoGin // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables, 125940fe15e0SLoGin // as these mappings may become out of sync 126040fe15e0SLoGin if unmap_parents { 126140fe15e0SLoGin // 如果子页表已经没有映射的页面了,就取消子页表的映射 126240fe15e0SLoGin 126340fe15e0SLoGin // 检查子页表中是否还有映射的页面 126440fe15e0SLoGin let x = (0..Arch::PAGE_ENTRY_NUM) 126540fe15e0SLoGin .map(|k| subtable.entry(k).expect("invalid page entry")) 126640fe15e0SLoGin .any(|e| e.present()); 126740fe15e0SLoGin if !x { 126840fe15e0SLoGin // 如果没有,就取消子页表的映射 12697a29d4fcSLoGin table.set_entry(i, PageEntry::from_usize(0)); 127040fe15e0SLoGin // 释放子页表 127140fe15e0SLoGin allocator.free_one(subtable.phys()); 127240fe15e0SLoGin } 127340fe15e0SLoGin } 127440fe15e0SLoGin 127540fe15e0SLoGin return Some(result); 127640fe15e0SLoGin } 127740fe15e0SLoGin 127840fe15e0SLoGin impl<Arch, F: Debug> Debug for PageMapper<Arch, F> { 127940fe15e0SLoGin fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 128040fe15e0SLoGin f.debug_struct("PageMapper") 128140fe15e0SLoGin .field("table_paddr", &self.table_paddr) 128240fe15e0SLoGin .field("frame_allocator", &self.frame_allocator) 128340fe15e0SLoGin .finish() 128440fe15e0SLoGin } 128540fe15e0SLoGin } 128640fe15e0SLoGin 128740fe15e0SLoGin /// 页表刷新器的trait 12887ae679ddSLoGin pub trait Flusher<Arch: MemoryManagementArch> { 128940fe15e0SLoGin /// 取消对指定的page flusher的刷新 129040fe15e0SLoGin fn consume(&mut self, flush: PageFlush<Arch>); 129140fe15e0SLoGin } 129240fe15e0SLoGin 129340fe15e0SLoGin /// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法, 129440fe15e0SLoGin /// 否则会造成对页表的更改被忽略,这是不安全的 129540fe15e0SLoGin #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 12967ae679ddSLoGin pub struct PageFlush<Arch: MemoryManagementArch> { 129740fe15e0SLoGin virt: VirtAddr, 129840fe15e0SLoGin phantom: PhantomData<Arch>, 129940fe15e0SLoGin } 130040fe15e0SLoGin 130140fe15e0SLoGin impl<Arch: MemoryManagementArch> PageFlush<Arch> { 130240fe15e0SLoGin pub fn new(virt: VirtAddr) -> Self { 130340fe15e0SLoGin return Self { 130440fe15e0SLoGin virt, 130540fe15e0SLoGin phantom: PhantomData, 130640fe15e0SLoGin }; 130740fe15e0SLoGin } 130840fe15e0SLoGin 130940fe15e0SLoGin pub fn flush(self) { 131040fe15e0SLoGin unsafe { Arch::invalidate_page(self.virt) }; 131140fe15e0SLoGin } 131240fe15e0SLoGin 131340fe15e0SLoGin /// 忽略掉这个刷新器 131440fe15e0SLoGin pub unsafe fn ignore(self) { 131540fe15e0SLoGin mem::forget(self); 131640fe15e0SLoGin } 131740fe15e0SLoGin } 131840fe15e0SLoGin 13197ae679ddSLoGin impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> { 13207ae679ddSLoGin fn drop(&mut self) { 13217ae679ddSLoGin unsafe { 13227ae679ddSLoGin MMArch::invalidate_page(self.virt); 13237ae679ddSLoGin } 13247ae679ddSLoGin } 13257ae679ddSLoGin } 13267ae679ddSLoGin 132740fe15e0SLoGin /// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法, 132840fe15e0SLoGin /// 否则会造成对页表的更改被忽略,这是不安全的 132940fe15e0SLoGin #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 133040fe15e0SLoGin pub struct PageFlushAll<Arch: MemoryManagementArch> { 133140fe15e0SLoGin phantom: PhantomData<fn() -> Arch>, 133240fe15e0SLoGin } 133340fe15e0SLoGin 133440fe15e0SLoGin #[allow(dead_code)] 133540fe15e0SLoGin impl<Arch: MemoryManagementArch> PageFlushAll<Arch> { 133640fe15e0SLoGin pub fn new() -> Self { 133740fe15e0SLoGin return Self { 133840fe15e0SLoGin phantom: PhantomData, 133940fe15e0SLoGin }; 134040fe15e0SLoGin } 134140fe15e0SLoGin 134240fe15e0SLoGin pub fn flush(self) { 134340fe15e0SLoGin unsafe { Arch::invalidate_all() }; 134440fe15e0SLoGin } 134540fe15e0SLoGin 134640fe15e0SLoGin /// 忽略掉这个刷新器 134740fe15e0SLoGin pub unsafe fn ignore(self) { 134840fe15e0SLoGin mem::forget(self); 134940fe15e0SLoGin } 135040fe15e0SLoGin } 135140fe15e0SLoGin 135240fe15e0SLoGin impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> { 135340fe15e0SLoGin /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了) 135440fe15e0SLoGin fn consume(&mut self, flush: PageFlush<Arch>) { 135540fe15e0SLoGin unsafe { flush.ignore() }; 135640fe15e0SLoGin } 135740fe15e0SLoGin } 135840fe15e0SLoGin 135940fe15e0SLoGin impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T { 136040fe15e0SLoGin /// 允许一个flusher consume掉另一个flusher 136140fe15e0SLoGin fn consume(&mut self, flush: PageFlush<Arch>) { 136240fe15e0SLoGin <T as Flusher<Arch>>::consume(self, flush); 136340fe15e0SLoGin } 136440fe15e0SLoGin } 136540fe15e0SLoGin 136640fe15e0SLoGin impl<Arch: MemoryManagementArch> Flusher<Arch> for () { 136740fe15e0SLoGin fn consume(&mut self, _flush: PageFlush<Arch>) {} 136840fe15e0SLoGin } 136940fe15e0SLoGin 137040fe15e0SLoGin impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> { 137140fe15e0SLoGin fn drop(&mut self) { 137240fe15e0SLoGin unsafe { 137340fe15e0SLoGin Arch::invalidate_all(); 137440fe15e0SLoGin } 137540fe15e0SLoGin } 137640fe15e0SLoGin } 137740fe15e0SLoGin 137840fe15e0SLoGin /// 未在当前CPU上激活的页表的刷新器 137940fe15e0SLoGin /// 138040fe15e0SLoGin /// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表 138140fe15e0SLoGin /// 138240fe15e0SLoGin /// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销) 138340fe15e0SLoGin #[derive(Debug)] 138440fe15e0SLoGin pub struct InactiveFlusher; 138540fe15e0SLoGin 138640fe15e0SLoGin impl InactiveFlusher { 138740fe15e0SLoGin pub fn new() -> Self { 138840fe15e0SLoGin return Self {}; 138940fe15e0SLoGin } 139040fe15e0SLoGin } 139140fe15e0SLoGin 139240fe15e0SLoGin impl Flusher<MMArch> for InactiveFlusher { 139340fe15e0SLoGin fn consume(&mut self, flush: PageFlush<MMArch>) { 139440fe15e0SLoGin unsafe { 139540fe15e0SLoGin flush.ignore(); 139640fe15e0SLoGin } 139740fe15e0SLoGin } 139840fe15e0SLoGin } 139940fe15e0SLoGin 140040fe15e0SLoGin impl Drop for InactiveFlusher { 140140fe15e0SLoGin fn drop(&mut self) { 140240fe15e0SLoGin // 发送刷新页表的IPI 140340fe15e0SLoGin send_ipi(IpiKind::FlushTLB, IpiTarget::Other); 140440fe15e0SLoGin } 140540fe15e0SLoGin } 140640fe15e0SLoGin 140740fe15e0SLoGin /// # 把一个地址向下对齐到页大小 140840fe15e0SLoGin pub fn round_down_to_page_size(addr: usize) -> usize { 140940fe15e0SLoGin addr & !(MMArch::PAGE_SIZE - 1) 141040fe15e0SLoGin } 141140fe15e0SLoGin 141240fe15e0SLoGin /// # 把一个地址向上对齐到页大小 141340fe15e0SLoGin pub fn round_up_to_page_size(addr: usize) -> usize { 141440fe15e0SLoGin round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1) 141540fe15e0SLoGin } 1416