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 let vm_flags = super::VmFlags::from(prot_flags); 811 // let flags: EntryFlags<Arch> = EntryFlags::new() 812 // .set_user(user) 813 // .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC)) 814 // .set_write(prot_flags.contains(ProtFlags::PROT_WRITE)); 815 let flags = Arch::vm_get_page_prot(vm_flags).set_user(user); 816 return flags; 817 } 818 819 #[inline(always)] 820 pub fn data(&self) -> usize { 821 self.data 822 } 823 824 #[inline(always)] 825 pub const unsafe fn from_data(data: usize) -> Self { 826 return Self { 827 data, 828 phantom: PhantomData, 829 }; 830 } 831 832 /// 为新页表的页表项设置默认值 833 /// 834 /// 默认值为: 835 /// - present 836 /// - read only 837 /// - kernel space 838 /// - no exec 839 #[inline(always)] 840 pub fn new_page_table(user: bool) -> Self { 841 return unsafe { 842 let r = { 843 #[cfg(target_arch = "x86_64")] 844 { 845 Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE) 846 } 847 848 #[cfg(target_arch = "riscv64")] 849 { 850 // riscv64指向下一级页表的页表项,不应设置R/W/X权限位 851 Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE) 852 } 853 }; 854 855 #[cfg(target_arch = "x86_64")] 856 { 857 if user { 858 r.set_user(true) 859 } else { 860 r 861 } 862 } 863 864 #[cfg(target_arch = "riscv64")] 865 { 866 r 867 } 868 }; 869 } 870 871 /// 取得当前页表项的所有权,更新当前页表项的标志位,并返回更新后的页表项。 872 /// 873 /// ## 参数 874 /// - flag 要更新的标志位的值 875 /// - value 如果为true,那么将flag对应的位设置为1,否则设置为0 876 /// 877 /// ## 返回值 878 /// 879 /// 更新后的页表项 880 #[inline(always)] 881 #[must_use] 882 pub fn update_flags(mut self, flag: usize, value: bool) -> Self { 883 if value { 884 self.data |= flag; 885 } else { 886 self.data &= !flag; 887 } 888 return self; 889 } 890 891 /// 判断当前页表项是否存在指定的flag(只有全部flag都存在才返回true) 892 #[inline(always)] 893 pub fn has_flag(&self, flag: usize) -> bool { 894 return self.data & flag == flag; 895 } 896 897 #[inline(always)] 898 pub fn present(&self) -> bool { 899 return self.has_flag(Arch::ENTRY_FLAG_PRESENT); 900 } 901 902 /// 设置当前页表项的权限 903 /// 904 /// @param value 如果为true,那么将当前页表项的权限设置为用户态可访问 905 #[must_use] 906 #[inline(always)] 907 pub fn set_user(self, value: bool) -> Self { 908 return self.update_flags(Arch::ENTRY_FLAG_USER, value); 909 } 910 911 /// 用户态是否可以访问当前页表项 912 #[inline(always)] 913 pub fn has_user(&self) -> bool { 914 return self.has_flag(Arch::ENTRY_FLAG_USER); 915 } 916 917 /// 设置当前页表项的可写性, 如果为true,那么将当前页表项的权限设置为可写, 否则设置为只读 918 /// 919 /// ## 返回值 920 /// 921 /// 更新后的页表项. 922 /// 923 /// **请注意,**本函数会取得当前页表项的所有权,因此返回的页表项不是原来的页表项 924 #[must_use] 925 #[inline(always)] 926 pub fn set_write(self, value: bool) -> Self { 927 #[cfg(target_arch = "x86_64")] 928 { 929 // 有的架构同时具有可写和不可写的标志位,因此需要同时更新 930 return self 931 .update_flags(Arch::ENTRY_FLAG_READONLY, !value) 932 .update_flags(Arch::ENTRY_FLAG_READWRITE, value); 933 } 934 935 #[cfg(target_arch = "riscv64")] 936 { 937 if value { 938 return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true); 939 } else { 940 return self 941 .update_flags(Arch::ENTRY_FLAG_READONLY, true) 942 .update_flags(Arch::ENTRY_FLAG_WRITEABLE, false); 943 } 944 } 945 } 946 947 /// 当前页表项是否可写 948 #[inline(always)] 949 pub fn has_write(&self) -> bool { 950 // 有的架构同时具有可写和不可写的标志位,因此需要同时判断 951 return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY) 952 == Arch::ENTRY_FLAG_READWRITE; 953 } 954 955 /// 设置当前页表项的可执行性, 如果为true,那么将当前页表项的权限设置为可执行, 否则设置为不可执行 956 #[must_use] 957 #[inline(always)] 958 pub fn set_execute(self, mut value: bool) -> Self { 959 #[cfg(target_arch = "x86_64")] 960 { 961 // 如果xd位被保留,那么将可执行性设置为true 962 if crate::arch::mm::X86_64MMArch::is_xd_reserved() { 963 value = true; 964 } 965 } 966 967 // 有的架构同时具有可执行和不可执行的标志位,因此需要同时更新 968 return self 969 .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value) 970 .update_flags(Arch::ENTRY_FLAG_EXEC, value); 971 } 972 973 /// 当前页表项是否可执行 974 #[inline(always)] 975 pub fn has_execute(&self) -> bool { 976 // 有的架构同时具有可执行和不可执行的标志位,因此需要同时判断 977 return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC) 978 == Arch::ENTRY_FLAG_EXEC; 979 } 980 981 /// 设置当前页表项的缓存策略 982 /// 983 /// ## 参数 984 /// 985 /// - value: 如果为true,那么将当前页表项的缓存策略设置为不缓存。 986 #[inline(always)] 987 pub fn set_page_cache_disable(self, value: bool) -> Self { 988 return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value); 989 } 990 991 /// 获取当前页表项的缓存策略 992 /// 993 /// ## 返回值 994 /// 995 /// 如果当前页表项的缓存策略为不缓存,那么返回true,否则返回false。 996 #[inline(always)] 997 pub fn has_page_cache_disable(&self) -> bool { 998 return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE); 999 } 1000 1001 /// 设置当前页表项的写穿策略 1002 /// 1003 /// ## 参数 1004 /// 1005 /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。 1006 #[inline(always)] 1007 pub fn set_page_write_through(self, value: bool) -> Self { 1008 return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value); 1009 } 1010 1011 #[inline(always)] 1012 pub fn set_page_global(self, value: bool) -> Self { 1013 return self.update_flags(MMArch::ENTRY_FLAG_GLOBAL, value); 1014 } 1015 1016 /// 获取当前页表项的写穿策略 1017 /// 1018 /// ## 返回值 1019 /// 1020 /// 如果当前页表项的写穿策略为写穿,那么返回true,否则返回false。 1021 #[inline(always)] 1022 pub fn has_page_write_through(&self) -> bool { 1023 return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH); 1024 } 1025 1026 /// 设置当前页表是否为脏页 1027 /// 1028 /// ## 参数 1029 /// 1030 /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。 1031 #[inline(always)] 1032 pub fn set_dirty(self, value: bool) -> Self { 1033 return self.update_flags(Arch::ENTRY_FLAG_DIRTY, value); 1034 } 1035 1036 /// 设置当前页表被访问 1037 /// 1038 /// ## 参数 1039 /// 1040 /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。 1041 #[inline(always)] 1042 pub fn set_access(self, value: bool) -> Self { 1043 return self.update_flags(Arch::ENTRY_FLAG_ACCESSED, value); 1044 } 1045 1046 /// 设置指向的页是否为大页 1047 /// 1048 /// ## 参数 1049 /// 1050 /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。 1051 #[inline(always)] 1052 pub fn set_huge_page(self, value: bool) -> Self { 1053 return self.update_flags(Arch::ENTRY_FLAG_HUGE_PAGE, value); 1054 } 1055 1056 /// MMIO内存的页表项标志 1057 #[inline(always)] 1058 pub fn mmio_flags() -> Self { 1059 #[cfg(target_arch = "x86_64")] 1060 { 1061 Self::new() 1062 .set_user(false) 1063 .set_write(true) 1064 .set_execute(true) 1065 .set_page_cache_disable(true) 1066 .set_page_write_through(true) 1067 .set_page_global(true) 1068 } 1069 1070 #[cfg(target_arch = "riscv64")] 1071 { 1072 Self::new() 1073 .set_user(false) 1074 .set_write(true) 1075 .set_execute(true) 1076 .set_page_global(true) 1077 } 1078 } 1079 } 1080 1081 impl<Arch: MemoryManagementArch> fmt::Debug for EntryFlags<Arch> { 1082 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1083 f.debug_struct("EntryFlags") 1084 .field("bits", &format_args!("{:#0x}", self.data)) 1085 .field("present", &self.present()) 1086 .field("has_write", &self.has_write()) 1087 .field("has_execute", &self.has_execute()) 1088 .field("has_user", &self.has_user()) 1089 .finish() 1090 } 1091 } 1092 1093 /// 页表映射器 1094 #[derive(Hash)] 1095 pub struct PageMapper<Arch, F> { 1096 /// 页表类型 1097 table_kind: PageTableKind, 1098 /// 根页表物理地址 1099 table_paddr: PhysAddr, 1100 /// 页分配器 1101 frame_allocator: F, 1102 phantom: PhantomData<fn() -> Arch>, 1103 } 1104 1105 impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> { 1106 /// 创建新的页面映射器 1107 /// 1108 /// ## 参数 1109 /// - table_kind 页表类型 1110 /// - table_paddr 根页表物理地址 1111 /// - allocator 页分配器 1112 /// 1113 /// ## 返回值 1114 /// 1115 /// 页面映射器 1116 pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self { 1117 return Self { 1118 table_kind, 1119 table_paddr, 1120 frame_allocator: allocator, 1121 phantom: PhantomData, 1122 }; 1123 } 1124 1125 /// 创建页表,并为这个页表创建页面映射器 1126 pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> { 1127 let table_paddr = allocator.allocate_one()?; 1128 // 清空页表 1129 let table_vaddr = Arch::phys_2_virt(table_paddr)?; 1130 Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE); 1131 return Some(Self::new(table_kind, table_paddr, allocator)); 1132 } 1133 1134 /// 获取当前页表的页面映射器 1135 #[inline(always)] 1136 pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self { 1137 let table_paddr = Arch::table(table_kind); 1138 return Self::new(table_kind, table_paddr, allocator); 1139 } 1140 1141 /// 判断当前页表分配器所属的页表是否是当前页表 1142 #[inline(always)] 1143 pub fn is_current(&self) -> bool { 1144 return unsafe { self.table().phys() == Arch::table(self.table_kind) }; 1145 } 1146 1147 /// 将当前页表分配器所属的页表设置为当前页表 1148 #[inline(always)] 1149 pub unsafe fn make_current(&self) { 1150 Arch::set_table(self.table_kind, self.table_paddr); 1151 } 1152 1153 /// 获取当前页表分配器所属的根页表的结构体 1154 #[inline(always)] 1155 pub fn table(&self) -> PageTable<Arch> { 1156 // 由于只能通过new方法创建PageMapper,因此这里假定table_paddr是有效的 1157 return unsafe { 1158 PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1) 1159 }; 1160 } 1161 1162 /// 获取当前PageMapper所对应的页分配器实例的引用 1163 #[inline(always)] 1164 #[allow(dead_code)] 1165 pub fn allocator_ref(&self) -> &F { 1166 return &self.frame_allocator; 1167 } 1168 1169 /// 获取当前PageMapper所对应的页分配器实例的可变引用 1170 #[inline(always)] 1171 pub fn allocator_mut(&mut self) -> &mut F { 1172 return &mut self.frame_allocator; 1173 } 1174 1175 /// 从当前PageMapper的页分配器中分配一个物理页,并将其映射到指定的虚拟地址 1176 pub unsafe fn map( 1177 &mut self, 1178 virt: VirtAddr, 1179 flags: EntryFlags<Arch>, 1180 ) -> Option<PageFlush<Arch>> { 1181 compiler_fence(Ordering::SeqCst); 1182 let phys: PhysAddr = self.frame_allocator.allocate_one()?; 1183 compiler_fence(Ordering::SeqCst); 1184 1185 unsafe { 1186 let vaddr = MMArch::phys_2_virt(phys).unwrap(); 1187 MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE); 1188 } 1189 1190 let mut page_manager_guard: SpinLockGuard<'static, PageManager> = 1191 page_manager_lock_irqsave(); 1192 if !page_manager_guard.contains(&phys) { 1193 page_manager_guard.insert(phys, &Arc::new(Page::new(false, phys))) 1194 } 1195 drop(page_manager_guard); 1196 return self.map_phys(virt, phys, flags); 1197 } 1198 1199 /// 映射一个物理页到指定的虚拟地址 1200 pub unsafe fn map_phys( 1201 &mut self, 1202 virt: VirtAddr, 1203 phys: PhysAddr, 1204 flags: EntryFlags<Arch>, 1205 ) -> Option<PageFlush<Arch>> { 1206 // 验证虚拟地址和物理地址是否对齐 1207 if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) { 1208 error!( 1209 "Try to map unaligned page: virt={:?}, phys={:?}", 1210 virt, phys 1211 ); 1212 return None; 1213 } 1214 1215 let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 1216 1217 // TODO: 验证flags是否合法 1218 1219 // 创建页表项 1220 let entry = PageEntry::new(phys, flags); 1221 let mut table = self.table(); 1222 loop { 1223 let i = table.index_of(virt)?; 1224 1225 assert!(i < Arch::PAGE_ENTRY_NUM); 1226 if table.level() == 0 { 1227 compiler_fence(Ordering::SeqCst); 1228 1229 table.set_entry(i, entry); 1230 compiler_fence(Ordering::SeqCst); 1231 return Some(PageFlush::new(virt)); 1232 } else { 1233 let next_table = table.next_level_table(i); 1234 if let Some(next_table) = next_table { 1235 table = next_table; 1236 // debug!("Mapping {:?} to next level table...", virt); 1237 } else { 1238 // 分配下一级页表 1239 let frame = self.frame_allocator.allocate_one()?; 1240 1241 // 清空这个页帧 1242 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 1243 // 设置页表项的flags 1244 let flags: EntryFlags<Arch> = 1245 EntryFlags::new_page_table(virt.kind() == PageTableKind::User); 1246 1247 // 把新分配的页表映射到当前页表 1248 table.set_entry(i, PageEntry::new(frame, flags)); 1249 1250 // 获取新分配的页表 1251 table = table.next_level_table(i)?; 1252 } 1253 } 1254 } 1255 } 1256 1257 /// 进行大页映射 1258 pub unsafe fn map_huge_page( 1259 &mut self, 1260 virt: VirtAddr, 1261 flags: EntryFlags<Arch>, 1262 ) -> Option<PageFlush<Arch>> { 1263 // 验证虚拟地址是否对齐 1264 if !(virt.check_aligned(Arch::PAGE_SIZE)) { 1265 error!("Try to map unaligned page: virt={:?}", virt); 1266 return None; 1267 } 1268 1269 let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 1270 1271 let mut table = self.table(); 1272 loop { 1273 let i = table.index_of(virt)?; 1274 assert!(i < Arch::PAGE_ENTRY_NUM); 1275 let next_table = table.next_level_table(i); 1276 if let Some(next_table) = next_table { 1277 table = next_table; 1278 } else { 1279 break; 1280 } 1281 } 1282 1283 // 支持2M、1G大页,即页表层级为1、2级的页表可以映射大页 1284 if table.level == 0 || table.level > 2 { 1285 return None; 1286 } 1287 1288 let (phys, count) = self.frame_allocator.allocate(PageFrameCount::new( 1289 Arch::PAGE_ENTRY_NUM.pow(table.level as u32), 1290 ))?; 1291 1292 MMArch::write_bytes( 1293 MMArch::phys_2_virt(phys).unwrap(), 1294 0, 1295 MMArch::PAGE_SIZE * count.data(), 1296 ); 1297 1298 table.set_entry( 1299 table.index_of(virt)?, 1300 PageEntry::new(phys, flags.set_huge_page(true)), 1301 )?; 1302 Some(PageFlush::new(virt)) 1303 } 1304 1305 /// 为虚拟地址分配指定层级的页表 1306 /// ## 参数 1307 /// 1308 /// - `virt`: 虚拟地址 1309 /// - `level`: 指定页表层级 1310 /// 1311 /// ## 返回值 1312 /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表 1313 /// - None: 对应页表不存在 1314 pub unsafe fn allocate_table( 1315 &mut self, 1316 virt: VirtAddr, 1317 level: usize, 1318 ) -> Option<PageTable<Arch>> { 1319 let table = self.get_table(virt, level + 1)?; 1320 let i = table.index_of(virt)?; 1321 let frame = self.frame_allocator.allocate_one()?; 1322 1323 // 清空这个页帧 1324 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 1325 1326 // 设置页表项的flags 1327 let flags: EntryFlags<Arch> = 1328 EntryFlags::new_page_table(virt.kind() == PageTableKind::User); 1329 1330 table.set_entry(i, PageEntry::new(frame, flags)); 1331 table.next_level_table(i) 1332 } 1333 1334 /// 获取虚拟地址的指定层级页表 1335 /// ## 参数 1336 /// 1337 /// - `virt`: 虚拟地址 1338 /// - `level`: 指定页表层级 1339 /// 1340 /// ## 返回值 1341 /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表 1342 /// - None: 对应页表不存在 1343 pub fn get_table(&self, virt: VirtAddr, level: usize) -> Option<PageTable<Arch>> { 1344 let mut table = self.table(); 1345 if level > Arch::PAGE_LEVELS - 1 { 1346 return None; 1347 } 1348 1349 unsafe { 1350 loop { 1351 if table.level == level { 1352 return Some(table); 1353 } 1354 let i = table.index_of(virt)?; 1355 assert!(i < Arch::PAGE_ENTRY_NUM); 1356 1357 table = table.next_level_table(i)?; 1358 } 1359 } 1360 } 1361 1362 /// 获取虚拟地址在指定层级页表的PageEntry 1363 /// ## 参数 1364 /// 1365 /// - `virt`: 虚拟地址 1366 /// - `level`: 指定页表层级 1367 /// 1368 /// ## 返回值 1369 /// - Some(PageEntry<Arch>): 虚拟地址在指定层级的页表的有效PageEntry 1370 /// - None: 无对应的有效PageEntry 1371 pub fn get_entry(&self, virt: VirtAddr, level: usize) -> Option<PageEntry<Arch>> { 1372 let table = self.get_table(virt, level)?; 1373 let i = table.index_of(virt)?; 1374 let entry = unsafe { table.entry(i) }?; 1375 1376 if !entry.empty() { 1377 Some(entry) 1378 } else { 1379 None 1380 } 1381 1382 // let mut table = self.table(); 1383 // if level > Arch::PAGE_LEVELS - 1 { 1384 // return None; 1385 // } 1386 // unsafe { 1387 // loop { 1388 // let i = table.index_of(virt)?; 1389 // assert!(i < Arch::PAGE_ENTRY_NUM); 1390 1391 // if table.level == level { 1392 // let entry = table.entry(i)?; 1393 // if !entry.empty() { 1394 // return Some(entry); 1395 // } else { 1396 // return None; 1397 // } 1398 // } 1399 1400 // table = table.next_level_table(i)?; 1401 // } 1402 // } 1403 } 1404 1405 /// 拷贝用户空间映射 1406 /// ## 参数 1407 /// 1408 /// - `umapper`: 要拷贝的用户空间 1409 /// - `copy_on_write`: 是否写时复制 1410 pub unsafe fn clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool) { 1411 let old_table = umapper.table(); 1412 let new_table = self.table(); 1413 let allocator = self.allocator_mut(); 1414 // 顶级页表的[0, PAGE_KERNEL_INDEX)项为用户空间映射 1415 for entry_index in 0..Arch::PAGE_KERNEL_INDEX { 1416 if let Some(next_table) = old_table.next_level_table(entry_index) { 1417 let table = next_table.clone(allocator, copy_on_write).unwrap(); 1418 let old_entry = old_table.entry(entry_index).unwrap(); 1419 let entry = PageEntry::new(table.phys(), old_entry.flags()); 1420 new_table.set_entry(entry_index, entry); 1421 } 1422 } 1423 } 1424 1425 /// 将物理地址映射到具有线性偏移量的虚拟地址 1426 #[allow(dead_code)] 1427 pub unsafe fn map_linearly( 1428 &mut self, 1429 phys: PhysAddr, 1430 flags: EntryFlags<Arch>, 1431 ) -> Option<(VirtAddr, PageFlush<Arch>)> { 1432 let virt: VirtAddr = Arch::phys_2_virt(phys)?; 1433 return self.map_phys(virt, phys, flags).map(|flush| (virt, flush)); 1434 } 1435 1436 /// 修改虚拟地址的页表项的flags,并返回页表项刷新器 1437 /// 1438 /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效 1439 /// 1440 /// ## 参数 1441 /// - virt 虚拟地址 1442 /// - flags 新的页表项的flags 1443 /// 1444 /// ## 返回值 1445 /// 1446 /// 如果修改成功,返回刷新器,否则返回None 1447 pub unsafe fn remap( 1448 &mut self, 1449 virt: VirtAddr, 1450 flags: EntryFlags<Arch>, 1451 ) -> Option<PageFlush<Arch>> { 1452 return self 1453 .visit(virt, |p1, i| { 1454 let mut entry = p1.entry(i)?; 1455 1456 entry.set_flags(flags); 1457 p1.set_entry(i, entry); 1458 Some(PageFlush::new(virt)) 1459 }) 1460 .flatten(); 1461 } 1462 1463 /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags 1464 /// 1465 /// ## 参数 1466 /// 1467 /// - virt 虚拟地址 1468 /// 1469 /// ## 返回值 1470 /// 1471 /// 如果查找成功,返回物理地址和页表项的flags,否则返回None 1472 pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, EntryFlags<Arch>)> { 1473 let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??; 1474 let paddr = entry.address().ok()?; 1475 let flags = entry.flags(); 1476 return Some((paddr, flags)); 1477 } 1478 1479 /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器 1480 /// 1481 /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效 1482 /// 1483 /// ## 参数 1484 /// 1485 /// - virt 虚拟地址 1486 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1487 /// 1488 /// ## 返回值 1489 /// 如果取消成功,返回刷新器,否则返回None 1490 #[allow(dead_code)] 1491 pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> { 1492 let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?; 1493 self.frame_allocator.free_one(paddr); 1494 return Some(flusher); 1495 } 1496 1497 /// 取消虚拟地址的映射,并返回物理地址和页表项的flags 1498 /// 1499 /// ## 参数 1500 /// 1501 /// - vaddr 虚拟地址 1502 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1503 /// 1504 /// ## 返回值 1505 /// 1506 /// 如果取消成功,返回物理地址和页表项的flags,否则返回None 1507 pub unsafe fn unmap_phys( 1508 &mut self, 1509 virt: VirtAddr, 1510 unmap_parents: bool, 1511 ) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>)> { 1512 if !virt.check_aligned(Arch::PAGE_SIZE) { 1513 error!("Try to unmap unaligned page: virt={:?}", virt); 1514 return None; 1515 } 1516 1517 let table = self.table(); 1518 return unmap_phys_inner(virt, &table, unmap_parents, self.allocator_mut()) 1519 .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt))); 1520 } 1521 1522 /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F 1523 fn visit<T>( 1524 &self, 1525 virt: VirtAddr, 1526 f: impl FnOnce(&mut PageTable<Arch>, usize) -> T, 1527 ) -> Option<T> { 1528 let mut table = self.table(); 1529 unsafe { 1530 loop { 1531 let i = table.index_of(virt)?; 1532 if table.level() == 0 { 1533 return Some(f(&mut table, i)); 1534 } else { 1535 table = table.next_level_table(i)?; 1536 } 1537 } 1538 } 1539 } 1540 } 1541 1542 /// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】 1543 /// 1544 /// ## 参数 1545 /// 1546 /// - vaddr 虚拟地址 1547 /// - table 页表 1548 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1549 /// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内) 1550 /// 1551 /// ## 返回值 1552 /// 1553 /// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None 1554 unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>( 1555 vaddr: VirtAddr, 1556 table: &PageTable<Arch>, 1557 unmap_parents: bool, 1558 allocator: &mut impl FrameAllocator, 1559 ) -> Option<(PhysAddr, EntryFlags<Arch>)> { 1560 // 获取页表项的索引 1561 let i = table.index_of(vaddr)?; 1562 1563 // 如果当前是最后一级页表,直接取消页面映射 1564 if table.level() == 0 { 1565 let entry = table.entry(i)?; 1566 table.set_entry(i, PageEntry::from_usize(0)); 1567 return Some((entry.address().ok()?, entry.flags())); 1568 } 1569 1570 let subtable = table.next_level_table(i)?; 1571 // 递归地取消映射 1572 let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator)?; 1573 1574 // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables, 1575 // as these mappings may become out of sync 1576 if unmap_parents { 1577 // 如果子页表已经没有映射的页面了,就取消子页表的映射 1578 1579 // 检查子页表中是否还有映射的页面 1580 let x = (0..Arch::PAGE_ENTRY_NUM) 1581 .map(|k| subtable.entry(k).expect("invalid page entry")) 1582 .any(|e| e.present()); 1583 if !x { 1584 // 如果没有,就取消子页表的映射 1585 table.set_entry(i, PageEntry::from_usize(0)); 1586 // 释放子页表 1587 allocator.free_one(subtable.phys()); 1588 } 1589 } 1590 1591 return Some(result); 1592 } 1593 1594 impl<Arch, F: Debug> Debug for PageMapper<Arch, F> { 1595 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1596 f.debug_struct("PageMapper") 1597 .field("table_paddr", &self.table_paddr) 1598 .field("frame_allocator", &self.frame_allocator) 1599 .finish() 1600 } 1601 } 1602 1603 /// 页表刷新器的trait 1604 pub trait Flusher<Arch: MemoryManagementArch> { 1605 /// 取消对指定的page flusher的刷新 1606 fn consume(&mut self, flush: PageFlush<Arch>); 1607 } 1608 1609 /// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法, 1610 /// 否则会造成对页表的更改被忽略,这是不安全的 1611 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 1612 pub struct PageFlush<Arch: MemoryManagementArch> { 1613 virt: VirtAddr, 1614 phantom: PhantomData<Arch>, 1615 } 1616 1617 impl<Arch: MemoryManagementArch> PageFlush<Arch> { 1618 pub fn new(virt: VirtAddr) -> Self { 1619 return Self { 1620 virt, 1621 phantom: PhantomData, 1622 }; 1623 } 1624 1625 pub fn flush(self) { 1626 unsafe { Arch::invalidate_page(self.virt) }; 1627 } 1628 1629 /// 忽略掉这个刷新器 1630 pub unsafe fn ignore(self) { 1631 mem::forget(self); 1632 } 1633 } 1634 1635 impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> { 1636 fn drop(&mut self) { 1637 unsafe { 1638 MMArch::invalidate_page(self.virt); 1639 } 1640 } 1641 } 1642 1643 /// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法, 1644 /// 否则会造成对页表的更改被忽略,这是不安全的 1645 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 1646 pub struct PageFlushAll<Arch: MemoryManagementArch> { 1647 phantom: PhantomData<fn() -> Arch>, 1648 } 1649 1650 #[allow(dead_code)] 1651 impl<Arch: MemoryManagementArch> PageFlushAll<Arch> { 1652 pub fn new() -> Self { 1653 return Self { 1654 phantom: PhantomData, 1655 }; 1656 } 1657 1658 pub fn flush(self) { 1659 unsafe { Arch::invalidate_all() }; 1660 } 1661 1662 /// 忽略掉这个刷新器 1663 pub unsafe fn ignore(self) { 1664 mem::forget(self); 1665 } 1666 } 1667 1668 impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> { 1669 /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了) 1670 fn consume(&mut self, flush: PageFlush<Arch>) { 1671 unsafe { flush.ignore() }; 1672 } 1673 } 1674 1675 impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T { 1676 /// 允许一个flusher consume掉另一个flusher 1677 fn consume(&mut self, flush: PageFlush<Arch>) { 1678 <T as Flusher<Arch>>::consume(self, flush); 1679 } 1680 } 1681 1682 impl<Arch: MemoryManagementArch> Flusher<Arch> for () { 1683 fn consume(&mut self, _flush: PageFlush<Arch>) {} 1684 } 1685 1686 impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> { 1687 fn drop(&mut self) { 1688 unsafe { 1689 Arch::invalidate_all(); 1690 } 1691 } 1692 } 1693 1694 /// 未在当前CPU上激活的页表的刷新器 1695 /// 1696 /// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表 1697 /// 1698 /// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销) 1699 #[derive(Debug)] 1700 pub struct InactiveFlusher; 1701 1702 impl InactiveFlusher { 1703 pub fn new() -> Self { 1704 return Self {}; 1705 } 1706 } 1707 1708 impl Flusher<MMArch> for InactiveFlusher { 1709 fn consume(&mut self, flush: PageFlush<MMArch>) { 1710 unsafe { 1711 flush.ignore(); 1712 } 1713 } 1714 } 1715 1716 impl Drop for InactiveFlusher { 1717 fn drop(&mut self) { 1718 // 发送刷新页表的IPI 1719 send_ipi(IpiKind::FlushTLB, IpiTarget::Other); 1720 } 1721 } 1722 1723 /// # 把一个地址向下对齐到页大小 1724 pub fn round_down_to_page_size(addr: usize) -> usize { 1725 addr & !(MMArch::PAGE_SIZE - 1) 1726 } 1727 1728 /// # 把一个地址向上对齐到页大小 1729 pub fn round_up_to_page_size(addr: usize) -> usize { 1730 round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1) 1731 } 1732