xref: /DragonOS/kernel/src/mm/page.rs (revision 9430523b465b19db4dd476e9fd3038bdc2aa0c8d)
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     kerror, kwarn,
16     libs::spinlock::{SpinLock, SpinLockGuard},
17 };
18 
19 use super::{
20     allocator::page_frame::FrameAllocator, syscall::ProtFlags, ucontext::LockedVMA,
21     MemoryManagementArch, PageTableKind, PhysAddr, VirtAddr,
22 };
23 
24 /// 全局物理页信息管理器
25 pub static mut PAGE_MANAGER: Option<SpinLock<PageManager>> = None;
26 
27 /// 初始化PAGE_MANAGER
28 pub fn page_manager_init() {
29     kinfo!("page_manager_init");
30     let page_manager = SpinLock::new(PageManager::new());
31 
32     compiler_fence(Ordering::SeqCst);
33     unsafe { PAGE_MANAGER = Some(page_manager) };
34     compiler_fence(Ordering::SeqCst);
35 
36     kinfo!("page_manager_init done");
37 }
38 
39 pub fn page_manager_lock_irasave() -> SpinLockGuard<'static, PageManager> {
40     unsafe { PAGE_MANAGER.as_ref().unwrap().lock_irqsave() }
41 }
42 
43 // 物理页管理器
44 pub struct PageManager {
45     phys2page: HashMap<PhysAddr, Page>,
46 }
47 
48 impl PageManager {
49     pub fn new() -> Self {
50         Self {
51             phys2page: HashMap::new(),
52         }
53     }
54 
55     pub fn get_mut(&mut self, paddr: &PhysAddr) -> &mut Page {
56         self.phys2page.get_mut(paddr).unwrap()
57     }
58 
59     pub fn insert(&mut self, paddr: PhysAddr, page: Page) {
60         self.phys2page.insert(paddr, page);
61     }
62 
63     pub fn remove_page(&mut self, paddr: &PhysAddr) {
64         self.phys2page.remove(paddr);
65     }
66 }
67 
68 /// 物理页面信息
69 pub struct Page {
70     /// 映射计数
71     map_count: usize,
72     /// 是否为共享页
73     shared: bool,
74     /// 映射到当前page的VMA
75     anon_vma: HashSet<Arc<LockedVMA>>,
76 }
77 
78 impl Page {
79     pub fn new(shared: bool) -> Self {
80         Self {
81             map_count: 0,
82             shared,
83             anon_vma: HashSet::new(),
84         }
85     }
86 
87     /// 将vma加入anon_vma
88     pub fn insert_vma(&mut self, vma: Arc<LockedVMA>) {
89         self.anon_vma.insert(vma);
90         self.map_count += 1;
91     }
92 
93     /// 将vma从anon_vma中删去
94     pub fn remove_vma(&mut self, vma: &LockedVMA) {
95         self.anon_vma.remove(vma);
96         self.map_count -= 1;
97     }
98 
99     /// 判断当前物理页是否能被回
100     pub fn can_deallocate(&self) -> bool {
101         self.map_count == 0 && !self.shared
102     }
103 }
104 
105 #[derive(Debug)]
106 pub struct PageTable<Arch> {
107     /// 当前页表表示的虚拟地址空间的起始地址
108     base: VirtAddr,
109     /// 当前页表所在的物理地址
110     phys: PhysAddr,
111     /// 当前页表的层级(请注意,最顶级页表的level为[Arch::PAGE_LEVELS - 1])
112     level: usize,
113     phantom: PhantomData<Arch>,
114 }
115 
116 #[allow(dead_code)]
117 impl<Arch: MemoryManagementArch> PageTable<Arch> {
118     pub unsafe fn new(base: VirtAddr, phys: PhysAddr, level: usize) -> Self {
119         Self {
120             base,
121             phys,
122             level,
123             phantom: PhantomData,
124         }
125     }
126 
127     /// 获取顶级页表
128     ///
129     /// ## 参数
130     ///
131     /// - table_kind 页表类型
132     ///
133     /// ## 返回值
134     ///
135     /// 返回顶级页表
136     pub unsafe fn top_level_table(table_kind: PageTableKind) -> Self {
137         return Self::new(
138             VirtAddr::new(0),
139             Arch::table(table_kind),
140             Arch::PAGE_LEVELS - 1,
141         );
142     }
143 
144     /// 获取当前页表的物理地址
145     #[inline(always)]
146     pub fn phys(&self) -> PhysAddr {
147         self.phys
148     }
149 
150     /// 当前页表表示的虚拟地址空间的起始地址
151     #[inline(always)]
152     pub fn base(&self) -> VirtAddr {
153         self.base
154     }
155 
156     /// 获取当前页表的层级
157     #[inline(always)]
158     pub fn level(&self) -> usize {
159         self.level
160     }
161 
162     /// 获取当前页表自身所在的虚拟地址
163     #[inline(always)]
164     pub unsafe fn virt(&self) -> VirtAddr {
165         return Arch::phys_2_virt(self.phys).unwrap();
166     }
167 
168     /// 获取第i个页表项所表示的虚拟内存空间的起始地址
169     pub fn entry_base(&self, i: usize) -> Option<VirtAddr> {
170         if i < Arch::PAGE_ENTRY_NUM {
171             let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT;
172             return Some(self.base.add(i << shift));
173         } else {
174             return None;
175         }
176     }
177 
178     /// 获取当前页表的第i个页表项所在的虚拟地址(注意与entry_base进行区分)
179     pub unsafe fn entry_virt(&self, i: usize) -> Option<VirtAddr> {
180         if i < Arch::PAGE_ENTRY_NUM {
181             return Some(self.virt().add(i * Arch::PAGE_ENTRY_SIZE));
182         } else {
183             return None;
184         }
185     }
186 
187     /// 获取当前页表的第i个页表项
188     pub unsafe fn entry(&self, i: usize) -> Option<PageEntry<Arch>> {
189         let entry_virt = self.entry_virt(i)?;
190         return Some(PageEntry::from_usize(Arch::read::<usize>(entry_virt)));
191     }
192 
193     /// 设置当前页表的第i个页表项
194     pub unsafe fn set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()> {
195         let entry_virt = self.entry_virt(i)?;
196         Arch::write::<usize>(entry_virt, entry.data());
197         return Some(());
198     }
199 
200     /// 判断当前页表的第i个页表项是否已经填写了值
201     ///
202     /// ## 参数
203     /// - Some(true) 如果已经填写了值
204     /// - Some(false) 如果未填写值
205     /// - None 如果i超出了页表项的范围
206     pub fn entry_mapped(&self, i: usize) -> Option<bool> {
207         let etv = unsafe { self.entry_virt(i) }?;
208         if unsafe { Arch::read::<usize>(etv) } != 0 {
209             return Some(true);
210         } else {
211             return Some(false);
212         }
213     }
214 
215     /// 根据虚拟地址,获取对应的页表项在页表中的下标
216     ///
217     /// ## 参数
218     ///
219     /// - addr: 虚拟地址
220     ///
221     /// ## 返回值
222     ///
223     /// 页表项在页表中的下标。如果addr不在当前页表所表示的虚拟地址空间中,则返回None
224     pub unsafe fn index_of(&self, addr: VirtAddr) -> Option<usize> {
225         let addr = VirtAddr::new(addr.data() & Arch::PAGE_ADDRESS_MASK);
226         let shift = self.level * Arch::PAGE_ENTRY_SHIFT + Arch::PAGE_SHIFT;
227 
228         let mask = (MMArch::PAGE_ENTRY_NUM << shift) - 1;
229         if addr < self.base || addr >= self.base.add(mask) {
230             return None;
231         } else {
232             return Some((addr.data() >> shift) & MMArch::PAGE_ENTRY_MASK);
233         }
234     }
235 
236     /// 获取第i个页表项指向的下一级页表
237     pub unsafe fn next_level_table(&self, index: usize) -> Option<Self> {
238         if self.level == 0 {
239             return None;
240         }
241 
242         // 返回下一级页表
243         return Some(PageTable::new(
244             self.entry_base(index)?,
245             self.entry(index)?.address().ok()?,
246             self.level - 1,
247         ));
248     }
249 }
250 
251 /// 页表项
252 #[derive(Copy, Clone)]
253 pub struct PageEntry<Arch> {
254     data: usize,
255     phantom: PhantomData<Arch>,
256 }
257 
258 impl<Arch> Debug for PageEntry<Arch> {
259     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
260         f.write_fmt(format_args!("PageEntry({:#x})", self.data))
261     }
262 }
263 
264 impl<Arch: MemoryManagementArch> PageEntry<Arch> {
265     #[inline(always)]
266     pub fn new(paddr: PhysAddr, flags: PageFlags<Arch>) -> Self {
267         Self {
268             data: MMArch::make_entry(paddr, flags.data()),
269             phantom: PhantomData,
270         }
271     }
272     #[inline(always)]
273     pub fn from_usize(data: usize) -> Self {
274         Self {
275             data,
276             phantom: PhantomData,
277         }
278     }
279 
280     #[inline(always)]
281     pub fn data(&self) -> usize {
282         self.data
283     }
284 
285     /// 获取当前页表项指向的物理地址
286     ///
287     /// ## 返回值
288     ///
289     /// - Ok(PhysAddr) 如果当前页面存在于物理内存中, 返回物理地址
290     /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址
291     #[inline(always)]
292     pub fn address(&self) -> Result<PhysAddr, PhysAddr> {
293         let paddr: PhysAddr = {
294             #[cfg(target_arch = "x86_64")]
295             {
296                 PhysAddr::new(self.data & Arch::PAGE_ADDRESS_MASK)
297             }
298 
299             #[cfg(target_arch = "riscv64")]
300             {
301                 let ppn = ((self.data & (!((1 << 10) - 1))) >> 10) & ((1 << 54) - 1);
302                 super::allocator::page_frame::PhysPageFrame::from_ppn(ppn).phys_address()
303             }
304         };
305 
306         if self.present() {
307             Ok(paddr)
308         } else {
309             Err(paddr)
310         }
311     }
312 
313     #[inline(always)]
314     pub fn flags(&self) -> PageFlags<Arch> {
315         unsafe { PageFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) }
316     }
317 
318     #[inline(always)]
319     pub fn set_flags(&mut self, flags: PageFlags<Arch>) {
320         self.data = (self.data & !Arch::ENTRY_FLAGS_MASK) | flags.data();
321     }
322 
323     #[inline(always)]
324     pub fn present(&self) -> bool {
325         return self.data & Arch::ENTRY_FLAG_PRESENT != 0;
326     }
327 }
328 
329 /// 页表项的标志位
330 #[derive(Copy, Clone, Hash)]
331 pub struct PageFlags<Arch> {
332     data: usize,
333     phantom: PhantomData<Arch>,
334 }
335 
336 #[allow(dead_code)]
337 impl<Arch: MemoryManagementArch> PageFlags<Arch> {
338     #[inline(always)]
339     pub fn new() -> Self {
340         let mut r = unsafe {
341             Self::from_data(
342                 Arch::ENTRY_FLAG_DEFAULT_PAGE
343                     | Arch::ENTRY_FLAG_READONLY
344                     | Arch::ENTRY_FLAG_NO_EXEC,
345             )
346         };
347 
348         #[cfg(target_arch = "x86_64")]
349         {
350             if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
351                 r = r.set_execute(true);
352             }
353         }
354 
355         return r;
356     }
357 
358     /// 根据ProtFlags生成PageFlags
359     ///
360     /// ## 参数
361     ///
362     /// - prot_flags: 页的保护标志
363     /// - user: 用户空间是否可访问
364     pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> PageFlags<Arch> {
365         let flags: PageFlags<Arch> = PageFlags::new()
366             .set_user(user)
367             .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
368             .set_write(prot_flags.contains(ProtFlags::PROT_WRITE));
369 
370         return flags;
371     }
372 
373     #[inline(always)]
374     pub fn data(&self) -> usize {
375         self.data
376     }
377 
378     #[inline(always)]
379     pub const unsafe fn from_data(data: usize) -> Self {
380         return Self {
381             data,
382             phantom: PhantomData,
383         };
384     }
385 
386     /// 为新页表的页表项设置默认值
387     ///
388     /// 默认值为:
389     /// - present
390     /// - read only
391     /// - kernel space
392     /// - no exec
393     #[inline(always)]
394     pub fn new_page_table(user: bool) -> Self {
395         return unsafe {
396             let r = {
397                 #[cfg(target_arch = "x86_64")]
398                 {
399                     Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE)
400                 }
401 
402                 #[cfg(target_arch = "riscv64")]
403                 {
404                     // riscv64指向下一级页表的页表项,不应设置R/W/X权限位
405                     Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE)
406                 }
407             };
408             if user {
409                 r.set_user(true)
410             } else {
411                 r
412             }
413         };
414     }
415 
416     /// 取得当前页表项的所有权,更新当前页表项的标志位,并返回更新后的页表项。
417     ///
418     /// ## 参数
419     /// - flag 要更新的标志位的值
420     /// - value 如果为true,那么将flag对应的位设置为1,否则设置为0
421     ///
422     /// ## 返回值
423     ///
424     /// 更新后的页表项
425     #[inline(always)]
426     #[must_use]
427     pub fn update_flags(mut self, flag: usize, value: bool) -> Self {
428         if value {
429             self.data |= flag;
430         } else {
431             self.data &= !flag;
432         }
433         return self;
434     }
435 
436     /// 判断当前页表项是否存在指定的flag(只有全部flag都存在才返回true)
437     #[inline(always)]
438     pub fn has_flag(&self, flag: usize) -> bool {
439         return self.data & flag == flag;
440     }
441 
442     #[inline(always)]
443     pub fn present(&self) -> bool {
444         return self.has_flag(Arch::ENTRY_FLAG_PRESENT);
445     }
446 
447     /// 设置当前页表项的权限
448     ///
449     /// @param value 如果为true,那么将当前页表项的权限设置为用户态可访问
450     #[must_use]
451     #[inline(always)]
452     pub fn set_user(self, value: bool) -> Self {
453         return self.update_flags(Arch::ENTRY_FLAG_USER, value);
454     }
455 
456     /// 用户态是否可以访问当前页表项
457     #[inline(always)]
458     pub fn has_user(&self) -> bool {
459         return self.has_flag(Arch::ENTRY_FLAG_USER);
460     }
461 
462     /// 设置当前页表项的可写性, 如果为true,那么将当前页表项的权限设置为可写, 否则设置为只读
463     ///
464     /// ## 返回值
465     ///
466     /// 更新后的页表项.
467     ///
468     /// **请注意,**本函数会取得当前页表项的所有权,因此返回的页表项不是原来的页表项
469     #[must_use]
470     #[inline(always)]
471     pub fn set_write(self, value: bool) -> Self {
472         #[cfg(target_arch = "x86_64")]
473         {
474             // 有的架构同时具有可写和不可写的标志位,因此需要同时更新
475             return self
476                 .update_flags(Arch::ENTRY_FLAG_READONLY, !value)
477                 .update_flags(Arch::ENTRY_FLAG_READWRITE, value);
478         }
479 
480         #[cfg(target_arch = "riscv64")]
481         {
482             if value {
483                 return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true);
484             } else {
485                 return self.update_flags(Arch::ENTRY_FLAG_READONLY, true);
486             }
487         }
488     }
489 
490     /// 当前页表项是否可写
491     #[inline(always)]
492     pub fn has_write(&self) -> bool {
493         // 有的架构同时具有可写和不可写的标志位,因此需要同时判断
494         return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY)
495             == Arch::ENTRY_FLAG_READWRITE;
496     }
497 
498     /// 设置当前页表项的可执行性, 如果为true,那么将当前页表项的权限设置为可执行, 否则设置为不可执行
499     #[must_use]
500     #[inline(always)]
501     pub fn set_execute(self, mut value: bool) -> Self {
502         #[cfg(target_arch = "x86_64")]
503         {
504             // 如果xd位被保留,那么将可执行性设置为true
505             if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
506                 value = true;
507             }
508         }
509 
510         // 有的架构同时具有可执行和不可执行的标志位,因此需要同时更新
511         return self
512             .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value)
513             .update_flags(Arch::ENTRY_FLAG_EXEC, value);
514     }
515 
516     /// 当前页表项是否可执行
517     #[inline(always)]
518     pub fn has_execute(&self) -> bool {
519         // 有的架构同时具有可执行和不可执行的标志位,因此需要同时判断
520         return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC)
521             == Arch::ENTRY_FLAG_EXEC;
522     }
523 
524     /// 设置当前页表项的缓存策略
525     ///
526     /// ## 参数
527     ///
528     /// - value: 如果为true,那么将当前页表项的缓存策略设置为不缓存。
529     #[inline(always)]
530     pub fn set_page_cache_disable(self, value: bool) -> Self {
531         return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value);
532     }
533 
534     /// 获取当前页表项的缓存策略
535     ///
536     /// ## 返回值
537     ///
538     /// 如果当前页表项的缓存策略为不缓存,那么返回true,否则返回false。
539     #[inline(always)]
540     pub fn has_page_cache_disable(&self) -> bool {
541         return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE);
542     }
543 
544     /// 设置当前页表项的写穿策略
545     ///
546     /// ## 参数
547     ///
548     /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。
549     #[inline(always)]
550     pub fn set_page_write_through(self, value: bool) -> Self {
551         return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value);
552     }
553 
554     /// 获取当前页表项的写穿策略
555     ///
556     /// ## 返回值
557     ///
558     /// 如果当前页表项的写穿策略为写穿,那么返回true,否则返回false。
559     #[inline(always)]
560     pub fn has_page_write_through(&self) -> bool {
561         return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH);
562     }
563 
564     /// MMIO内存的页表项标志
565     #[inline(always)]
566     pub fn mmio_flags() -> Self {
567         return Self::new()
568             .set_user(false)
569             .set_write(true)
570             .set_execute(true)
571             .set_page_cache_disable(true)
572             .set_page_write_through(true);
573     }
574 }
575 
576 impl<Arch: MemoryManagementArch> fmt::Debug for PageFlags<Arch> {
577     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
578         f.debug_struct("PageFlags")
579             .field("bits", &format_args!("{:#0x}", self.data))
580             .field("present", &self.present())
581             .field("has_write", &self.has_write())
582             .field("has_execute", &self.has_execute())
583             .field("has_user", &self.has_user())
584             .finish()
585     }
586 }
587 
588 /// 页表映射器
589 #[derive(Hash)]
590 pub struct PageMapper<Arch, F> {
591     /// 页表类型
592     table_kind: PageTableKind,
593     /// 根页表物理地址
594     table_paddr: PhysAddr,
595     /// 页分配器
596     frame_allocator: F,
597     phantom: PhantomData<fn() -> Arch>,
598 }
599 
600 impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
601     /// 创建新的页面映射器
602     ///
603     /// ## 参数
604     /// - table_kind 页表类型
605     /// - table_paddr 根页表物理地址
606     /// - allocator 页分配器
607     ///
608     /// ## 返回值
609     ///
610     /// 页面映射器
611     pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self {
612         return Self {
613             table_kind,
614             table_paddr,
615             frame_allocator: allocator,
616             phantom: PhantomData,
617         };
618     }
619 
620     /// 创建页表,并为这个页表创建页面映射器
621     pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> {
622         let table_paddr = allocator.allocate_one()?;
623         // 清空页表
624         let table_vaddr = Arch::phys_2_virt(table_paddr)?;
625         Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE);
626         return Some(Self::new(table_kind, table_paddr, allocator));
627     }
628 
629     /// 获取当前页表的页面映射器
630     #[inline(always)]
631     pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self {
632         let table_paddr = Arch::table(table_kind);
633         return Self::new(table_kind, table_paddr, allocator);
634     }
635 
636     /// 判断当前页表分配器所属的页表是否是当前页表
637     #[inline(always)]
638     pub fn is_current(&self) -> bool {
639         return unsafe { self.table().phys() == Arch::table(self.table_kind) };
640     }
641 
642     /// 将当前页表分配器所属的页表设置为当前页表
643     #[inline(always)]
644     pub unsafe fn make_current(&self) {
645         Arch::set_table(self.table_kind, self.table_paddr);
646     }
647 
648     /// 获取当前页表分配器所属的根页表的结构体
649     #[inline(always)]
650     pub fn table(&self) -> PageTable<Arch> {
651         // 由于只能通过new方法创建PageMapper,因此这里假定table_paddr是有效的
652         return unsafe {
653             PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1)
654         };
655     }
656 
657     /// 获取当前PageMapper所对应的页分配器实例的引用
658     #[inline(always)]
659     #[allow(dead_code)]
660     pub fn allocator_ref(&self) -> &F {
661         return &self.frame_allocator;
662     }
663 
664     /// 获取当前PageMapper所对应的页分配器实例的可变引用
665     #[inline(always)]
666     pub fn allocator_mut(&mut self) -> &mut F {
667         return &mut self.frame_allocator;
668     }
669 
670     /// 从当前PageMapper的页分配器中分配一个物理页,并将其映射到指定的虚拟地址
671     pub unsafe fn map(
672         &mut self,
673         virt: VirtAddr,
674         flags: PageFlags<Arch>,
675     ) -> Option<PageFlush<Arch>> {
676         compiler_fence(Ordering::SeqCst);
677         let phys: PhysAddr = self.frame_allocator.allocate_one()?;
678         compiler_fence(Ordering::SeqCst);
679 
680         page_manager_lock_irasave().insert(phys, Page::new(false));
681         return self.map_phys(virt, phys, flags);
682     }
683 
684     /// 映射一个物理页到指定的虚拟地址
685     pub unsafe fn map_phys(
686         &mut self,
687         virt: VirtAddr,
688         phys: PhysAddr,
689         flags: PageFlags<Arch>,
690     ) -> Option<PageFlush<Arch>> {
691         // 验证虚拟地址和物理地址是否对齐
692         if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) {
693             kerror!(
694                 "Try to map unaligned page: virt={:?}, phys={:?}",
695                 virt,
696                 phys
697             );
698             return None;
699         }
700 
701         let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
702 
703         // TODO: 验证flags是否合法
704 
705         // 创建页表项
706         let entry = PageEntry::new(phys, flags);
707         let mut table = self.table();
708         loop {
709             let i = table.index_of(virt)?;
710             assert!(i < Arch::PAGE_ENTRY_NUM);
711             if table.level() == 0 {
712                 // todo: 检查是否已经映射
713                 // 现在不检查的原因是,刚刚启动系统时,内核会映射一些页。
714                 if table.entry_mapped(i)? {
715                     kwarn!("Page {:?} already mapped", virt);
716                 }
717 
718                 compiler_fence(Ordering::SeqCst);
719 
720                 table.set_entry(i, entry);
721                 compiler_fence(Ordering::SeqCst);
722                 return Some(PageFlush::new(virt));
723             } else {
724                 let next_table = table.next_level_table(i);
725                 if let Some(next_table) = next_table {
726                     table = next_table;
727                     // kdebug!("Mapping {:?} to next level table...", virt);
728                 } else {
729                     // 分配下一级页表
730                     let frame = self.frame_allocator.allocate_one()?;
731 
732                     // 清空这个页帧
733                     MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
734 
735                     // 设置页表项的flags
736                     let flags: PageFlags<Arch> =
737                         PageFlags::new_page_table(virt.kind() == PageTableKind::User);
738 
739                     // kdebug!("Flags: {:?}", flags);
740 
741                     // 把新分配的页表映射到当前页表
742                     table.set_entry(i, PageEntry::new(frame, flags));
743 
744                     // 获取新分配的页表
745                     table = table.next_level_table(i)?;
746                 }
747             }
748         }
749     }
750 
751     /// 将物理地址映射到具有线性偏移量的虚拟地址
752     #[allow(dead_code)]
753     pub unsafe fn map_linearly(
754         &mut self,
755         phys: PhysAddr,
756         flags: PageFlags<Arch>,
757     ) -> Option<(VirtAddr, PageFlush<Arch>)> {
758         let virt: VirtAddr = Arch::phys_2_virt(phys)?;
759         return self.map_phys(virt, phys, flags).map(|flush| (virt, flush));
760     }
761 
762     /// 修改虚拟地址的页表项的flags,并返回页表项刷新器
763     ///
764     /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效
765     ///
766     /// ## 参数
767     /// - virt 虚拟地址
768     /// - flags 新的页表项的flags
769     ///
770     /// ## 返回值
771     ///
772     /// 如果修改成功,返回刷新器,否则返回None
773     pub unsafe fn remap(
774         &mut self,
775         virt: VirtAddr,
776         flags: PageFlags<Arch>,
777     ) -> Option<PageFlush<Arch>> {
778         return self
779             .visit(virt, |p1, i| {
780                 let mut entry = p1.entry(i)?;
781                 entry.set_flags(flags);
782                 p1.set_entry(i, entry);
783                 Some(PageFlush::new(virt))
784             })
785             .flatten();
786     }
787 
788     /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags
789     ///
790     /// ## 参数
791     ///
792     /// - virt 虚拟地址
793     ///
794     /// ## 返回值
795     ///
796     /// 如果查找成功,返回物理地址和页表项的flags,否则返回None
797     pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, PageFlags<Arch>)> {
798         let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??;
799         let paddr = entry.address().ok()?;
800         let flags = entry.flags();
801         return Some((paddr, flags));
802     }
803 
804     /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器
805     ///
806     /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效
807     ///
808     /// ## 参数
809     ///
810     /// - virt 虚拟地址
811     /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
812     ///
813     /// ## 返回值
814     /// 如果取消成功,返回刷新器,否则返回None
815     #[allow(dead_code)]
816     pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> {
817         let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?;
818         self.frame_allocator.free_one(paddr);
819         return Some(flusher);
820     }
821 
822     /// 取消虚拟地址的映射,并返回物理地址和页表项的flags
823     ///
824     /// ## 参数
825     ///
826     /// - vaddr 虚拟地址
827     /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
828     ///
829     /// ## 返回值
830     ///
831     /// 如果取消成功,返回物理地址和页表项的flags,否则返回None
832     pub unsafe fn unmap_phys(
833         &mut self,
834         virt: VirtAddr,
835         unmap_parents: bool,
836     ) -> Option<(PhysAddr, PageFlags<Arch>, PageFlush<Arch>)> {
837         if !virt.check_aligned(Arch::PAGE_SIZE) {
838             kerror!("Try to unmap unaligned page: virt={:?}", virt);
839             return None;
840         }
841 
842         let table = self.table();
843         return unmap_phys_inner(virt, &table, unmap_parents, self.allocator_mut())
844             .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt)));
845     }
846 
847     /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F
848     fn visit<T>(
849         &self,
850         virt: VirtAddr,
851         f: impl FnOnce(&mut PageTable<Arch>, usize) -> T,
852     ) -> Option<T> {
853         let mut table = self.table();
854         unsafe {
855             loop {
856                 let i = table.index_of(virt)?;
857                 if table.level() == 0 {
858                     return Some(f(&mut table, i));
859                 } else {
860                     table = table.next_level_table(i)?;
861                 }
862             }
863         }
864     }
865 }
866 
867 /// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】
868 ///
869 /// ## 参数
870 ///
871 /// - vaddr 虚拟地址
872 /// - table 页表
873 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
874 /// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内)
875 ///
876 /// ## 返回值
877 ///
878 /// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None
879 unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
880     vaddr: VirtAddr,
881     table: &PageTable<Arch>,
882     unmap_parents: bool,
883     allocator: &mut impl FrameAllocator,
884 ) -> Option<(PhysAddr, PageFlags<Arch>)> {
885     // 获取页表项的索引
886     let i = table.index_of(vaddr)?;
887 
888     // 如果当前是最后一级页表,直接取消页面映射
889     if table.level() == 0 {
890         let entry = table.entry(i)?;
891         table.set_entry(i, PageEntry::from_usize(0));
892         return Some((entry.address().ok()?, entry.flags()));
893     }
894 
895     let subtable = table.next_level_table(i)?;
896     // 递归地取消映射
897     let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator)?;
898 
899     // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables,
900     // as these mappings may become out of sync
901     if unmap_parents {
902         // 如果子页表已经没有映射的页面了,就取消子页表的映射
903 
904         // 检查子页表中是否还有映射的页面
905         let x = (0..Arch::PAGE_ENTRY_NUM)
906             .map(|k| subtable.entry(k).expect("invalid page entry"))
907             .any(|e| e.present());
908         if !x {
909             // 如果没有,就取消子页表的映射
910             table.set_entry(i, PageEntry::from_usize(0));
911             // 释放子页表
912             allocator.free_one(subtable.phys());
913         }
914     }
915 
916     return Some(result);
917 }
918 
919 impl<Arch, F: Debug> Debug for PageMapper<Arch, F> {
920     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
921         f.debug_struct("PageMapper")
922             .field("table_paddr", &self.table_paddr)
923             .field("frame_allocator", &self.frame_allocator)
924             .finish()
925     }
926 }
927 
928 /// 页表刷新器的trait
929 pub trait Flusher<Arch: MemoryManagementArch> {
930     /// 取消对指定的page flusher的刷新
931     fn consume(&mut self, flush: PageFlush<Arch>);
932 }
933 
934 /// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法,
935 /// 否则会造成对页表的更改被忽略,这是不安全的
936 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
937 pub struct PageFlush<Arch: MemoryManagementArch> {
938     virt: VirtAddr,
939     phantom: PhantomData<Arch>,
940 }
941 
942 impl<Arch: MemoryManagementArch> PageFlush<Arch> {
943     pub fn new(virt: VirtAddr) -> Self {
944         return Self {
945             virt,
946             phantom: PhantomData,
947         };
948     }
949 
950     pub fn flush(self) {
951         unsafe { Arch::invalidate_page(self.virt) };
952     }
953 
954     /// 忽略掉这个刷新器
955     pub unsafe fn ignore(self) {
956         mem::forget(self);
957     }
958 }
959 
960 impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> {
961     fn drop(&mut self) {
962         unsafe {
963             MMArch::invalidate_page(self.virt);
964         }
965     }
966 }
967 
968 /// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法,
969 /// 否则会造成对页表的更改被忽略,这是不安全的
970 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
971 pub struct PageFlushAll<Arch: MemoryManagementArch> {
972     phantom: PhantomData<fn() -> Arch>,
973 }
974 
975 #[allow(dead_code)]
976 impl<Arch: MemoryManagementArch> PageFlushAll<Arch> {
977     pub fn new() -> Self {
978         return Self {
979             phantom: PhantomData,
980         };
981     }
982 
983     pub fn flush(self) {
984         unsafe { Arch::invalidate_all() };
985     }
986 
987     /// 忽略掉这个刷新器
988     pub unsafe fn ignore(self) {
989         mem::forget(self);
990     }
991 }
992 
993 impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> {
994     /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了)
995     fn consume(&mut self, flush: PageFlush<Arch>) {
996         unsafe { flush.ignore() };
997     }
998 }
999 
1000 impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T {
1001     /// 允许一个flusher consume掉另一个flusher
1002     fn consume(&mut self, flush: PageFlush<Arch>) {
1003         <T as Flusher<Arch>>::consume(self, flush);
1004     }
1005 }
1006 
1007 impl<Arch: MemoryManagementArch> Flusher<Arch> for () {
1008     fn consume(&mut self, _flush: PageFlush<Arch>) {}
1009 }
1010 
1011 impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> {
1012     fn drop(&mut self) {
1013         unsafe {
1014             Arch::invalidate_all();
1015         }
1016     }
1017 }
1018 
1019 /// 未在当前CPU上激活的页表的刷新器
1020 ///
1021 /// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表
1022 ///
1023 /// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销)
1024 #[derive(Debug)]
1025 pub struct InactiveFlusher;
1026 
1027 impl InactiveFlusher {
1028     pub fn new() -> Self {
1029         return Self {};
1030     }
1031 }
1032 
1033 impl Flusher<MMArch> for InactiveFlusher {
1034     fn consume(&mut self, flush: PageFlush<MMArch>) {
1035         unsafe {
1036             flush.ignore();
1037         }
1038     }
1039 }
1040 
1041 impl Drop for InactiveFlusher {
1042     fn drop(&mut self) {
1043         // 发送刷新页表的IPI
1044         send_ipi(IpiKind::FlushTLB, IpiTarget::Other);
1045     }
1046 }
1047 
1048 /// # 把一个地址向下对齐到页大小
1049 pub fn round_down_to_page_size(addr: usize) -> usize {
1050     addr & !(MMArch::PAGE_SIZE - 1)
1051 }
1052 
1053 /// # 把一个地址向上对齐到页大小
1054 pub fn round_up_to_page_size(addr: usize) -> usize {
1055     round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1)
1056 }
1057