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 use log::{error, info}; 12 13 use crate::{ 14 arch::{interrupt::ipi::send_ipi, MMArch}, 15 exception::ipi::{IpiKind, IpiTarget}, 16 ipc::shm::ShmId, 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 info!("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 info!("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 impl<Arch: MemoryManagementArch> Default for PageFlags<Arch> { 462 fn default() -> Self { 463 Self::new() 464 } 465 } 466 467 #[allow(dead_code)] 468 impl<Arch: MemoryManagementArch> PageFlags<Arch> { 469 #[inline(always)] 470 pub fn new() -> Self { 471 let mut r = unsafe { 472 Self::from_data( 473 Arch::ENTRY_FLAG_DEFAULT_PAGE 474 | Arch::ENTRY_FLAG_READONLY 475 | Arch::ENTRY_FLAG_NO_EXEC, 476 ) 477 }; 478 479 #[cfg(target_arch = "x86_64")] 480 { 481 if crate::arch::mm::X86_64MMArch::is_xd_reserved() { 482 r = r.set_execute(true); 483 } 484 } 485 486 return r; 487 } 488 489 /// 根据ProtFlags生成PageFlags 490 /// 491 /// ## 参数 492 /// 493 /// - prot_flags: 页的保护标志 494 /// - user: 用户空间是否可访问 495 pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> PageFlags<Arch> { 496 let flags: PageFlags<Arch> = PageFlags::new() 497 .set_user(user) 498 .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC)) 499 .set_write(prot_flags.contains(ProtFlags::PROT_WRITE)); 500 501 return flags; 502 } 503 504 #[inline(always)] 505 pub fn data(&self) -> usize { 506 self.data 507 } 508 509 #[inline(always)] 510 pub const unsafe fn from_data(data: usize) -> Self { 511 return Self { 512 data, 513 phantom: PhantomData, 514 }; 515 } 516 517 /// 为新页表的页表项设置默认值 518 /// 519 /// 默认值为: 520 /// - present 521 /// - read only 522 /// - kernel space 523 /// - no exec 524 #[inline(always)] 525 pub fn new_page_table(user: bool) -> Self { 526 return unsafe { 527 let r = { 528 #[cfg(target_arch = "x86_64")] 529 { 530 Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE) 531 } 532 533 #[cfg(target_arch = "riscv64")] 534 { 535 // riscv64指向下一级页表的页表项,不应设置R/W/X权限位 536 Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE) 537 } 538 }; 539 540 #[cfg(target_arch = "x86_64")] 541 { 542 if user { 543 r.set_user(true) 544 } else { 545 r 546 } 547 } 548 549 #[cfg(target_arch = "riscv64")] 550 { 551 r 552 } 553 }; 554 } 555 556 /// 取得当前页表项的所有权,更新当前页表项的标志位,并返回更新后的页表项。 557 /// 558 /// ## 参数 559 /// - flag 要更新的标志位的值 560 /// - value 如果为true,那么将flag对应的位设置为1,否则设置为0 561 /// 562 /// ## 返回值 563 /// 564 /// 更新后的页表项 565 #[inline(always)] 566 #[must_use] 567 pub fn update_flags(mut self, flag: usize, value: bool) -> Self { 568 if value { 569 self.data |= flag; 570 } else { 571 self.data &= !flag; 572 } 573 return self; 574 } 575 576 /// 判断当前页表项是否存在指定的flag(只有全部flag都存在才返回true) 577 #[inline(always)] 578 pub fn has_flag(&self, flag: usize) -> bool { 579 return self.data & flag == flag; 580 } 581 582 #[inline(always)] 583 pub fn present(&self) -> bool { 584 return self.has_flag(Arch::ENTRY_FLAG_PRESENT); 585 } 586 587 /// 设置当前页表项的权限 588 /// 589 /// @param value 如果为true,那么将当前页表项的权限设置为用户态可访问 590 #[must_use] 591 #[inline(always)] 592 pub fn set_user(self, value: bool) -> Self { 593 return self.update_flags(Arch::ENTRY_FLAG_USER, value); 594 } 595 596 /// 用户态是否可以访问当前页表项 597 #[inline(always)] 598 pub fn has_user(&self) -> bool { 599 return self.has_flag(Arch::ENTRY_FLAG_USER); 600 } 601 602 /// 设置当前页表项的可写性, 如果为true,那么将当前页表项的权限设置为可写, 否则设置为只读 603 /// 604 /// ## 返回值 605 /// 606 /// 更新后的页表项. 607 /// 608 /// **请注意,**本函数会取得当前页表项的所有权,因此返回的页表项不是原来的页表项 609 #[must_use] 610 #[inline(always)] 611 pub fn set_write(self, value: bool) -> Self { 612 #[cfg(target_arch = "x86_64")] 613 { 614 // 有的架构同时具有可写和不可写的标志位,因此需要同时更新 615 return self 616 .update_flags(Arch::ENTRY_FLAG_READONLY, !value) 617 .update_flags(Arch::ENTRY_FLAG_READWRITE, value); 618 } 619 620 #[cfg(target_arch = "riscv64")] 621 { 622 if value { 623 return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true); 624 } else { 625 return self 626 .update_flags(Arch::ENTRY_FLAG_READONLY, true) 627 .update_flags(Arch::ENTRY_FLAG_WRITEABLE, false); 628 } 629 } 630 } 631 632 /// 当前页表项是否可写 633 #[inline(always)] 634 pub fn has_write(&self) -> bool { 635 // 有的架构同时具有可写和不可写的标志位,因此需要同时判断 636 return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY) 637 == Arch::ENTRY_FLAG_READWRITE; 638 } 639 640 /// 设置当前页表项的可执行性, 如果为true,那么将当前页表项的权限设置为可执行, 否则设置为不可执行 641 #[must_use] 642 #[inline(always)] 643 pub fn set_execute(self, mut value: bool) -> Self { 644 #[cfg(target_arch = "x86_64")] 645 { 646 // 如果xd位被保留,那么将可执行性设置为true 647 if crate::arch::mm::X86_64MMArch::is_xd_reserved() { 648 value = true; 649 } 650 } 651 652 // 有的架构同时具有可执行和不可执行的标志位,因此需要同时更新 653 return self 654 .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value) 655 .update_flags(Arch::ENTRY_FLAG_EXEC, value); 656 } 657 658 /// 当前页表项是否可执行 659 #[inline(always)] 660 pub fn has_execute(&self) -> bool { 661 // 有的架构同时具有可执行和不可执行的标志位,因此需要同时判断 662 return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC) 663 == Arch::ENTRY_FLAG_EXEC; 664 } 665 666 /// 设置当前页表项的缓存策略 667 /// 668 /// ## 参数 669 /// 670 /// - value: 如果为true,那么将当前页表项的缓存策略设置为不缓存。 671 #[inline(always)] 672 pub fn set_page_cache_disable(self, value: bool) -> Self { 673 return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value); 674 } 675 676 /// 获取当前页表项的缓存策略 677 /// 678 /// ## 返回值 679 /// 680 /// 如果当前页表项的缓存策略为不缓存,那么返回true,否则返回false。 681 #[inline(always)] 682 pub fn has_page_cache_disable(&self) -> bool { 683 return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE); 684 } 685 686 /// 设置当前页表项的写穿策略 687 /// 688 /// ## 参数 689 /// 690 /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。 691 #[inline(always)] 692 pub fn set_page_write_through(self, value: bool) -> Self { 693 return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value); 694 } 695 696 #[inline(always)] 697 pub fn set_page_global(self, value: bool) -> Self { 698 return self.update_flags(MMArch::ENTRY_FLAG_GLOBAL, value); 699 } 700 701 /// 获取当前页表项的写穿策略 702 /// 703 /// ## 返回值 704 /// 705 /// 如果当前页表项的写穿策略为写穿,那么返回true,否则返回false。 706 #[inline(always)] 707 pub fn has_page_write_through(&self) -> bool { 708 return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH); 709 } 710 711 /// 设置当前页表是否为脏页 712 /// 713 /// ## 参数 714 /// 715 /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。 716 #[inline(always)] 717 pub fn set_dirty(self, value: bool) -> Self { 718 return self.update_flags(Arch::ENTRY_FLAG_DIRTY, value); 719 } 720 721 /// 设置当前页表被访问 722 /// 723 /// ## 参数 724 /// 725 /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。 726 #[inline(always)] 727 pub fn set_access(self, value: bool) -> Self { 728 return self.update_flags(Arch::ENTRY_FLAG_ACCESSED, value); 729 } 730 731 /// 设置指向的页是否为大页 732 /// 733 /// ## 参数 734 /// 735 /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。 736 #[inline(always)] 737 pub fn set_huge_page(self, value: bool) -> Self { 738 return self.update_flags(Arch::ENTRY_FLAG_HUGE_PAGE, value); 739 } 740 741 /// MMIO内存的页表项标志 742 #[inline(always)] 743 pub fn mmio_flags() -> Self { 744 #[cfg(target_arch = "x86_64")] 745 { 746 Self::new() 747 .set_user(false) 748 .set_write(true) 749 .set_execute(true) 750 .set_page_cache_disable(true) 751 .set_page_write_through(true) 752 .set_page_global(true) 753 } 754 755 #[cfg(target_arch = "riscv64")] 756 { 757 Self::new() 758 .set_user(false) 759 .set_write(true) 760 .set_execute(true) 761 .set_page_global(true) 762 } 763 } 764 } 765 766 impl<Arch: MemoryManagementArch> fmt::Debug for PageFlags<Arch> { 767 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 768 f.debug_struct("PageFlags") 769 .field("bits", &format_args!("{:#0x}", self.data)) 770 .field("present", &self.present()) 771 .field("has_write", &self.has_write()) 772 .field("has_execute", &self.has_execute()) 773 .field("has_user", &self.has_user()) 774 .finish() 775 } 776 } 777 778 /// 页表映射器 779 #[derive(Hash)] 780 pub struct PageMapper<Arch, F> { 781 /// 页表类型 782 table_kind: PageTableKind, 783 /// 根页表物理地址 784 table_paddr: PhysAddr, 785 /// 页分配器 786 frame_allocator: F, 787 phantom: PhantomData<fn() -> Arch>, 788 } 789 790 impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> { 791 /// 创建新的页面映射器 792 /// 793 /// ## 参数 794 /// - table_kind 页表类型 795 /// - table_paddr 根页表物理地址 796 /// - allocator 页分配器 797 /// 798 /// ## 返回值 799 /// 800 /// 页面映射器 801 pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self { 802 return Self { 803 table_kind, 804 table_paddr, 805 frame_allocator: allocator, 806 phantom: PhantomData, 807 }; 808 } 809 810 /// 创建页表,并为这个页表创建页面映射器 811 pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> { 812 let table_paddr = allocator.allocate_one()?; 813 // 清空页表 814 let table_vaddr = Arch::phys_2_virt(table_paddr)?; 815 Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE); 816 return Some(Self::new(table_kind, table_paddr, allocator)); 817 } 818 819 /// 获取当前页表的页面映射器 820 #[inline(always)] 821 pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self { 822 let table_paddr = Arch::table(table_kind); 823 return Self::new(table_kind, table_paddr, allocator); 824 } 825 826 /// 判断当前页表分配器所属的页表是否是当前页表 827 #[inline(always)] 828 pub fn is_current(&self) -> bool { 829 return unsafe { self.table().phys() == Arch::table(self.table_kind) }; 830 } 831 832 /// 将当前页表分配器所属的页表设置为当前页表 833 #[inline(always)] 834 pub unsafe fn make_current(&self) { 835 Arch::set_table(self.table_kind, self.table_paddr); 836 } 837 838 /// 获取当前页表分配器所属的根页表的结构体 839 #[inline(always)] 840 pub fn table(&self) -> PageTable<Arch> { 841 // 由于只能通过new方法创建PageMapper,因此这里假定table_paddr是有效的 842 return unsafe { 843 PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1) 844 }; 845 } 846 847 /// 获取当前PageMapper所对应的页分配器实例的引用 848 #[inline(always)] 849 #[allow(dead_code)] 850 pub fn allocator_ref(&self) -> &F { 851 return &self.frame_allocator; 852 } 853 854 /// 获取当前PageMapper所对应的页分配器实例的可变引用 855 #[inline(always)] 856 pub fn allocator_mut(&mut self) -> &mut F { 857 return &mut self.frame_allocator; 858 } 859 860 /// 从当前PageMapper的页分配器中分配一个物理页,并将其映射到指定的虚拟地址 861 pub unsafe fn map( 862 &mut self, 863 virt: VirtAddr, 864 flags: PageFlags<Arch>, 865 ) -> Option<PageFlush<Arch>> { 866 compiler_fence(Ordering::SeqCst); 867 let phys: PhysAddr = self.frame_allocator.allocate_one()?; 868 compiler_fence(Ordering::SeqCst); 869 870 unsafe { 871 let vaddr = MMArch::phys_2_virt(phys).unwrap(); 872 MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE); 873 } 874 875 let mut page_manager_guard: SpinLockGuard<'static, PageManager> = 876 page_manager_lock_irqsave(); 877 if !page_manager_guard.contains(&phys) { 878 page_manager_guard.insert(phys, Page::new(false)) 879 } 880 881 return self.map_phys(virt, phys, flags); 882 } 883 884 /// 映射一个物理页到指定的虚拟地址 885 pub unsafe fn map_phys( 886 &mut self, 887 virt: VirtAddr, 888 phys: PhysAddr, 889 flags: PageFlags<Arch>, 890 ) -> Option<PageFlush<Arch>> { 891 // 验证虚拟地址和物理地址是否对齐 892 if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) { 893 error!( 894 "Try to map unaligned page: virt={:?}, phys={:?}", 895 virt, phys 896 ); 897 return None; 898 } 899 900 let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 901 902 // TODO: 验证flags是否合法 903 904 // 创建页表项 905 let entry = PageEntry::new(phys, flags); 906 let mut table = self.table(); 907 loop { 908 let i = table.index_of(virt)?; 909 910 assert!(i < Arch::PAGE_ENTRY_NUM); 911 if table.level() == 0 { 912 compiler_fence(Ordering::SeqCst); 913 914 table.set_entry(i, entry); 915 compiler_fence(Ordering::SeqCst); 916 return Some(PageFlush::new(virt)); 917 } else { 918 let next_table = table.next_level_table(i); 919 if let Some(next_table) = next_table { 920 table = next_table; 921 // debug!("Mapping {:?} to next level table...", virt); 922 } else { 923 // 分配下一级页表 924 let frame = self.frame_allocator.allocate_one()?; 925 926 // 清空这个页帧 927 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 928 // 设置页表项的flags 929 let flags: PageFlags<Arch> = 930 PageFlags::new_page_table(virt.kind() == PageTableKind::User); 931 932 // 把新分配的页表映射到当前页表 933 table.set_entry(i, PageEntry::new(frame, flags)); 934 935 // 获取新分配的页表 936 table = table.next_level_table(i)?; 937 } 938 } 939 } 940 } 941 942 /// 进行大页映射 943 pub unsafe fn map_huge_page( 944 &mut self, 945 virt: VirtAddr, 946 flags: PageFlags<Arch>, 947 ) -> Option<PageFlush<Arch>> { 948 // 验证虚拟地址是否对齐 949 if !(virt.check_aligned(Arch::PAGE_SIZE)) { 950 error!("Try to map unaligned page: virt={:?}", virt); 951 return None; 952 } 953 954 let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 955 956 let mut table = self.table(); 957 loop { 958 let i = table.index_of(virt)?; 959 assert!(i < Arch::PAGE_ENTRY_NUM); 960 let next_table = table.next_level_table(i); 961 if let Some(next_table) = next_table { 962 table = next_table; 963 } else { 964 break; 965 } 966 } 967 968 // 支持2M、1G大页,即页表层级为1、2级的页表可以映射大页 969 if table.level == 0 || table.level > 2 { 970 return None; 971 } 972 973 let (phys, count) = self.frame_allocator.allocate(PageFrameCount::new( 974 Arch::PAGE_ENTRY_NUM.pow(table.level as u32), 975 ))?; 976 977 MMArch::write_bytes( 978 MMArch::phys_2_virt(phys).unwrap(), 979 0, 980 MMArch::PAGE_SIZE * count.data(), 981 ); 982 983 table.set_entry( 984 table.index_of(virt)?, 985 PageEntry::new(phys, flags.set_huge_page(true)), 986 )?; 987 Some(PageFlush::new(virt)) 988 } 989 990 /// 为虚拟地址分配指定层级的页表 991 /// ## 参数 992 /// 993 /// - `virt`: 虚拟地址 994 /// - `level`: 指定页表层级 995 /// 996 /// ## 返回值 997 /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表 998 /// - None: 对应页表不存在 999 pub unsafe fn allocate_table( 1000 &mut self, 1001 virt: VirtAddr, 1002 level: usize, 1003 ) -> Option<PageTable<Arch>> { 1004 let table = self.get_table(virt, level + 1)?; 1005 let i = table.index_of(virt)?; 1006 let frame = self.frame_allocator.allocate_one()?; 1007 1008 // 清空这个页帧 1009 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 1010 1011 // 设置页表项的flags 1012 let flags: PageFlags<Arch> = PageFlags::new_page_table(virt.kind() == PageTableKind::User); 1013 1014 table.set_entry(i, PageEntry::new(frame, flags)); 1015 table.next_level_table(i) 1016 } 1017 1018 /// 获取虚拟地址的指定层级页表 1019 /// ## 参数 1020 /// 1021 /// - `virt`: 虚拟地址 1022 /// - `level`: 指定页表层级 1023 /// 1024 /// ## 返回值 1025 /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表 1026 /// - None: 对应页表不存在 1027 pub fn get_table(&self, virt: VirtAddr, level: usize) -> Option<PageTable<Arch>> { 1028 let mut table = self.table(); 1029 if level > Arch::PAGE_LEVELS - 1 { 1030 return None; 1031 } 1032 1033 unsafe { 1034 loop { 1035 if table.level == level { 1036 return Some(table); 1037 } 1038 let i = table.index_of(virt)?; 1039 assert!(i < Arch::PAGE_ENTRY_NUM); 1040 1041 table = table.next_level_table(i)?; 1042 } 1043 } 1044 } 1045 1046 /// 获取虚拟地址在指定层级页表的PageEntry 1047 /// ## 参数 1048 /// 1049 /// - `virt`: 虚拟地址 1050 /// - `level`: 指定页表层级 1051 /// 1052 /// ## 返回值 1053 /// - Some(PageEntry<Arch>): 虚拟地址在指定层级的页表的有效PageEntry 1054 /// - None: 无对应的有效PageEntry 1055 pub fn get_entry(&self, virt: VirtAddr, level: usize) -> Option<PageEntry<Arch>> { 1056 let table = self.get_table(virt, level)?; 1057 let i = table.index_of(virt)?; 1058 let entry = unsafe { table.entry(i) }?; 1059 1060 if !entry.empty() { 1061 Some(entry) 1062 } else { 1063 None 1064 } 1065 1066 // let mut table = self.table(); 1067 // if level > Arch::PAGE_LEVELS - 1 { 1068 // return None; 1069 // } 1070 // unsafe { 1071 // loop { 1072 // let i = table.index_of(virt)?; 1073 // assert!(i < Arch::PAGE_ENTRY_NUM); 1074 1075 // if table.level == level { 1076 // let entry = table.entry(i)?; 1077 // if !entry.empty() { 1078 // return Some(entry); 1079 // } else { 1080 // return None; 1081 // } 1082 // } 1083 1084 // table = table.next_level_table(i)?; 1085 // } 1086 // } 1087 } 1088 1089 /// 拷贝用户空间映射 1090 /// ## 参数 1091 /// 1092 /// - `umapper`: 要拷贝的用户空间 1093 /// - `copy_on_write`: 是否写时复制 1094 pub unsafe fn clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool) { 1095 let old_table = umapper.table(); 1096 let new_table = self.table(); 1097 let allocator = self.allocator_mut(); 1098 // 顶级页表的[0, PAGE_KERNEL_INDEX)项为用户空间映射 1099 for entry_index in 0..Arch::PAGE_KERNEL_INDEX { 1100 if let Some(next_table) = old_table.next_level_table(entry_index) { 1101 let table = next_table.clone(allocator, copy_on_write).unwrap(); 1102 let old_entry = old_table.entry(entry_index).unwrap(); 1103 let entry = PageEntry::new(table.phys(), old_entry.flags()); 1104 new_table.set_entry(entry_index, entry); 1105 } 1106 } 1107 } 1108 1109 /// 将物理地址映射到具有线性偏移量的虚拟地址 1110 #[allow(dead_code)] 1111 pub unsafe fn map_linearly( 1112 &mut self, 1113 phys: PhysAddr, 1114 flags: PageFlags<Arch>, 1115 ) -> Option<(VirtAddr, PageFlush<Arch>)> { 1116 let virt: VirtAddr = Arch::phys_2_virt(phys)?; 1117 return self.map_phys(virt, phys, flags).map(|flush| (virt, flush)); 1118 } 1119 1120 /// 修改虚拟地址的页表项的flags,并返回页表项刷新器 1121 /// 1122 /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效 1123 /// 1124 /// ## 参数 1125 /// - virt 虚拟地址 1126 /// - flags 新的页表项的flags 1127 /// 1128 /// ## 返回值 1129 /// 1130 /// 如果修改成功,返回刷新器,否则返回None 1131 pub unsafe fn remap( 1132 &mut self, 1133 virt: VirtAddr, 1134 flags: PageFlags<Arch>, 1135 ) -> Option<PageFlush<Arch>> { 1136 return self 1137 .visit(virt, |p1, i| { 1138 let mut entry = p1.entry(i)?; 1139 1140 entry.set_flags(flags); 1141 p1.set_entry(i, entry); 1142 Some(PageFlush::new(virt)) 1143 }) 1144 .flatten(); 1145 } 1146 1147 /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags 1148 /// 1149 /// ## 参数 1150 /// 1151 /// - virt 虚拟地址 1152 /// 1153 /// ## 返回值 1154 /// 1155 /// 如果查找成功,返回物理地址和页表项的flags,否则返回None 1156 pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, PageFlags<Arch>)> { 1157 let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??; 1158 let paddr = entry.address().ok()?; 1159 let flags = entry.flags(); 1160 return Some((paddr, flags)); 1161 } 1162 1163 /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器 1164 /// 1165 /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效 1166 /// 1167 /// ## 参数 1168 /// 1169 /// - virt 虚拟地址 1170 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1171 /// 1172 /// ## 返回值 1173 /// 如果取消成功,返回刷新器,否则返回None 1174 #[allow(dead_code)] 1175 pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> { 1176 let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?; 1177 self.frame_allocator.free_one(paddr); 1178 return Some(flusher); 1179 } 1180 1181 /// 取消虚拟地址的映射,并返回物理地址和页表项的flags 1182 /// 1183 /// ## 参数 1184 /// 1185 /// - vaddr 虚拟地址 1186 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1187 /// 1188 /// ## 返回值 1189 /// 1190 /// 如果取消成功,返回物理地址和页表项的flags,否则返回None 1191 pub unsafe fn unmap_phys( 1192 &mut self, 1193 virt: VirtAddr, 1194 unmap_parents: bool, 1195 ) -> Option<(PhysAddr, PageFlags<Arch>, PageFlush<Arch>)> { 1196 if !virt.check_aligned(Arch::PAGE_SIZE) { 1197 error!("Try to unmap unaligned page: virt={:?}", virt); 1198 return None; 1199 } 1200 1201 let table = self.table(); 1202 return unmap_phys_inner(virt, &table, unmap_parents, self.allocator_mut()) 1203 .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt))); 1204 } 1205 1206 /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F 1207 fn visit<T>( 1208 &self, 1209 virt: VirtAddr, 1210 f: impl FnOnce(&mut PageTable<Arch>, usize) -> T, 1211 ) -> Option<T> { 1212 let mut table = self.table(); 1213 unsafe { 1214 loop { 1215 let i = table.index_of(virt)?; 1216 if table.level() == 0 { 1217 return Some(f(&mut table, i)); 1218 } else { 1219 table = table.next_level_table(i)?; 1220 } 1221 } 1222 } 1223 } 1224 } 1225 1226 /// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】 1227 /// 1228 /// ## 参数 1229 /// 1230 /// - vaddr 虚拟地址 1231 /// - table 页表 1232 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1233 /// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内) 1234 /// 1235 /// ## 返回值 1236 /// 1237 /// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None 1238 unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>( 1239 vaddr: VirtAddr, 1240 table: &PageTable<Arch>, 1241 unmap_parents: bool, 1242 allocator: &mut impl FrameAllocator, 1243 ) -> Option<(PhysAddr, PageFlags<Arch>)> { 1244 // 获取页表项的索引 1245 let i = table.index_of(vaddr)?; 1246 1247 // 如果当前是最后一级页表,直接取消页面映射 1248 if table.level() == 0 { 1249 let entry = table.entry(i)?; 1250 table.set_entry(i, PageEntry::from_usize(0)); 1251 return Some((entry.address().ok()?, entry.flags())); 1252 } 1253 1254 let subtable = table.next_level_table(i)?; 1255 // 递归地取消映射 1256 let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator)?; 1257 1258 // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables, 1259 // as these mappings may become out of sync 1260 if unmap_parents { 1261 // 如果子页表已经没有映射的页面了,就取消子页表的映射 1262 1263 // 检查子页表中是否还有映射的页面 1264 let x = (0..Arch::PAGE_ENTRY_NUM) 1265 .map(|k| subtable.entry(k).expect("invalid page entry")) 1266 .any(|e| e.present()); 1267 if !x { 1268 // 如果没有,就取消子页表的映射 1269 table.set_entry(i, PageEntry::from_usize(0)); 1270 // 释放子页表 1271 allocator.free_one(subtable.phys()); 1272 } 1273 } 1274 1275 return Some(result); 1276 } 1277 1278 impl<Arch, F: Debug> Debug for PageMapper<Arch, F> { 1279 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1280 f.debug_struct("PageMapper") 1281 .field("table_paddr", &self.table_paddr) 1282 .field("frame_allocator", &self.frame_allocator) 1283 .finish() 1284 } 1285 } 1286 1287 /// 页表刷新器的trait 1288 pub trait Flusher<Arch: MemoryManagementArch> { 1289 /// 取消对指定的page flusher的刷新 1290 fn consume(&mut self, flush: PageFlush<Arch>); 1291 } 1292 1293 /// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法, 1294 /// 否则会造成对页表的更改被忽略,这是不安全的 1295 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 1296 pub struct PageFlush<Arch: MemoryManagementArch> { 1297 virt: VirtAddr, 1298 phantom: PhantomData<Arch>, 1299 } 1300 1301 impl<Arch: MemoryManagementArch> PageFlush<Arch> { 1302 pub fn new(virt: VirtAddr) -> Self { 1303 return Self { 1304 virt, 1305 phantom: PhantomData, 1306 }; 1307 } 1308 1309 pub fn flush(self) { 1310 unsafe { Arch::invalidate_page(self.virt) }; 1311 } 1312 1313 /// 忽略掉这个刷新器 1314 pub unsafe fn ignore(self) { 1315 mem::forget(self); 1316 } 1317 } 1318 1319 impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> { 1320 fn drop(&mut self) { 1321 unsafe { 1322 MMArch::invalidate_page(self.virt); 1323 } 1324 } 1325 } 1326 1327 /// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法, 1328 /// 否则会造成对页表的更改被忽略,这是不安全的 1329 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 1330 pub struct PageFlushAll<Arch: MemoryManagementArch> { 1331 phantom: PhantomData<fn() -> Arch>, 1332 } 1333 1334 #[allow(dead_code)] 1335 impl<Arch: MemoryManagementArch> PageFlushAll<Arch> { 1336 pub fn new() -> Self { 1337 return Self { 1338 phantom: PhantomData, 1339 }; 1340 } 1341 1342 pub fn flush(self) { 1343 unsafe { Arch::invalidate_all() }; 1344 } 1345 1346 /// 忽略掉这个刷新器 1347 pub unsafe fn ignore(self) { 1348 mem::forget(self); 1349 } 1350 } 1351 1352 impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> { 1353 /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了) 1354 fn consume(&mut self, flush: PageFlush<Arch>) { 1355 unsafe { flush.ignore() }; 1356 } 1357 } 1358 1359 impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T { 1360 /// 允许一个flusher consume掉另一个flusher 1361 fn consume(&mut self, flush: PageFlush<Arch>) { 1362 <T as Flusher<Arch>>::consume(self, flush); 1363 } 1364 } 1365 1366 impl<Arch: MemoryManagementArch> Flusher<Arch> for () { 1367 fn consume(&mut self, _flush: PageFlush<Arch>) {} 1368 } 1369 1370 impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> { 1371 fn drop(&mut self) { 1372 unsafe { 1373 Arch::invalidate_all(); 1374 } 1375 } 1376 } 1377 1378 /// 未在当前CPU上激活的页表的刷新器 1379 /// 1380 /// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表 1381 /// 1382 /// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销) 1383 #[derive(Debug)] 1384 pub struct InactiveFlusher; 1385 1386 impl InactiveFlusher { 1387 pub fn new() -> Self { 1388 return Self {}; 1389 } 1390 } 1391 1392 impl Flusher<MMArch> for InactiveFlusher { 1393 fn consume(&mut self, flush: PageFlush<MMArch>) { 1394 unsafe { 1395 flush.ignore(); 1396 } 1397 } 1398 } 1399 1400 impl Drop for InactiveFlusher { 1401 fn drop(&mut self) { 1402 // 发送刷新页表的IPI 1403 send_ipi(IpiKind::FlushTLB, IpiTarget::Other); 1404 } 1405 } 1406 1407 /// # 把一个地址向下对齐到页大小 1408 pub fn round_down_to_page_size(addr: usize) -> usize { 1409 addr & !(MMArch::PAGE_SIZE - 1) 1410 } 1411 1412 /// # 把一个地址向上对齐到页大小 1413 pub fn round_up_to_page_size(addr: usize) -> usize { 1414 round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1) 1415 } 1416