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