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