1 use alloc::string::ToString; 2 use core::{ 3 fmt::{self, Debug, Error, Formatter}, 4 marker::PhantomData, 5 mem, 6 ops::Add, 7 sync::atomic::{compiler_fence, Ordering}, 8 }; 9 use system_error::SystemError; 10 use unified_init::macros::unified_init; 11 12 use alloc::sync::Arc; 13 use hashbrown::{HashMap, HashSet}; 14 use log::{error, info}; 15 use lru::LruCache; 16 17 use crate::{ 18 arch::{interrupt::ipi::send_ipi, mm::LockedFrameAllocator, MMArch}, 19 exception::ipi::{IpiKind, IpiTarget}, 20 filesystem::vfs::{file::PageCache, FilePrivateData}, 21 init::initcall::INITCALL_CORE, 22 ipc::shm::ShmId, 23 libs::{ 24 rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}, 25 spinlock::{SpinLock, SpinLockGuard}, 26 }, 27 process::{ProcessControlBlock, ProcessManager}, 28 time::{sleep::nanosleep, PosixTimeSpec}, 29 }; 30 31 use super::{ 32 allocator::page_frame::{FrameAllocator, PageFrameCount}, 33 syscall::ProtFlags, 34 ucontext::LockedVMA, 35 MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr, 36 }; 37 38 pub const PAGE_4K_SHIFT: usize = 12; 39 #[allow(dead_code)] 40 pub const PAGE_2M_SHIFT: usize = 21; 41 pub const PAGE_1G_SHIFT: usize = 30; 42 43 pub const PAGE_4K_SIZE: usize = 1 << PAGE_4K_SHIFT; 44 pub const PAGE_2M_SIZE: usize = 1 << PAGE_2M_SHIFT; 45 46 /// 全局物理页信息管理器 47 pub static mut PAGE_MANAGER: Option<SpinLock<PageManager>> = None; 48 49 /// 初始化PAGE_MANAGER 50 pub fn page_manager_init() { 51 info!("page_manager_init"); 52 let page_manager = SpinLock::new(PageManager::new()); 53 54 compiler_fence(Ordering::SeqCst); 55 unsafe { PAGE_MANAGER = Some(page_manager) }; 56 compiler_fence(Ordering::SeqCst); 57 58 info!("page_manager_init done"); 59 } 60 61 pub fn page_manager_lock_irqsave() -> SpinLockGuard<'static, PageManager> { 62 unsafe { PAGE_MANAGER.as_ref().unwrap().lock_irqsave() } 63 } 64 65 // 物理页管理器 66 pub struct PageManager { 67 phys2page: HashMap<PhysAddr, Arc<Page>>, 68 } 69 70 impl PageManager { 71 pub fn new() -> Self { 72 Self { 73 phys2page: HashMap::new(), 74 } 75 } 76 77 pub fn contains(&self, paddr: &PhysAddr) -> bool { 78 self.phys2page.contains_key(paddr) 79 } 80 81 pub fn get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> { 82 page_reclaimer_lock_irqsave().get(paddr); 83 self.phys2page.get(paddr).cloned() 84 } 85 86 pub fn get_unwrap(&mut self, paddr: &PhysAddr) -> Arc<Page> { 87 page_reclaimer_lock_irqsave().get(paddr); 88 self.phys2page 89 .get(paddr) 90 .unwrap_or_else(|| panic!("Phys Page not found, {:?}", paddr)) 91 .clone() 92 } 93 94 pub fn insert(&mut self, paddr: PhysAddr, page: &Arc<Page>) { 95 self.phys2page.insert(paddr, page.clone()); 96 } 97 98 pub fn remove_page(&mut self, paddr: &PhysAddr) { 99 self.phys2page.remove(paddr); 100 } 101 } 102 103 pub static mut PAGE_RECLAIMER: Option<SpinLock<PageReclaimer>> = None; 104 105 pub fn page_reclaimer_init() { 106 info!("page_reclaimer_init"); 107 let page_reclaimer = SpinLock::new(PageReclaimer::new()); 108 109 compiler_fence(Ordering::SeqCst); 110 unsafe { PAGE_RECLAIMER = Some(page_reclaimer) }; 111 compiler_fence(Ordering::SeqCst); 112 113 info!("page_reclaimer_init done"); 114 } 115 116 /// 页面回收线程 117 static mut PAGE_RECLAIMER_THREAD: Option<Arc<ProcessControlBlock>> = None; 118 119 /// 页面回收线程初始化函数 120 #[unified_init(INITCALL_CORE)] 121 fn page_reclaimer_thread_init() -> Result<(), SystemError> { 122 let closure = crate::process::kthread::KernelThreadClosure::StaticEmptyClosure(( 123 &(page_reclaim_thread as fn() -> i32), 124 (), 125 )); 126 let pcb = crate::process::kthread::KernelThreadMechanism::create_and_run( 127 closure, 128 "page_reclaim".to_string(), 129 ) 130 .ok_or("") 131 .expect("create tty_refresh thread failed"); 132 unsafe { 133 PAGE_RECLAIMER_THREAD = Some(pcb); 134 } 135 Ok(()) 136 } 137 138 /// 页面回收线程执行的函数 139 fn page_reclaim_thread() -> i32 { 140 loop { 141 let usage = unsafe { LockedFrameAllocator.usage() }; 142 // log::info!("usage{:?}", usage); 143 144 // 保留4096个页面,总计16MB的空闲空间 145 if usage.free().data() < 4096 { 146 let page_to_free = 4096; 147 page_reclaimer_lock_irqsave().shrink_list(PageFrameCount::new(page_to_free)); 148 } else { 149 //TODO 暂时让页面回收线程负责脏页回写任务,后续需要分离 150 page_reclaimer_lock_irqsave().flush_dirty_pages(); 151 // 休眠5秒 152 // log::info!("sleep"); 153 let _ = nanosleep(PosixTimeSpec::new(5, 0)); 154 } 155 } 156 } 157 158 /// 获取页面回收器 159 pub fn page_reclaimer_lock_irqsave() -> SpinLockGuard<'static, PageReclaimer> { 160 unsafe { PAGE_RECLAIMER.as_ref().unwrap().lock_irqsave() } 161 } 162 163 /// 页面回收器 164 pub struct PageReclaimer { 165 lru: LruCache<PhysAddr, Arc<Page>>, 166 } 167 168 impl PageReclaimer { 169 pub fn new() -> Self { 170 Self { 171 lru: LruCache::unbounded(), 172 } 173 } 174 175 pub fn get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> { 176 self.lru.get(paddr).cloned() 177 } 178 179 pub fn insert_page(&mut self, paddr: PhysAddr, page: &Arc<Page>) { 180 self.lru.put(paddr, page.clone()); 181 } 182 183 /// lru链表缩减 184 /// ## 参数 185 /// 186 /// - `count`: 需要缩减的页面数量 187 pub fn shrink_list(&mut self, count: PageFrameCount) { 188 for _ in 0..count.data() { 189 let (paddr, page) = self.lru.pop_lru().expect("pagecache is empty"); 190 let page_cache = page.read_irqsave().page_cache().unwrap(); 191 for vma in page.read_irqsave().anon_vma() { 192 let address_space = vma.lock_irqsave().address_space().unwrap(); 193 let address_space = address_space.upgrade().unwrap(); 194 let mut guard = address_space.write(); 195 let mapper = &mut guard.user_mapper.utable; 196 let virt = vma.lock_irqsave().page_address(&page).unwrap(); 197 unsafe { 198 mapper.unmap(virt, false).unwrap().flush(); 199 } 200 } 201 page_cache.remove_page(page.read_irqsave().index().unwrap()); 202 page_manager_lock_irqsave().remove_page(&paddr); 203 if page.read_irqsave().flags.contains(PageFlags::PG_DIRTY) { 204 Self::page_writeback(&page, true); 205 } 206 } 207 } 208 209 /// 唤醒页面回收线程 210 pub fn wakeup_claim_thread() { 211 // log::info!("wakeup_claim_thread"); 212 let _ = ProcessManager::wakeup(unsafe { PAGE_RECLAIMER_THREAD.as_ref().unwrap() }); 213 } 214 215 /// 脏页回写函数 216 /// ## 参数 217 /// 218 /// - `page`: 需要回写的脏页 219 /// - `unmap`: 是否取消映射 220 /// 221 /// ## 返回值 222 /// - VmFaultReason: 页面错误处理信息标志 223 pub fn page_writeback(page: &Arc<Page>, unmap: bool) { 224 if !unmap { 225 page.write_irqsave().remove_flags(PageFlags::PG_DIRTY); 226 } 227 228 for vma in page.read_irqsave().anon_vma() { 229 let address_space = vma.lock_irqsave().address_space().unwrap(); 230 let address_space = address_space.upgrade().unwrap(); 231 let mut guard = address_space.write(); 232 let mapper = &mut guard.user_mapper.utable; 233 let virt = vma.lock_irqsave().page_address(page).unwrap(); 234 if unmap { 235 unsafe { 236 mapper.unmap(virt, false).unwrap().flush(); 237 } 238 } else { 239 unsafe { 240 // 保护位设为只读 241 mapper.remap( 242 virt, 243 mapper.get_entry(virt, 0).unwrap().flags().set_write(false), 244 ) 245 }; 246 } 247 } 248 let inode = page 249 .read_irqsave() 250 .page_cache 251 .clone() 252 .unwrap() 253 .inode() 254 .clone() 255 .unwrap() 256 .upgrade() 257 .unwrap(); 258 inode 259 .write_at( 260 page.read_irqsave().index().unwrap(), 261 MMArch::PAGE_SIZE, 262 unsafe { 263 core::slice::from_raw_parts( 264 MMArch::phys_2_virt(page.read_irqsave().phys_addr) 265 .unwrap() 266 .data() as *mut u8, 267 MMArch::PAGE_SIZE, 268 ) 269 }, 270 SpinLock::new(FilePrivateData::Unused).lock(), 271 ) 272 .unwrap(); 273 } 274 275 /// lru脏页刷新 276 pub fn flush_dirty_pages(&self) { 277 // log::info!("flush_dirty_pages"); 278 let iter = self.lru.iter(); 279 for (_, page) in iter { 280 if page.read_irqsave().flags().contains(PageFlags::PG_DIRTY) { 281 Self::page_writeback(page, false); 282 } 283 } 284 } 285 } 286 287 bitflags! { 288 pub struct PageFlags: u64 { 289 const PG_LOCKED = 1 << 0; 290 const PG_WRITEBACK = 1 << 1; 291 const PG_REFERENCED = 1 << 2; 292 const PG_UPTODATE = 1 << 3; 293 const PG_DIRTY = 1 << 4; 294 const PG_LRU = 1 << 5; 295 const PG_HEAD = 1 << 6; 296 const PG_WAITERS = 1 << 7; 297 const PG_ACTIVE = 1 << 8; 298 const PG_WORKINGSET = 1 << 9; 299 const PG_ERROR = 1 << 10; 300 const PG_SLAB = 1 << 11; 301 const PG_RESERVED = 1 << 14; 302 const PG_PRIVATE = 1 << 15; 303 const PG_RECLAIM = 1 << 18; 304 const PG_SWAPBACKED = 1 << 19; 305 } 306 } 307 308 #[derive(Debug)] 309 pub struct Page { 310 inner: RwLock<InnerPage>, 311 } 312 313 impl Page { 314 pub fn new(shared: bool, phys_addr: PhysAddr) -> Self { 315 let inner = InnerPage::new(shared, phys_addr); 316 Self { 317 inner: RwLock::new(inner), 318 } 319 } 320 321 pub fn read_irqsave(&self) -> RwLockReadGuard<InnerPage> { 322 self.inner.read_irqsave() 323 } 324 325 pub fn write_irqsave(&self) -> RwLockWriteGuard<InnerPage> { 326 self.inner.write_irqsave() 327 } 328 } 329 330 #[derive(Debug)] 331 /// 物理页面信息 332 pub struct InnerPage { 333 /// 映射计数 334 map_count: usize, 335 /// 是否为共享页 336 shared: bool, 337 /// 映射计数为0时,是否可回收 338 free_when_zero: bool, 339 /// 共享页id(如果是共享页) 340 shm_id: Option<ShmId>, 341 /// 映射到当前page的VMA 342 anon_vma: HashSet<Arc<LockedVMA>>, 343 /// 标志 344 flags: PageFlags, 345 /// 页所在的物理页帧号 346 phys_addr: PhysAddr, 347 /// 在pagecache中的偏移 348 index: Option<usize>, 349 page_cache: Option<Arc<PageCache>>, 350 } 351 352 impl InnerPage { 353 pub fn new(shared: bool, phys_addr: PhysAddr) -> Self { 354 let dealloc_when_zero = !shared; 355 Self { 356 map_count: 0, 357 shared, 358 free_when_zero: dealloc_when_zero, 359 shm_id: None, 360 anon_vma: HashSet::new(), 361 flags: PageFlags::empty(), 362 phys_addr, 363 index: None, 364 page_cache: None, 365 } 366 } 367 368 /// 将vma加入anon_vma 369 pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) { 370 self.anon_vma.insert(vma); 371 self.map_count += 1; 372 } 373 374 /// 将vma从anon_vma中删去 375 pub fn remove_vma(&mut self, vma: &LockedVMA) { 376 self.anon_vma.remove(vma); 377 self.map_count -= 1; 378 } 379 380 /// 判断当前物理页是否能被回 381 pub fn can_deallocate(&self) -> bool { 382 self.map_count == 0 && self.free_when_zero 383 } 384 385 pub fn shared(&self) -> bool { 386 self.shared 387 } 388 389 pub fn shm_id(&self) -> Option<ShmId> { 390 self.shm_id 391 } 392 393 pub fn index(&self) -> Option<usize> { 394 self.index 395 } 396 397 pub fn page_cache(&self) -> Option<Arc<PageCache>> { 398 self.page_cache.clone() 399 } 400 401 pub fn set_page_cache(&mut self, page_cache: Option<Arc<PageCache>>) { 402 self.page_cache = page_cache; 403 } 404 405 pub fn set_index(&mut self, index: Option<usize>) { 406 self.index = index; 407 } 408 409 pub fn set_page_cache_index( 410 &mut self, 411 page_cache: Option<Arc<PageCache>>, 412 index: Option<usize>, 413 ) { 414 self.page_cache = page_cache; 415 self.index = index; 416 } 417 418 pub fn set_shm_id(&mut self, shm_id: ShmId) { 419 self.shm_id = Some(shm_id); 420 } 421 422 pub fn set_dealloc_when_zero(&mut self, dealloc_when_zero: bool) { 423 self.free_when_zero = dealloc_when_zero; 424 } 425 426 #[inline(always)] 427 pub fn anon_vma(&self) -> &HashSet<Arc<LockedVMA>> { 428 &self.anon_vma 429 } 430 431 #[inline(always)] 432 pub fn map_count(&self) -> usize { 433 self.map_count 434 } 435 436 #[inline(always)] 437 pub fn flags(&self) -> &PageFlags { 438 &self.flags 439 } 440 441 #[inline(always)] 442 pub fn set_flags(&mut self, flags: PageFlags) { 443 self.flags = flags 444 } 445 446 #[inline(always)] 447 pub fn add_flags(&mut self, flags: PageFlags) { 448 self.flags = self.flags.union(flags); 449 } 450 451 #[inline(always)] 452 pub fn remove_flags(&mut self, flags: PageFlags) { 453 self.flags = self.flags.difference(flags); 454 } 455 456 #[inline(always)] 457 pub fn phys_address(&self) -> PhysAddr { 458 self.phys_addr 459 } 460 } 461 462 #[derive(Debug)] 463 pub struct PageTable<Arch> { 464 /// 当前页表表示的虚拟地址空间的起始地址 465 base: VirtAddr, 466 /// 当前页表所在的物理地址 467 phys: PhysAddr, 468 /// 当前页表的层级(请注意,最顶级页表的level为[Arch::PAGE_LEVELS - 1]) 469 level: usize, 470 phantom: PhantomData<Arch>, 471 } 472 473 #[allow(dead_code)] 474 impl<Arch: MemoryManagementArch> PageTable<Arch> { 475 pub unsafe fn new(base: VirtAddr, phys: PhysAddr, level: usize) -> Self { 476 Self { 477 base, 478 phys, 479 level, 480 phantom: PhantomData, 481 } 482 } 483 484 /// 获取顶级页表 485 /// 486 /// ## 参数 487 /// 488 /// - table_kind 页表类型 489 /// 490 /// ## 返回值 491 /// 492 /// 返回顶级页表 493 pub unsafe fn top_level_table(table_kind: PageTableKind) -> Self { 494 return Self::new( 495 VirtAddr::new(0), 496 Arch::table(table_kind), 497 Arch::PAGE_LEVELS - 1, 498 ); 499 } 500 501 /// 获取当前页表的物理地址 502 #[inline(always)] 503 pub fn phys(&self) -> PhysAddr { 504 self.phys 505 } 506 507 /// 当前页表表示的虚拟地址空间的起始地址 508 #[inline(always)] 509 pub fn base(&self) -> VirtAddr { 510 self.base 511 } 512 513 /// 获取当前页表的层级 514 #[inline(always)] 515 pub fn level(&self) -> usize { 516 self.level 517 } 518 519 /// 获取当前页表自身所在的虚拟地址 520 #[inline(always)] 521 pub unsafe fn virt(&self) -> VirtAddr { 522 return Arch::phys_2_virt(self.phys).unwrap(); 523 } 524 525 /// 获取第i个页表项所表示的虚拟内存空间的起始地址 526 pub fn entry_base(&self, i: usize) -> Option<VirtAddr> { 527 if i < Arch::PAGE_ENTRY_NUM { 528 let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT; 529 return Some(self.base.add(i << shift)); 530 } else { 531 return None; 532 } 533 } 534 535 /// 获取当前页表的第i个页表项所在的虚拟地址(注意与entry_base进行区分) 536 pub unsafe fn entry_virt(&self, i: usize) -> Option<VirtAddr> { 537 if i < Arch::PAGE_ENTRY_NUM { 538 return Some(self.virt().add(i * Arch::PAGE_ENTRY_SIZE)); 539 } else { 540 return None; 541 } 542 } 543 544 /// 获取当前页表的第i个页表项 545 pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> { 546 let entry_virt = self.entry_virt(i)?; 547 return Some(PageEntry::from_usize(Arch::read::<usize>(entry_virt))); 548 } 549 550 /// 设置当前页表的第i个页表项 551 pub unsafe fn set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()> { 552 let entry_virt = self.entry_virt(i)?; 553 Arch::write::<usize>(entry_virt, entry.data()); 554 return Some(()); 555 } 556 557 /// 判断当前页表的第i个页表项是否已经填写了值 558 /// 559 /// ## 参数 560 /// - Some(true) 如果已经填写了值 561 /// - Some(false) 如果未填写值 562 /// - None 如果i超出了页表项的范围 563 pub fn entry_mapped(&self, i: usize) -> Option<bool> { 564 let etv = unsafe { self.entry_virt(i) }?; 565 if unsafe { Arch::read::<usize>(etv) } != 0 { 566 return Some(true); 567 } else { 568 return Some(false); 569 } 570 } 571 572 /// 根据虚拟地址,获取对应的页表项在页表中的下标 573 /// 574 /// ## 参数 575 /// 576 /// - addr: 虚拟地址 577 /// 578 /// ## 返回值 579 /// 580 /// 页表项在页表中的下标。如果addr不在当前页表所表示的虚拟地址空间中,则返回None 581 pub fn index_of(&self, addr: VirtAddr) -> Option<usize> { 582 let addr = VirtAddr::new(addr.data() & Arch::PAGE_ADDRESS_MASK); 583 let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT; 584 585 let mask = (MMArch::PAGE_ENTRY_NUM << shift) - 1; 586 if addr < self.base || addr >= self.base.add(mask) { 587 return None; 588 } else { 589 return Some((addr.data() >> shift) & MMArch::PAGE_ENTRY_MASK); 590 } 591 } 592 593 /// 获取第i个页表项指向的下一级页表 594 pub unsafe fn next_level_table(&self, index: usize) -> Option<Self> { 595 if self.level == 0 { 596 return None; 597 } 598 599 // 返回下一级页表 600 return Some(PageTable::new( 601 self.entry_base(index)?, 602 self.entry(index)?.address().ok()?, 603 self.level - 1, 604 )); 605 } 606 607 /// 拷贝页表 608 /// ## 参数 609 /// 610 /// - `allocator`: 物理页框分配器 611 /// - `copy_on_write`: 是否写时复制 612 pub unsafe fn clone( 613 &self, 614 allocator: &mut impl FrameAllocator, 615 copy_on_write: bool, 616 ) -> Option<PageTable<Arch>> { 617 // 分配新页面作为新的页表 618 let phys = allocator.allocate_one()?; 619 let frame = MMArch::phys_2_virt(phys).unwrap(); 620 MMArch::write_bytes(frame, 0, MMArch::PAGE_SIZE); 621 let new_table = PageTable::new(self.base, phys, self.level); 622 if self.level == 0 { 623 for i in 0..Arch::PAGE_ENTRY_NUM { 624 if let Some(mut entry) = self.entry(i) { 625 if entry.present() { 626 if copy_on_write { 627 let mut new_flags = entry.flags().set_write(false); 628 entry.set_flags(new_flags); 629 self.set_entry(i, entry); 630 new_flags = new_flags.set_dirty(false); 631 entry.set_flags(new_flags); 632 new_table.set_entry(i, entry); 633 } else { 634 let phys = allocator.allocate_one()?; 635 let mut page_manager_guard = page_manager_lock_irqsave(); 636 let old_phys = entry.address().unwrap(); 637 let old_page = page_manager_guard.get_unwrap(&old_phys); 638 let new_page = 639 Arc::new(Page::new(old_page.read_irqsave().shared(), phys)); 640 if let Some(ref page_cache) = old_page.read_irqsave().page_cache() { 641 new_page.write_irqsave().set_page_cache_index( 642 Some(page_cache.clone()), 643 old_page.read_irqsave().index(), 644 ); 645 } 646 647 page_manager_guard.insert(phys, &new_page); 648 let old_phys = entry.address().unwrap(); 649 let frame = MMArch::phys_2_virt(phys).unwrap().data() as *mut u8; 650 frame.copy_from_nonoverlapping( 651 MMArch::phys_2_virt(old_phys).unwrap().data() as *mut u8, 652 MMArch::PAGE_SIZE, 653 ); 654 new_table.set_entry(i, PageEntry::new(phys, entry.flags())); 655 } 656 } 657 } 658 } 659 } else { 660 // 非一级页表拷贝时,对每个页表项对应的页表都进行拷贝 661 for i in 0..MMArch::PAGE_ENTRY_NUM { 662 if let Some(next_table) = self.next_level_table(i) { 663 let table = next_table.clone(allocator, copy_on_write)?; 664 let old_entry = self.entry(i).unwrap(); 665 let entry = PageEntry::new(table.phys(), old_entry.flags()); 666 new_table.set_entry(i, entry); 667 } 668 } 669 } 670 Some(new_table) 671 } 672 } 673 674 /// 页表项 675 #[derive(Copy, Clone)] 676 pub struct PageEntry<Arch> { 677 data: usize, 678 phantom: PhantomData<Arch>, 679 } 680 681 impl<Arch> Debug for PageEntry<Arch> { 682 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { 683 f.write_fmt(format_args!("PageEntry({:#x})", self.data)) 684 } 685 } 686 687 impl<Arch: MemoryManagementArch> PageEntry<Arch> { 688 #[inline(always)] 689 pub fn new(paddr: PhysAddr, flags: EntryFlags<Arch>) -> Self { 690 Self { 691 data: MMArch::make_entry(paddr, flags.data()), 692 phantom: PhantomData, 693 } 694 } 695 #[inline(always)] 696 pub fn from_usize(data: usize) -> Self { 697 Self { 698 data, 699 phantom: PhantomData, 700 } 701 } 702 703 #[inline(always)] 704 pub fn data(&self) -> usize { 705 self.data 706 } 707 708 /// 获取当前页表项指向的物理地址 709 /// 710 /// ## 返回值 711 /// 712 /// - Ok(PhysAddr) 如果当前页面存在于物理内存中, 返回物理地址 713 /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址 714 #[inline(always)] 715 pub fn address(&self) -> Result<PhysAddr, PhysAddr> { 716 let paddr: PhysAddr = { 717 #[cfg(target_arch = "x86_64")] 718 { 719 PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK) 720 } 721 722 #[cfg(target_arch = "riscv64")] 723 { 724 let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 54) - 1); 725 super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address() 726 } 727 }; 728 729 if self.present() { 730 Ok(paddr) 731 } else { 732 Err(paddr) 733 } 734 } 735 736 #[inline(always)] 737 pub fn flags(&self) -> EntryFlags<Arch> { 738 unsafe { EntryFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) } 739 } 740 741 #[inline(always)] 742 pub fn set_flags(&mut self, flags: EntryFlags<Arch>) { 743 self.data = (self.data & !Arch::ENTRY_FLAGS_MASK) | flags.data(); 744 } 745 746 #[inline(always)] 747 pub fn present(&self) -> bool { 748 return self.data & Arch::ENTRY_FLAG_PRESENT != 0; 749 } 750 751 #[inline(always)] 752 pub fn empty(&self) -> bool { 753 self.data & !(Arch::ENTRY_FLAG_DIRTY & Arch::ENTRY_FLAG_ACCESSED) == 0 754 } 755 756 #[inline(always)] 757 pub fn protnone(&self) -> bool { 758 return self.data & (Arch::ENTRY_FLAG_PRESENT | Arch::ENTRY_FLAG_GLOBAL) 759 == Arch::ENTRY_FLAG_GLOBAL; 760 } 761 762 #[inline(always)] 763 pub fn write(&self) -> bool { 764 return self.data & Arch::ENTRY_FLAG_READWRITE != 0; 765 } 766 } 767 768 /// 页表项的标志位 769 #[derive(Copy, Clone, Hash)] 770 pub struct EntryFlags<Arch> { 771 data: usize, 772 phantom: PhantomData<Arch>, 773 } 774 775 impl<Arch: MemoryManagementArch> Default for EntryFlags<Arch> { 776 fn default() -> Self { 777 Self::new() 778 } 779 } 780 781 #[allow(dead_code)] 782 impl<Arch: MemoryManagementArch> EntryFlags<Arch> { 783 #[inline(always)] 784 pub fn new() -> Self { 785 let mut r = unsafe { 786 Self::from_data( 787 Arch::ENTRY_FLAG_DEFAULT_PAGE 788 | Arch::ENTRY_FLAG_READONLY 789 | Arch::ENTRY_FLAG_NO_EXEC, 790 ) 791 }; 792 793 #[cfg(target_arch = "x86_64")] 794 { 795 if crate::arch::mm::X86_64MMArch::is_xd_reserved() { 796 r = r.set_execute(true); 797 } 798 } 799 800 return r; 801 } 802 803 /// 根据ProtFlags生成EntryFlags 804 /// 805 /// ## 参数 806 /// 807 /// - prot_flags: 页的保护标志 808 /// - user: 用户空间是否可访问 809 pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> Self { 810 if Arch::PAGE_FAULT_ENABLED { 811 let vm_flags = super::VmFlags::from(prot_flags); 812 Arch::vm_get_page_prot(vm_flags).set_user(user) 813 } else { 814 EntryFlags::new() 815 .set_user(user) 816 .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC)) 817 .set_write(prot_flags.contains(ProtFlags::PROT_WRITE)) 818 } 819 } 820 821 #[inline(always)] 822 pub fn data(&self) -> usize { 823 self.data 824 } 825 826 #[inline(always)] 827 pub const unsafe fn from_data(data: usize) -> Self { 828 return Self { 829 data, 830 phantom: PhantomData, 831 }; 832 } 833 834 /// 为新页表的页表项设置默认值 835 /// 836 /// 默认值为: 837 /// - present 838 /// - read only 839 /// - kernel space 840 /// - no exec 841 #[inline(always)] 842 pub fn new_page_table(user: bool) -> Self { 843 return unsafe { 844 let r = { 845 #[cfg(target_arch = "x86_64")] 846 { 847 Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE) 848 } 849 850 #[cfg(target_arch = "riscv64")] 851 { 852 // riscv64指向下一级页表的页表项,不应设置R/W/X权限位 853 Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE) 854 } 855 }; 856 857 #[cfg(target_arch = "x86_64")] 858 { 859 if user { 860 r.set_user(true) 861 } else { 862 r 863 } 864 } 865 866 #[cfg(target_arch = "riscv64")] 867 { 868 r 869 } 870 }; 871 } 872 873 /// 取得当前页表项的所有权,更新当前页表项的标志位,并返回更新后的页表项。 874 /// 875 /// ## 参数 876 /// - flag 要更新的标志位的值 877 /// - value 如果为true,那么将flag对应的位设置为1,否则设置为0 878 /// 879 /// ## 返回值 880 /// 881 /// 更新后的页表项 882 #[inline(always)] 883 #[must_use] 884 pub fn update_flags(mut self, flag: usize, value: bool) -> Self { 885 if value { 886 self.data |= flag; 887 } else { 888 self.data &= !flag; 889 } 890 return self; 891 } 892 893 /// 判断当前页表项是否存在指定的flag(只有全部flag都存在才返回true) 894 #[inline(always)] 895 pub fn has_flag(&self, flag: usize) -> bool { 896 return self.data & flag == flag; 897 } 898 899 #[inline(always)] 900 pub fn present(&self) -> bool { 901 return self.has_flag(Arch::ENTRY_FLAG_PRESENT); 902 } 903 904 /// 设置当前页表项的权限 905 /// 906 /// @param value 如果为true,那么将当前页表项的权限设置为用户态可访问 907 #[must_use] 908 #[inline(always)] 909 pub fn set_user(self, value: bool) -> Self { 910 return self.update_flags(Arch::ENTRY_FLAG_USER, value); 911 } 912 913 /// 用户态是否可以访问当前页表项 914 #[inline(always)] 915 pub fn has_user(&self) -> bool { 916 return self.has_flag(Arch::ENTRY_FLAG_USER); 917 } 918 919 /// 设置当前页表项的可写性, 如果为true,那么将当前页表项的权限设置为可写, 否则设置为只读 920 /// 921 /// ## 返回值 922 /// 923 /// 更新后的页表项. 924 /// 925 /// **请注意,**本函数会取得当前页表项的所有权,因此返回的页表项不是原来的页表项 926 #[must_use] 927 #[inline(always)] 928 pub fn set_write(self, value: bool) -> Self { 929 #[cfg(target_arch = "x86_64")] 930 { 931 // 有的架构同时具有可写和不可写的标志位,因此需要同时更新 932 return self 933 .update_flags(Arch::ENTRY_FLAG_READONLY, !value) 934 .update_flags(Arch::ENTRY_FLAG_READWRITE, value); 935 } 936 937 #[cfg(target_arch = "riscv64")] 938 { 939 if value { 940 return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true); 941 } else { 942 return self 943 .update_flags(Arch::ENTRY_FLAG_READONLY, true) 944 .update_flags(Arch::ENTRY_FLAG_WRITEABLE, false); 945 } 946 } 947 } 948 949 /// 当前页表项是否可写 950 #[inline(always)] 951 pub fn has_write(&self) -> bool { 952 // 有的架构同时具有可写和不可写的标志位,因此需要同时判断 953 return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY) 954 == Arch::ENTRY_FLAG_READWRITE; 955 } 956 957 /// 设置当前页表项的可执行性, 如果为true,那么将当前页表项的权限设置为可执行, 否则设置为不可执行 958 #[must_use] 959 #[inline(always)] 960 pub fn set_execute(self, mut value: bool) -> Self { 961 #[cfg(target_arch = "x86_64")] 962 { 963 // 如果xd位被保留,那么将可执行性设置为true 964 if crate::arch::mm::X86_64MMArch::is_xd_reserved() { 965 value = true; 966 } 967 } 968 969 // 有的架构同时具有可执行和不可执行的标志位,因此需要同时更新 970 return self 971 .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value) 972 .update_flags(Arch::ENTRY_FLAG_EXEC, value); 973 } 974 975 /// 当前页表项是否可执行 976 #[inline(always)] 977 pub fn has_execute(&self) -> bool { 978 // 有的架构同时具有可执行和不可执行的标志位,因此需要同时判断 979 return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC) 980 == Arch::ENTRY_FLAG_EXEC; 981 } 982 983 /// 设置当前页表项的缓存策略 984 /// 985 /// ## 参数 986 /// 987 /// - value: 如果为true,那么将当前页表项的缓存策略设置为不缓存。 988 #[inline(always)] 989 pub fn set_page_cache_disable(self, value: bool) -> Self { 990 return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value); 991 } 992 993 /// 获取当前页表项的缓存策略 994 /// 995 /// ## 返回值 996 /// 997 /// 如果当前页表项的缓存策略为不缓存,那么返回true,否则返回false。 998 #[inline(always)] 999 pub fn has_page_cache_disable(&self) -> bool { 1000 return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE); 1001 } 1002 1003 /// 设置当前页表项的写穿策略 1004 /// 1005 /// ## 参数 1006 /// 1007 /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。 1008 #[inline(always)] 1009 pub fn set_page_write_through(self, value: bool) -> Self { 1010 return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value); 1011 } 1012 1013 #[inline(always)] 1014 pub fn set_page_global(self, value: bool) -> Self { 1015 return self.update_flags(MMArch::ENTRY_FLAG_GLOBAL, value); 1016 } 1017 1018 /// 获取当前页表项的写穿策略 1019 /// 1020 /// ## 返回值 1021 /// 1022 /// 如果当前页表项的写穿策略为写穿,那么返回true,否则返回false。 1023 #[inline(always)] 1024 pub fn has_page_write_through(&self) -> bool { 1025 return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH); 1026 } 1027 1028 /// 设置当前页表是否为脏页 1029 /// 1030 /// ## 参数 1031 /// 1032 /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。 1033 #[inline(always)] 1034 pub fn set_dirty(self, value: bool) -> Self { 1035 return self.update_flags(Arch::ENTRY_FLAG_DIRTY, value); 1036 } 1037 1038 /// 设置当前页表被访问 1039 /// 1040 /// ## 参数 1041 /// 1042 /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。 1043 #[inline(always)] 1044 pub fn set_access(self, value: bool) -> Self { 1045 return self.update_flags(Arch::ENTRY_FLAG_ACCESSED, value); 1046 } 1047 1048 /// 设置指向的页是否为大页 1049 /// 1050 /// ## 参数 1051 /// 1052 /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。 1053 #[inline(always)] 1054 pub fn set_huge_page(self, value: bool) -> Self { 1055 return self.update_flags(Arch::ENTRY_FLAG_HUGE_PAGE, value); 1056 } 1057 1058 /// MMIO内存的页表项标志 1059 #[inline(always)] 1060 pub fn mmio_flags() -> Self { 1061 #[cfg(target_arch = "x86_64")] 1062 { 1063 Self::new() 1064 .set_user(false) 1065 .set_write(true) 1066 .set_execute(true) 1067 .set_page_cache_disable(true) 1068 .set_page_write_through(true) 1069 .set_page_global(true) 1070 } 1071 1072 #[cfg(target_arch = "riscv64")] 1073 { 1074 Self::new() 1075 .set_user(false) 1076 .set_write(true) 1077 .set_execute(true) 1078 .set_page_global(true) 1079 } 1080 } 1081 } 1082 1083 impl<Arch: MemoryManagementArch> fmt::Debug for EntryFlags<Arch> { 1084 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1085 f.debug_struct("EntryFlags") 1086 .field("bits", &format_args!("{:#0x}", self.data)) 1087 .field("present", &self.present()) 1088 .field("has_write", &self.has_write()) 1089 .field("has_execute", &self.has_execute()) 1090 .field("has_user", &self.has_user()) 1091 .finish() 1092 } 1093 } 1094 1095 /// 页表映射器 1096 #[derive(Hash)] 1097 pub struct PageMapper<Arch, F> { 1098 /// 页表类型 1099 table_kind: PageTableKind, 1100 /// 根页表物理地址 1101 table_paddr: PhysAddr, 1102 /// 页分配器 1103 frame_allocator: F, 1104 phantom: PhantomData<fn() -> Arch>, 1105 } 1106 1107 impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> { 1108 /// 创建新的页面映射器 1109 /// 1110 /// ## 参数 1111 /// - table_kind 页表类型 1112 /// - table_paddr 根页表物理地址 1113 /// - allocator 页分配器 1114 /// 1115 /// ## 返回值 1116 /// 1117 /// 页面映射器 1118 pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self { 1119 return Self { 1120 table_kind, 1121 table_paddr, 1122 frame_allocator: allocator, 1123 phantom: PhantomData, 1124 }; 1125 } 1126 1127 /// 创建页表,并为这个页表创建页面映射器 1128 pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> { 1129 let table_paddr = allocator.allocate_one()?; 1130 // 清空页表 1131 let table_vaddr = Arch::phys_2_virt(table_paddr)?; 1132 Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE); 1133 return Some(Self::new(table_kind, table_paddr, allocator)); 1134 } 1135 1136 /// 获取当前页表的页面映射器 1137 #[inline(always)] 1138 pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self { 1139 let table_paddr = Arch::table(table_kind); 1140 return Self::new(table_kind, table_paddr, allocator); 1141 } 1142 1143 /// 判断当前页表分配器所属的页表是否是当前页表 1144 #[inline(always)] 1145 pub fn is_current(&self) -> bool { 1146 return unsafe { self.table().phys() == Arch::table(self.table_kind) }; 1147 } 1148 1149 /// 将当前页表分配器所属的页表设置为当前页表 1150 #[inline(always)] 1151 pub unsafe fn make_current(&self) { 1152 Arch::set_table(self.table_kind, self.table_paddr); 1153 } 1154 1155 /// 获取当前页表分配器所属的根页表的结构体 1156 #[inline(always)] 1157 pub fn table(&self) -> PageTable<Arch> { 1158 // 由于只能通过new方法创建PageMapper,因此这里假定table_paddr是有效的 1159 return unsafe { 1160 PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1) 1161 }; 1162 } 1163 1164 /// 获取当前PageMapper所对应的页分配器实例的引用 1165 #[inline(always)] 1166 #[allow(dead_code)] 1167 pub fn allocator_ref(&self) -> &F { 1168 return &self.frame_allocator; 1169 } 1170 1171 /// 获取当前PageMapper所对应的页分配器实例的可变引用 1172 #[inline(always)] 1173 pub fn allocator_mut(&mut self) -> &mut F { 1174 return &mut self.frame_allocator; 1175 } 1176 1177 /// 从当前PageMapper的页分配器中分配一个物理页,并将其映射到指定的虚拟地址 1178 pub unsafe fn map( 1179 &mut self, 1180 virt: VirtAddr, 1181 flags: EntryFlags<Arch>, 1182 ) -> Option<PageFlush<Arch>> { 1183 compiler_fence(Ordering::SeqCst); 1184 let phys: PhysAddr = self.frame_allocator.allocate_one()?; 1185 compiler_fence(Ordering::SeqCst); 1186 1187 unsafe { 1188 let vaddr = MMArch::phys_2_virt(phys).unwrap(); 1189 MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE); 1190 } 1191 1192 let mut page_manager_guard: SpinLockGuard<'static, PageManager> = 1193 page_manager_lock_irqsave(); 1194 if !page_manager_guard.contains(&phys) { 1195 page_manager_guard.insert(phys, &Arc::new(Page::new(false, phys))) 1196 } 1197 drop(page_manager_guard); 1198 return self.map_phys(virt, phys, flags); 1199 } 1200 1201 /// 映射一个物理页到指定的虚拟地址 1202 pub unsafe fn map_phys( 1203 &mut self, 1204 virt: VirtAddr, 1205 phys: PhysAddr, 1206 flags: EntryFlags<Arch>, 1207 ) -> Option<PageFlush<Arch>> { 1208 // 验证虚拟地址和物理地址是否对齐 1209 if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) { 1210 error!( 1211 "Try to map unaligned page: virt={:?}, phys={:?}", 1212 virt, phys 1213 ); 1214 return None; 1215 } 1216 1217 let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 1218 1219 // TODO: 验证flags是否合法 1220 1221 // 创建页表项 1222 let entry = PageEntry::new(phys, flags); 1223 let mut table = self.table(); 1224 loop { 1225 let i = table.index_of(virt)?; 1226 1227 assert!(i < Arch::PAGE_ENTRY_NUM); 1228 if table.level() == 0 { 1229 compiler_fence(Ordering::SeqCst); 1230 1231 table.set_entry(i, entry); 1232 compiler_fence(Ordering::SeqCst); 1233 return Some(PageFlush::new(virt)); 1234 } else { 1235 let next_table = table.next_level_table(i); 1236 if let Some(next_table) = next_table { 1237 table = next_table; 1238 // debug!("Mapping {:?} to next level table...", virt); 1239 } else { 1240 // 分配下一级页表 1241 let frame = self.frame_allocator.allocate_one()?; 1242 1243 // 清空这个页帧 1244 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 1245 // 设置页表项的flags 1246 let flags: EntryFlags<Arch> = 1247 EntryFlags::new_page_table(virt.kind() == PageTableKind::User); 1248 1249 // 把新分配的页表映射到当前页表 1250 table.set_entry(i, PageEntry::new(frame, flags)); 1251 1252 // 获取新分配的页表 1253 table = table.next_level_table(i)?; 1254 } 1255 } 1256 } 1257 } 1258 1259 /// 进行大页映射 1260 pub unsafe fn map_huge_page( 1261 &mut self, 1262 virt: VirtAddr, 1263 flags: EntryFlags<Arch>, 1264 ) -> Option<PageFlush<Arch>> { 1265 // 验证虚拟地址是否对齐 1266 if !(virt.check_aligned(Arch::PAGE_SIZE)) { 1267 error!("Try to map unaligned page: virt={:?}", virt); 1268 return None; 1269 } 1270 1271 let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 1272 1273 let mut table = self.table(); 1274 loop { 1275 let i = table.index_of(virt)?; 1276 assert!(i < Arch::PAGE_ENTRY_NUM); 1277 let next_table = table.next_level_table(i); 1278 if let Some(next_table) = next_table { 1279 table = next_table; 1280 } else { 1281 break; 1282 } 1283 } 1284 1285 // 支持2M、1G大页,即页表层级为1、2级的页表可以映射大页 1286 if table.level == 0 || table.level > 2 { 1287 return None; 1288 } 1289 1290 let (phys, count) = self.frame_allocator.allocate(PageFrameCount::new( 1291 Arch::PAGE_ENTRY_NUM.pow(table.level as u32), 1292 ))?; 1293 1294 MMArch::write_bytes( 1295 MMArch::phys_2_virt(phys).unwrap(), 1296 0, 1297 MMArch::PAGE_SIZE * count.data(), 1298 ); 1299 1300 table.set_entry( 1301 table.index_of(virt)?, 1302 PageEntry::new(phys, flags.set_huge_page(true)), 1303 )?; 1304 Some(PageFlush::new(virt)) 1305 } 1306 1307 /// 为虚拟地址分配指定层级的页表 1308 /// ## 参数 1309 /// 1310 /// - `virt`: 虚拟地址 1311 /// - `level`: 指定页表层级 1312 /// 1313 /// ## 返回值 1314 /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表 1315 /// - None: 对应页表不存在 1316 pub unsafe fn allocate_table( 1317 &mut self, 1318 virt: VirtAddr, 1319 level: usize, 1320 ) -> Option<PageTable<Arch>> { 1321 let table = self.get_table(virt, level + 1)?; 1322 let i = table.index_of(virt)?; 1323 let frame = self.frame_allocator.allocate_one()?; 1324 1325 // 清空这个页帧 1326 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 1327 1328 // 设置页表项的flags 1329 let flags: EntryFlags<Arch> = 1330 EntryFlags::new_page_table(virt.kind() == PageTableKind::User); 1331 1332 table.set_entry(i, PageEntry::new(frame, flags)); 1333 table.next_level_table(i) 1334 } 1335 1336 /// 获取虚拟地址的指定层级页表 1337 /// ## 参数 1338 /// 1339 /// - `virt`: 虚拟地址 1340 /// - `level`: 指定页表层级 1341 /// 1342 /// ## 返回值 1343 /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表 1344 /// - None: 对应页表不存在 1345 pub fn get_table(&self, virt: VirtAddr, level: usize) -> Option<PageTable<Arch>> { 1346 let mut table = self.table(); 1347 if level > Arch::PAGE_LEVELS - 1 { 1348 return None; 1349 } 1350 1351 unsafe { 1352 loop { 1353 if table.level == level { 1354 return Some(table); 1355 } 1356 let i = table.index_of(virt)?; 1357 assert!(i < Arch::PAGE_ENTRY_NUM); 1358 1359 table = table.next_level_table(i)?; 1360 } 1361 } 1362 } 1363 1364 /// 获取虚拟地址在指定层级页表的PageEntry 1365 /// ## 参数 1366 /// 1367 /// - `virt`: 虚拟地址 1368 /// - `level`: 指定页表层级 1369 /// 1370 /// ## 返回值 1371 /// - Some(PageEntry<Arch>): 虚拟地址在指定层级的页表的有效PageEntry 1372 /// - None: 无对应的有效PageEntry 1373 pub fn get_entry(&self, virt: VirtAddr, level: usize) -> Option<PageEntry<Arch>> { 1374 let table = self.get_table(virt, level)?; 1375 let i = table.index_of(virt)?; 1376 let entry = unsafe { table.entry(i) }?; 1377 1378 if !entry.empty() { 1379 Some(entry) 1380 } else { 1381 None 1382 } 1383 1384 // let mut table = self.table(); 1385 // if level > Arch::PAGE_LEVELS - 1 { 1386 // return None; 1387 // } 1388 // unsafe { 1389 // loop { 1390 // let i = table.index_of(virt)?; 1391 // assert!(i < Arch::PAGE_ENTRY_NUM); 1392 1393 // if table.level == level { 1394 // let entry = table.entry(i)?; 1395 // if !entry.empty() { 1396 // return Some(entry); 1397 // } else { 1398 // return None; 1399 // } 1400 // } 1401 1402 // table = table.next_level_table(i)?; 1403 // } 1404 // } 1405 } 1406 1407 /// 拷贝用户空间映射 1408 /// ## 参数 1409 /// 1410 /// - `umapper`: 要拷贝的用户空间 1411 /// - `copy_on_write`: 是否写时复制 1412 pub unsafe fn clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool) { 1413 let old_table = umapper.table(); 1414 let new_table = self.table(); 1415 let allocator = self.allocator_mut(); 1416 // 顶级页表的[0, PAGE_KERNEL_INDEX)项为用户空间映射 1417 for entry_index in 0..Arch::PAGE_KERNEL_INDEX { 1418 if let Some(next_table) = old_table.next_level_table(entry_index) { 1419 let table = next_table.clone(allocator, copy_on_write).unwrap(); 1420 let old_entry = old_table.entry(entry_index).unwrap(); 1421 let entry = PageEntry::new(table.phys(), old_entry.flags()); 1422 new_table.set_entry(entry_index, entry); 1423 } 1424 } 1425 } 1426 1427 /// 将物理地址映射到具有线性偏移量的虚拟地址 1428 #[allow(dead_code)] 1429 pub unsafe fn map_linearly( 1430 &mut self, 1431 phys: PhysAddr, 1432 flags: EntryFlags<Arch>, 1433 ) -> Option<(VirtAddr, PageFlush<Arch>)> { 1434 let virt: VirtAddr = Arch::phys_2_virt(phys)?; 1435 return self.map_phys(virt, phys, flags).map(|flush| (virt, flush)); 1436 } 1437 1438 /// 修改虚拟地址的页表项的flags,并返回页表项刷新器 1439 /// 1440 /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效 1441 /// 1442 /// ## 参数 1443 /// - virt 虚拟地址 1444 /// - flags 新的页表项的flags 1445 /// 1446 /// ## 返回值 1447 /// 1448 /// 如果修改成功,返回刷新器,否则返回None 1449 pub unsafe fn remap( 1450 &mut self, 1451 virt: VirtAddr, 1452 flags: EntryFlags<Arch>, 1453 ) -> Option<PageFlush<Arch>> { 1454 return self 1455 .visit(virt, |p1, i| { 1456 let mut entry = p1.entry(i)?; 1457 1458 entry.set_flags(flags); 1459 p1.set_entry(i, entry); 1460 Some(PageFlush::new(virt)) 1461 }) 1462 .flatten(); 1463 } 1464 1465 /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags 1466 /// 1467 /// ## 参数 1468 /// 1469 /// - virt 虚拟地址 1470 /// 1471 /// ## 返回值 1472 /// 1473 /// 如果查找成功,返回物理地址和页表项的flags,否则返回None 1474 pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, EntryFlags<Arch>)> { 1475 let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??; 1476 let paddr = entry.address().ok()?; 1477 let flags = entry.flags(); 1478 return Some((paddr, flags)); 1479 } 1480 1481 /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器 1482 /// 1483 /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效 1484 /// 1485 /// ## 参数 1486 /// 1487 /// - virt 虚拟地址 1488 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1489 /// 1490 /// ## 返回值 1491 /// 如果取消成功,返回刷新器,否则返回None 1492 #[allow(dead_code)] 1493 pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> { 1494 let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?; 1495 self.frame_allocator.free_one(paddr); 1496 return Some(flusher); 1497 } 1498 1499 /// 取消虚拟地址的映射,并返回物理地址和页表项的flags 1500 /// 1501 /// ## 参数 1502 /// 1503 /// - vaddr 虚拟地址 1504 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1505 /// 1506 /// ## 返回值 1507 /// 1508 /// 如果取消成功,返回物理地址和页表项的flags,否则返回None 1509 pub unsafe fn unmap_phys( 1510 &mut self, 1511 virt: VirtAddr, 1512 unmap_parents: bool, 1513 ) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>)> { 1514 if !virt.check_aligned(Arch::PAGE_SIZE) { 1515 error!("Try to unmap unaligned page: virt={:?}", virt); 1516 return None; 1517 } 1518 1519 let table = self.table(); 1520 return unmap_phys_inner(virt, &table, unmap_parents, self.allocator_mut()) 1521 .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt))); 1522 } 1523 1524 /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F 1525 fn visit<T>( 1526 &self, 1527 virt: VirtAddr, 1528 f: impl FnOnce(&mut PageTable<Arch>, usize) -> T, 1529 ) -> Option<T> { 1530 let mut table = self.table(); 1531 unsafe { 1532 loop { 1533 let i = table.index_of(virt)?; 1534 if table.level() == 0 { 1535 return Some(f(&mut table, i)); 1536 } else { 1537 table = table.next_level_table(i)?; 1538 } 1539 } 1540 } 1541 } 1542 } 1543 1544 /// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】 1545 /// 1546 /// ## 参数 1547 /// 1548 /// - vaddr 虚拟地址 1549 /// - table 页表 1550 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1551 /// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内) 1552 /// 1553 /// ## 返回值 1554 /// 1555 /// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None 1556 unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>( 1557 vaddr: VirtAddr, 1558 table: &PageTable<Arch>, 1559 unmap_parents: bool, 1560 allocator: &mut impl FrameAllocator, 1561 ) -> Option<(PhysAddr, EntryFlags<Arch>)> { 1562 // 获取页表项的索引 1563 let i = table.index_of(vaddr)?; 1564 1565 // 如果当前是最后一级页表,直接取消页面映射 1566 if table.level() == 0 { 1567 let entry = table.entry(i)?; 1568 table.set_entry(i, PageEntry::from_usize(0)); 1569 return Some((entry.address().ok()?, entry.flags())); 1570 } 1571 1572 let subtable = table.next_level_table(i)?; 1573 // 递归地取消映射 1574 let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator)?; 1575 1576 // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables, 1577 // as these mappings may become out of sync 1578 if unmap_parents { 1579 // 如果子页表已经没有映射的页面了,就取消子页表的映射 1580 1581 // 检查子页表中是否还有映射的页面 1582 let x = (0..Arch::PAGE_ENTRY_NUM) 1583 .map(|k| subtable.entry(k).expect("invalid page entry")) 1584 .any(|e| e.present()); 1585 if !x { 1586 // 如果没有,就取消子页表的映射 1587 table.set_entry(i, PageEntry::from_usize(0)); 1588 // 释放子页表 1589 allocator.free_one(subtable.phys()); 1590 } 1591 } 1592 1593 return Some(result); 1594 } 1595 1596 impl<Arch, F: Debug> Debug for PageMapper<Arch, F> { 1597 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1598 f.debug_struct("PageMapper") 1599 .field("table_paddr", &self.table_paddr) 1600 .field("frame_allocator", &self.frame_allocator) 1601 .finish() 1602 } 1603 } 1604 1605 /// 页表刷新器的trait 1606 pub trait Flusher<Arch: MemoryManagementArch> { 1607 /// 取消对指定的page flusher的刷新 1608 fn consume(&mut self, flush: PageFlush<Arch>); 1609 } 1610 1611 /// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法, 1612 /// 否则会造成对页表的更改被忽略,这是不安全的 1613 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 1614 pub struct PageFlush<Arch: MemoryManagementArch> { 1615 virt: VirtAddr, 1616 phantom: PhantomData<Arch>, 1617 } 1618 1619 impl<Arch: MemoryManagementArch> PageFlush<Arch> { 1620 pub fn new(virt: VirtAddr) -> Self { 1621 return Self { 1622 virt, 1623 phantom: PhantomData, 1624 }; 1625 } 1626 1627 pub fn flush(self) { 1628 unsafe { Arch::invalidate_page(self.virt) }; 1629 } 1630 1631 /// 忽略掉这个刷新器 1632 pub unsafe fn ignore(self) { 1633 mem::forget(self); 1634 } 1635 } 1636 1637 impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> { 1638 fn drop(&mut self) { 1639 unsafe { 1640 MMArch::invalidate_page(self.virt); 1641 } 1642 } 1643 } 1644 1645 /// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法, 1646 /// 否则会造成对页表的更改被忽略,这是不安全的 1647 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 1648 pub struct PageFlushAll<Arch: MemoryManagementArch> { 1649 phantom: PhantomData<fn() -> Arch>, 1650 } 1651 1652 #[allow(dead_code)] 1653 impl<Arch: MemoryManagementArch> PageFlushAll<Arch> { 1654 pub fn new() -> Self { 1655 return Self { 1656 phantom: PhantomData, 1657 }; 1658 } 1659 1660 pub fn flush(self) { 1661 unsafe { Arch::invalidate_all() }; 1662 } 1663 1664 /// 忽略掉这个刷新器 1665 pub unsafe fn ignore(self) { 1666 mem::forget(self); 1667 } 1668 } 1669 1670 impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> { 1671 /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了) 1672 fn consume(&mut self, flush: PageFlush<Arch>) { 1673 unsafe { flush.ignore() }; 1674 } 1675 } 1676 1677 impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T { 1678 /// 允许一个flusher consume掉另一个flusher 1679 fn consume(&mut self, flush: PageFlush<Arch>) { 1680 <T as Flusher<Arch>>::consume(self, flush); 1681 } 1682 } 1683 1684 impl<Arch: MemoryManagementArch> Flusher<Arch> for () { 1685 fn consume(&mut self, _flush: PageFlush<Arch>) {} 1686 } 1687 1688 impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> { 1689 fn drop(&mut self) { 1690 unsafe { 1691 Arch::invalidate_all(); 1692 } 1693 } 1694 } 1695 1696 /// 未在当前CPU上激活的页表的刷新器 1697 /// 1698 /// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表 1699 /// 1700 /// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销) 1701 #[derive(Debug)] 1702 pub struct InactiveFlusher; 1703 1704 impl InactiveFlusher { 1705 pub fn new() -> Self { 1706 return Self {}; 1707 } 1708 } 1709 1710 impl Flusher<MMArch> for InactiveFlusher { 1711 fn consume(&mut self, flush: PageFlush<MMArch>) { 1712 unsafe { 1713 flush.ignore(); 1714 } 1715 } 1716 } 1717 1718 impl Drop for InactiveFlusher { 1719 fn drop(&mut self) { 1720 // 发送刷新页表的IPI 1721 send_ipi(IpiKind::FlushTLB, IpiTarget::Other); 1722 } 1723 } 1724 1725 /// # 把一个地址向下对齐到页大小 1726 pub fn round_down_to_page_size(addr: usize) -> usize { 1727 addr & !(MMArch::PAGE_SIZE - 1) 1728 } 1729 1730 /// # 把一个地址向上对齐到页大小 1731 pub fn round_up_to_page_size(addr: usize) -> usize { 1732 round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1) 1733 } 1734