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