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 #[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 unsafe { 865 let vaddr = MMArch::phys_2_virt(phys).unwrap(); 866 MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE); 867 } 868 869 let mut page_manager_guard: SpinLockGuard<'static, PageManager> = 870 page_manager_lock_irqsave(); 871 if !page_manager_guard.contains(&phys) { 872 page_manager_guard.insert(phys, Page::new(false)) 873 } 874 875 return self.map_phys(virt, phys, flags); 876 } 877 878 /// 映射一个物理页到指定的虚拟地址 879 pub unsafe fn map_phys( 880 &mut self, 881 virt: VirtAddr, 882 phys: PhysAddr, 883 flags: PageFlags<Arch>, 884 ) -> Option<PageFlush<Arch>> { 885 // 验证虚拟地址和物理地址是否对齐 886 if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) { 887 error!( 888 "Try to map unaligned page: virt={:?}, phys={:?}", 889 virt, phys 890 ); 891 return None; 892 } 893 894 let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 895 896 // TODO: 验证flags是否合法 897 898 // 创建页表项 899 let entry = PageEntry::new(phys, flags); 900 let mut table = self.table(); 901 loop { 902 let i = table.index_of(virt)?; 903 904 assert!(i < Arch::PAGE_ENTRY_NUM); 905 if table.level() == 0 { 906 compiler_fence(Ordering::SeqCst); 907 908 table.set_entry(i, entry); 909 compiler_fence(Ordering::SeqCst); 910 return Some(PageFlush::new(virt)); 911 } else { 912 let next_table = table.next_level_table(i); 913 if let Some(next_table) = next_table { 914 table = next_table; 915 // debug!("Mapping {:?} to next level table...", virt); 916 } else { 917 // 分配下一级页表 918 let frame = self.frame_allocator.allocate_one()?; 919 920 // 清空这个页帧 921 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 922 // 设置页表项的flags 923 let flags: PageFlags<Arch> = 924 PageFlags::new_page_table(virt.kind() == PageTableKind::User); 925 926 // 把新分配的页表映射到当前页表 927 table.set_entry(i, PageEntry::new(frame, flags)); 928 929 // 获取新分配的页表 930 table = table.next_level_table(i)?; 931 } 932 } 933 } 934 } 935 936 /// 进行大页映射 937 pub unsafe fn map_huge_page( 938 &mut self, 939 virt: VirtAddr, 940 flags: PageFlags<Arch>, 941 ) -> Option<PageFlush<Arch>> { 942 // 验证虚拟地址是否对齐 943 if !(virt.check_aligned(Arch::PAGE_SIZE)) { 944 error!("Try to map unaligned page: virt={:?}", virt); 945 return None; 946 } 947 948 let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK)); 949 950 let mut table = self.table(); 951 loop { 952 let i = table.index_of(virt)?; 953 assert!(i < Arch::PAGE_ENTRY_NUM); 954 let next_table = table.next_level_table(i); 955 if let Some(next_table) = next_table { 956 table = next_table; 957 } else { 958 break; 959 } 960 } 961 962 // 支持2M、1G大页,即页表层级为1、2级的页表可以映射大页 963 if table.level == 0 || table.level > 2 { 964 return None; 965 } 966 967 let (phys, count) = self.frame_allocator.allocate(PageFrameCount::new( 968 Arch::PAGE_ENTRY_NUM.pow(table.level as u32), 969 ))?; 970 971 MMArch::write_bytes( 972 MMArch::phys_2_virt(phys).unwrap(), 973 0, 974 MMArch::PAGE_SIZE * count.data(), 975 ); 976 977 table.set_entry( 978 table.index_of(virt)?, 979 PageEntry::new(phys, flags.set_huge_page(true)), 980 )?; 981 Some(PageFlush::new(virt)) 982 } 983 984 /// 为虚拟地址分配指定层级的页表 985 /// ## 参数 986 /// 987 /// - `virt`: 虚拟地址 988 /// - `level`: 指定页表层级 989 /// 990 /// ## 返回值 991 /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表 992 /// - None: 对应页表不存在 993 pub unsafe fn allocate_table( 994 &mut self, 995 virt: VirtAddr, 996 level: usize, 997 ) -> Option<PageTable<Arch>> { 998 let table = self.get_table(virt, level + 1)?; 999 let i = table.index_of(virt)?; 1000 let frame = self.frame_allocator.allocate_one()?; 1001 1002 // 清空这个页帧 1003 MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE); 1004 1005 // 设置页表项的flags 1006 let flags: PageFlags<Arch> = PageFlags::new_page_table(virt.kind() == PageTableKind::User); 1007 1008 table.set_entry(i, PageEntry::new(frame, flags)); 1009 table.next_level_table(i) 1010 } 1011 1012 /// 获取虚拟地址的指定层级页表 1013 /// ## 参数 1014 /// 1015 /// - `virt`: 虚拟地址 1016 /// - `level`: 指定页表层级 1017 /// 1018 /// ## 返回值 1019 /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表 1020 /// - None: 对应页表不存在 1021 pub fn get_table(&self, virt: VirtAddr, level: usize) -> Option<PageTable<Arch>> { 1022 let mut table = self.table(); 1023 if level > Arch::PAGE_LEVELS - 1 { 1024 return None; 1025 } 1026 1027 unsafe { 1028 loop { 1029 if table.level == level { 1030 return Some(table); 1031 } 1032 let i = table.index_of(virt)?; 1033 assert!(i < Arch::PAGE_ENTRY_NUM); 1034 1035 table = table.next_level_table(i)?; 1036 } 1037 } 1038 } 1039 1040 /// 获取虚拟地址在指定层级页表的PageEntry 1041 /// ## 参数 1042 /// 1043 /// - `virt`: 虚拟地址 1044 /// - `level`: 指定页表层级 1045 /// 1046 /// ## 返回值 1047 /// - Some(PageEntry<Arch>): 虚拟地址在指定层级的页表的有效PageEntry 1048 /// - None: 无对应的有效PageEntry 1049 pub fn get_entry(&self, virt: VirtAddr, level: usize) -> Option<PageEntry<Arch>> { 1050 let table = self.get_table(virt, level)?; 1051 let i = table.index_of(virt)?; 1052 let entry = unsafe { table.entry(i) }?; 1053 1054 if !entry.empty() { 1055 Some(entry) 1056 } else { 1057 None 1058 } 1059 1060 // let mut table = self.table(); 1061 // if level > Arch::PAGE_LEVELS - 1 { 1062 // return None; 1063 // } 1064 // unsafe { 1065 // loop { 1066 // let i = table.index_of(virt)?; 1067 // assert!(i < Arch::PAGE_ENTRY_NUM); 1068 1069 // if table.level == level { 1070 // let entry = table.entry(i)?; 1071 // if !entry.empty() { 1072 // return Some(entry); 1073 // } else { 1074 // return None; 1075 // } 1076 // } 1077 1078 // table = table.next_level_table(i)?; 1079 // } 1080 // } 1081 } 1082 1083 /// 拷贝用户空间映射 1084 /// ## 参数 1085 /// 1086 /// - `umapper`: 要拷贝的用户空间 1087 /// - `copy_on_write`: 是否写时复制 1088 pub unsafe fn clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool) { 1089 let old_table = umapper.table(); 1090 let new_table = self.table(); 1091 let allocator = self.allocator_mut(); 1092 // 顶级页表的[0, PAGE_KERNEL_INDEX)项为用户空间映射 1093 for entry_index in 0..Arch::PAGE_KERNEL_INDEX { 1094 if let Some(next_table) = old_table.next_level_table(entry_index) { 1095 let table = next_table.clone(allocator, copy_on_write).unwrap(); 1096 let old_entry = old_table.entry(entry_index).unwrap(); 1097 let entry = PageEntry::new(table.phys(), old_entry.flags()); 1098 new_table.set_entry(entry_index, entry); 1099 } 1100 } 1101 } 1102 1103 /// 将物理地址映射到具有线性偏移量的虚拟地址 1104 #[allow(dead_code)] 1105 pub unsafe fn map_linearly( 1106 &mut self, 1107 phys: PhysAddr, 1108 flags: PageFlags<Arch>, 1109 ) -> Option<(VirtAddr, PageFlush<Arch>)> { 1110 let virt: VirtAddr = Arch::phys_2_virt(phys)?; 1111 return self.map_phys(virt, phys, flags).map(|flush| (virt, flush)); 1112 } 1113 1114 /// 修改虚拟地址的页表项的flags,并返回页表项刷新器 1115 /// 1116 /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效 1117 /// 1118 /// ## 参数 1119 /// - virt 虚拟地址 1120 /// - flags 新的页表项的flags 1121 /// 1122 /// ## 返回值 1123 /// 1124 /// 如果修改成功,返回刷新器,否则返回None 1125 pub unsafe fn remap( 1126 &mut self, 1127 virt: VirtAddr, 1128 flags: PageFlags<Arch>, 1129 ) -> Option<PageFlush<Arch>> { 1130 return self 1131 .visit(virt, |p1, i| { 1132 let mut entry = p1.entry(i)?; 1133 1134 entry.set_flags(flags); 1135 p1.set_entry(i, entry); 1136 Some(PageFlush::new(virt)) 1137 }) 1138 .flatten(); 1139 } 1140 1141 /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags 1142 /// 1143 /// ## 参数 1144 /// 1145 /// - virt 虚拟地址 1146 /// 1147 /// ## 返回值 1148 /// 1149 /// 如果查找成功,返回物理地址和页表项的flags,否则返回None 1150 pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, PageFlags<Arch>)> { 1151 let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??; 1152 let paddr = entry.address().ok()?; 1153 let flags = entry.flags(); 1154 return Some((paddr, flags)); 1155 } 1156 1157 /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器 1158 /// 1159 /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效 1160 /// 1161 /// ## 参数 1162 /// 1163 /// - virt 虚拟地址 1164 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1165 /// 1166 /// ## 返回值 1167 /// 如果取消成功,返回刷新器,否则返回None 1168 #[allow(dead_code)] 1169 pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> { 1170 let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?; 1171 self.frame_allocator.free_one(paddr); 1172 return Some(flusher); 1173 } 1174 1175 /// 取消虚拟地址的映射,并返回物理地址和页表项的flags 1176 /// 1177 /// ## 参数 1178 /// 1179 /// - vaddr 虚拟地址 1180 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1181 /// 1182 /// ## 返回值 1183 /// 1184 /// 如果取消成功,返回物理地址和页表项的flags,否则返回None 1185 pub unsafe fn unmap_phys( 1186 &mut self, 1187 virt: VirtAddr, 1188 unmap_parents: bool, 1189 ) -> Option<(PhysAddr, PageFlags<Arch>, PageFlush<Arch>)> { 1190 if !virt.check_aligned(Arch::PAGE_SIZE) { 1191 error!("Try to unmap unaligned page: virt={:?}", virt); 1192 return None; 1193 } 1194 1195 let table = self.table(); 1196 return unmap_phys_inner(virt, &table, unmap_parents, self.allocator_mut()) 1197 .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt))); 1198 } 1199 1200 /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F 1201 fn visit<T>( 1202 &self, 1203 virt: VirtAddr, 1204 f: impl FnOnce(&mut PageTable<Arch>, usize) -> T, 1205 ) -> Option<T> { 1206 let mut table = self.table(); 1207 unsafe { 1208 loop { 1209 let i = table.index_of(virt)?; 1210 if table.level() == 0 { 1211 return Some(f(&mut table, i)); 1212 } else { 1213 table = table.next_level_table(i)?; 1214 } 1215 } 1216 } 1217 } 1218 } 1219 1220 /// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】 1221 /// 1222 /// ## 参数 1223 /// 1224 /// - vaddr 虚拟地址 1225 /// - table 页表 1226 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射 1227 /// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内) 1228 /// 1229 /// ## 返回值 1230 /// 1231 /// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None 1232 unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>( 1233 vaddr: VirtAddr, 1234 table: &PageTable<Arch>, 1235 unmap_parents: bool, 1236 allocator: &mut impl FrameAllocator, 1237 ) -> Option<(PhysAddr, PageFlags<Arch>)> { 1238 // 获取页表项的索引 1239 let i = table.index_of(vaddr)?; 1240 1241 // 如果当前是最后一级页表,直接取消页面映射 1242 if table.level() == 0 { 1243 let entry = table.entry(i)?; 1244 table.set_entry(i, PageEntry::from_usize(0)); 1245 return Some((entry.address().ok()?, entry.flags())); 1246 } 1247 1248 let subtable = table.next_level_table(i)?; 1249 // 递归地取消映射 1250 let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator)?; 1251 1252 // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables, 1253 // as these mappings may become out of sync 1254 if unmap_parents { 1255 // 如果子页表已经没有映射的页面了,就取消子页表的映射 1256 1257 // 检查子页表中是否还有映射的页面 1258 let x = (0..Arch::PAGE_ENTRY_NUM) 1259 .map(|k| subtable.entry(k).expect("invalid page entry")) 1260 .any(|e| e.present()); 1261 if !x { 1262 // 如果没有,就取消子页表的映射 1263 table.set_entry(i, PageEntry::from_usize(0)); 1264 // 释放子页表 1265 allocator.free_one(subtable.phys()); 1266 } 1267 } 1268 1269 return Some(result); 1270 } 1271 1272 impl<Arch, F: Debug> Debug for PageMapper<Arch, F> { 1273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 1274 f.debug_struct("PageMapper") 1275 .field("table_paddr", &self.table_paddr) 1276 .field("frame_allocator", &self.frame_allocator) 1277 .finish() 1278 } 1279 } 1280 1281 /// 页表刷新器的trait 1282 pub trait Flusher<Arch: MemoryManagementArch> { 1283 /// 取消对指定的page flusher的刷新 1284 fn consume(&mut self, flush: PageFlush<Arch>); 1285 } 1286 1287 /// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法, 1288 /// 否则会造成对页表的更改被忽略,这是不安全的 1289 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 1290 pub struct PageFlush<Arch: MemoryManagementArch> { 1291 virt: VirtAddr, 1292 phantom: PhantomData<Arch>, 1293 } 1294 1295 impl<Arch: MemoryManagementArch> PageFlush<Arch> { 1296 pub fn new(virt: VirtAddr) -> Self { 1297 return Self { 1298 virt, 1299 phantom: PhantomData, 1300 }; 1301 } 1302 1303 pub fn flush(self) { 1304 unsafe { Arch::invalidate_page(self.virt) }; 1305 } 1306 1307 /// 忽略掉这个刷新器 1308 pub unsafe fn ignore(self) { 1309 mem::forget(self); 1310 } 1311 } 1312 1313 impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> { 1314 fn drop(&mut self) { 1315 unsafe { 1316 MMArch::invalidate_page(self.virt); 1317 } 1318 } 1319 } 1320 1321 /// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法, 1322 /// 否则会造成对页表的更改被忽略,这是不安全的 1323 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."] 1324 pub struct PageFlushAll<Arch: MemoryManagementArch> { 1325 phantom: PhantomData<fn() -> Arch>, 1326 } 1327 1328 #[allow(dead_code)] 1329 impl<Arch: MemoryManagementArch> PageFlushAll<Arch> { 1330 pub fn new() -> Self { 1331 return Self { 1332 phantom: PhantomData, 1333 }; 1334 } 1335 1336 pub fn flush(self) { 1337 unsafe { Arch::invalidate_all() }; 1338 } 1339 1340 /// 忽略掉这个刷新器 1341 pub unsafe fn ignore(self) { 1342 mem::forget(self); 1343 } 1344 } 1345 1346 impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> { 1347 /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了) 1348 fn consume(&mut self, flush: PageFlush<Arch>) { 1349 unsafe { flush.ignore() }; 1350 } 1351 } 1352 1353 impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T { 1354 /// 允许一个flusher consume掉另一个flusher 1355 fn consume(&mut self, flush: PageFlush<Arch>) { 1356 <T as Flusher<Arch>>::consume(self, flush); 1357 } 1358 } 1359 1360 impl<Arch: MemoryManagementArch> Flusher<Arch> for () { 1361 fn consume(&mut self, _flush: PageFlush<Arch>) {} 1362 } 1363 1364 impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> { 1365 fn drop(&mut self) { 1366 unsafe { 1367 Arch::invalidate_all(); 1368 } 1369 } 1370 } 1371 1372 /// 未在当前CPU上激活的页表的刷新器 1373 /// 1374 /// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表 1375 /// 1376 /// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销) 1377 #[derive(Debug)] 1378 pub struct InactiveFlusher; 1379 1380 impl InactiveFlusher { 1381 pub fn new() -> Self { 1382 return Self {}; 1383 } 1384 } 1385 1386 impl Flusher<MMArch> for InactiveFlusher { 1387 fn consume(&mut self, flush: PageFlush<MMArch>) { 1388 unsafe { 1389 flush.ignore(); 1390 } 1391 } 1392 } 1393 1394 impl Drop for InactiveFlusher { 1395 fn drop(&mut self) { 1396 // 发送刷新页表的IPI 1397 send_ipi(IpiKind::FlushTLB, IpiTarget::Other); 1398 } 1399 } 1400 1401 /// # 把一个地址向下对齐到页大小 1402 pub fn round_down_to_page_size(addr: usize) -> usize { 1403 addr & !(MMArch::PAGE_SIZE - 1) 1404 } 1405 1406 /// # 把一个地址向上对齐到页大小 1407 pub fn round_up_to_page_size(addr: usize) -> usize { 1408 round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1) 1409 } 1410