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