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