xref: /DragonOS/kernel/src/mm/page.rs (revision a3571c8b7908145315148104bcc9fdea05db9c4f)
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
page_manager_init()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 
page_manager_lock_irqsave() -> SpinLockGuard<'static, PageManager>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 {
new() -> Self71     pub fn new() -> Self {
72         Self {
73             phys2page: HashMap::new(),
74         }
75     }
76 
contains(&self, paddr: &PhysAddr) -> bool77     pub fn contains(&self, paddr: &PhysAddr) -> bool {
78         self.phys2page.contains_key(paddr)
79     }
80 
get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>>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 
get_unwrap(&mut self, paddr: &PhysAddr) -> Arc<Page>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 
insert(&mut self, paddr: PhysAddr, page: &Arc<Page>)94     pub fn insert(&mut self, paddr: PhysAddr, page: &Arc<Page>) {
95         self.phys2page.insert(paddr, page.clone());
96     }
97 
remove_page(&mut self, paddr: &PhysAddr)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 
page_reclaimer_init()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)]
page_reclaimer_thread_init() -> Result<(), SystemError>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 /// 页面回收线程执行的函数
page_reclaim_thread() -> i32139 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 /// 获取页面回收器
page_reclaimer_lock_irqsave() -> SpinLockGuard<'static, PageReclaimer>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 {
new() -> Self169     pub fn new() -> Self {
170         Self {
171             lru: LruCache::unbounded(),
172         }
173     }
174 
get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>>175     pub fn get(&mut self, paddr: &PhysAddr) -> Option<Arc<Page>> {
176         self.lru.get(paddr).cloned()
177     }
178 
insert_page(&mut self, paddr: PhysAddr, page: &Arc<Page>)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`: 需要缩减的页面数量
shrink_list(&mut self, count: PageFrameCount)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     /// 唤醒页面回收线程
wakeup_claim_thread()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: 页面错误处理信息标志
page_writeback(page: &Arc<Page>, unmap: bool)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脏页刷新
flush_dirty_pages(&self)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 {
new(shared: bool, phys_addr: PhysAddr) -> Self314     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 
read_irqsave(&self) -> RwLockReadGuard<InnerPage>321     pub fn read_irqsave(&self) -> RwLockReadGuard<InnerPage> {
322         self.inner.read_irqsave()
323     }
324 
write_irqsave(&self) -> RwLockWriteGuard<InnerPage>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 {
new(shared: bool, phys_addr: PhysAddr) -> Self353     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
insert_vma(&mut self, vma: Arc<LockedVMA>)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中删去
remove_vma(&mut self, vma: &LockedVMA)375     pub fn remove_vma(&mut self, vma: &LockedVMA) {
376         self.anon_vma.remove(vma);
377         self.map_count -= 1;
378     }
379 
380     /// 判断当前物理页是否能被回
can_deallocate(&self) -> bool381     pub fn can_deallocate(&self) -> bool {
382         self.map_count == 0 && self.free_when_zero
383     }
384 
shared(&self) -> bool385     pub fn shared(&self) -> bool {
386         self.shared
387     }
388 
shm_id(&self) -> Option<ShmId>389     pub fn shm_id(&self) -> Option<ShmId> {
390         self.shm_id
391     }
392 
index(&self) -> Option<usize>393     pub fn index(&self) -> Option<usize> {
394         self.index
395     }
396 
page_cache(&self) -> Option<Arc<PageCache>>397     pub fn page_cache(&self) -> Option<Arc<PageCache>> {
398         self.page_cache.clone()
399     }
400 
set_page_cache(&mut self, page_cache: Option<Arc<PageCache>>)401     pub fn set_page_cache(&mut self, page_cache: Option<Arc<PageCache>>) {
402         self.page_cache = page_cache;
403     }
404 
set_index(&mut self, index: Option<usize>)405     pub fn set_index(&mut self, index: Option<usize>) {
406         self.index = index;
407     }
408 
set_page_cache_index( &mut self, page_cache: Option<Arc<PageCache>>, index: Option<usize>, )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 
set_shm_id(&mut self, shm_id: ShmId)418     pub fn set_shm_id(&mut self, shm_id: ShmId) {
419         self.shm_id = Some(shm_id);
420     }
421 
set_dealloc_when_zero(&mut self, dealloc_when_zero: bool)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)]
anon_vma(&self) -> &HashSet<Arc<LockedVMA>>427     pub fn anon_vma(&self) -> &HashSet<Arc<LockedVMA>> {
428         &self.anon_vma
429     }
430 
431     #[inline(always)]
map_count(&self) -> usize432     pub fn map_count(&self) -> usize {
433         self.map_count
434     }
435 
436     #[inline(always)]
flags(&self) -> &PageFlags437     pub fn flags(&self) -> &PageFlags {
438         &self.flags
439     }
440 
441     #[inline(always)]
set_flags(&mut self, flags: PageFlags)442     pub fn set_flags(&mut self, flags: PageFlags) {
443         self.flags = flags
444     }
445 
446     #[inline(always)]
add_flags(&mut self, flags: PageFlags)447     pub fn add_flags(&mut self, flags: PageFlags) {
448         self.flags = self.flags.union(flags);
449     }
450 
451     #[inline(always)]
remove_flags(&mut self, flags: PageFlags)452     pub fn remove_flags(&mut self, flags: PageFlags) {
453         self.flags = self.flags.difference(flags);
454     }
455 
456     #[inline(always)]
phys_address(&self) -> PhysAddr457     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> {
new(base: VirtAddr, phys: PhysAddr, level: usize) -> Self475     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     /// 返回顶级页表
top_level_table(table_kind: PageTableKind) -> Self493     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)]
phys(&self) -> PhysAddr503     pub fn phys(&self) -> PhysAddr {
504         self.phys
505     }
506 
507     /// 当前页表表示的虚拟地址空间的起始地址
508     #[inline(always)]
base(&self) -> VirtAddr509     pub fn base(&self) -> VirtAddr {
510         self.base
511     }
512 
513     /// 获取当前页表的层级
514     #[inline(always)]
level(&self) -> usize515     pub fn level(&self) -> usize {
516         self.level
517     }
518 
519     /// 获取当前页表自身所在的虚拟地址
520     #[inline(always)]
virt(&self) -> VirtAddr521     pub unsafe fn virt(&self) -> VirtAddr {
522         return Arch::phys_2_virt(self.phys).unwrap();
523     }
524 
525     /// 获取第i个页表项所表示的虚拟内存空间的起始地址
entry_base(&self, i: usize) -> Option<VirtAddr>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进行区分)
entry_virt(&self, i: usize) -> Option<VirtAddr>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个页表项
entry(&self, i: usize) -> Option<PageEntry<Arch>>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个页表项
set_entry(&self, i: usize, entry: PageEntry<Arch>) -> Option<()>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超出了页表项的范围
entry_mapped(&self, i: usize) -> Option<bool>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
index_of(&self, addr: VirtAddr) -> Option<usize>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个页表项指向的下一级页表
next_level_table(&self, index: usize) -> Option<Self>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`: 是否写时复制
clone( &self, allocator: &mut impl FrameAllocator, copy_on_write: bool, ) -> Option<PageTable<Arch>>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> {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>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)]
new(paddr: PhysAddr, flags: EntryFlags<Arch>) -> Self689     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)]
from_usize(data: usize) -> Self696     pub fn from_usize(data: usize) -> Self {
697         Self {
698             data,
699             phantom: PhantomData,
700         }
701     }
702 
703     #[inline(always)]
data(&self) -> usize704     pub fn data(&self) -> usize {
705         self.data
706     }
707 
708     /// 获取当前页表项指向的物理地址
709     ///
710     /// ## 返回值
711     ///
712     /// - Ok(PhysAddr) 如果当前页面存在于物理内存中, 返回物理地址
713     /// - Err(PhysAddr) 如果当前页表项不存在, 返回物理地址
714     #[inline(always)]
address(&self) -> Result<PhysAddr, PhysAddr>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)]
flags(&self) -> EntryFlags<Arch>737     pub fn flags(&self) -> EntryFlags<Arch> {
738         unsafe { EntryFlags::from_data(self.data & Arch::ENTRY_FLAGS_MASK) }
739     }
740 
741     #[inline(always)]
set_flags(&mut self, flags: EntryFlags<Arch>)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)]
present(&self) -> bool747     pub fn present(&self) -> bool {
748         return self.data & Arch::ENTRY_FLAG_PRESENT != 0;
749     }
750 
751     #[inline(always)]
empty(&self) -> bool752     pub fn empty(&self) -> bool {
753         self.data & !(Arch::ENTRY_FLAG_DIRTY & Arch::ENTRY_FLAG_ACCESSED) == 0
754     }
755 
756     #[inline(always)]
protnone(&self) -> bool757     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)]
write(&self) -> bool763     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> {
default() -> Self776     fn default() -> Self {
777         Self::new()
778     }
779 }
780 
781 #[allow(dead_code)]
782 impl<Arch: MemoryManagementArch> EntryFlags<Arch> {
783     #[inline(always)]
new() -> Self784     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: 用户空间是否可访问
from_prot_flags(prot_flags: ProtFlags, user: bool) -> Self809     pub fn from_prot_flags(prot_flags: ProtFlags, user: bool) -> Self {
810         if Arch::PAGE_FAULT_ENABLED {
811             let vm_flags = super::VmFlags::from(prot_flags);
812             Arch::vm_get_page_prot(vm_flags).set_user(user)
813         } else {
814             EntryFlags::new()
815                 .set_user(user)
816                 .set_execute(prot_flags.contains(ProtFlags::PROT_EXEC))
817                 .set_write(prot_flags.contains(ProtFlags::PROT_WRITE))
818         }
819     }
820 
821     #[inline(always)]
data(&self) -> usize822     pub fn data(&self) -> usize {
823         self.data
824     }
825 
826     #[inline(always)]
from_data(data: usize) -> Self827     pub const unsafe fn from_data(data: usize) -> Self {
828         return Self {
829             data,
830             phantom: PhantomData,
831         };
832     }
833 
834     /// 为新页表的页表项设置默认值
835     ///
836     /// 默认值为:
837     /// - present
838     /// - read only
839     /// - kernel space
840     /// - no exec
841     #[inline(always)]
new_page_table(user: bool) -> Self842     pub fn new_page_table(user: bool) -> Self {
843         return unsafe {
844             let r = {
845                 #[cfg(target_arch = "x86_64")]
846                 {
847                     Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE | Arch::ENTRY_FLAG_READWRITE)
848                 }
849 
850                 #[cfg(target_arch = "riscv64")]
851                 {
852                     // riscv64指向下一级页表的页表项,不应设置R/W/X权限位
853                     Self::from_data(Arch::ENTRY_FLAG_DEFAULT_TABLE)
854                 }
855             };
856 
857             #[cfg(target_arch = "x86_64")]
858             {
859                 if user {
860                     r.set_user(true)
861                 } else {
862                     r
863                 }
864             }
865 
866             #[cfg(target_arch = "riscv64")]
867             {
868                 r
869             }
870         };
871     }
872 
873     /// 取得当前页表项的所有权,更新当前页表项的标志位,并返回更新后的页表项。
874     ///
875     /// ## 参数
876     /// - flag 要更新的标志位的值
877     /// - value 如果为true,那么将flag对应的位设置为1,否则设置为0
878     ///
879     /// ## 返回值
880     ///
881     /// 更新后的页表项
882     #[inline(always)]
883     #[must_use]
update_flags(mut self, flag: usize, value: bool) -> Self884     pub fn update_flags(mut self, flag: usize, value: bool) -> Self {
885         if value {
886             self.data |= flag;
887         } else {
888             self.data &= !flag;
889         }
890         return self;
891     }
892 
893     /// 判断当前页表项是否存在指定的flag(只有全部flag都存在才返回true)
894     #[inline(always)]
has_flag(&self, flag: usize) -> bool895     pub fn has_flag(&self, flag: usize) -> bool {
896         return self.data & flag == flag;
897     }
898 
899     #[inline(always)]
present(&self) -> bool900     pub fn present(&self) -> bool {
901         return self.has_flag(Arch::ENTRY_FLAG_PRESENT);
902     }
903 
904     /// 设置当前页表项的权限
905     ///
906     /// @param value 如果为true,那么将当前页表项的权限设置为用户态可访问
907     #[must_use]
908     #[inline(always)]
set_user(self, value: bool) -> Self909     pub fn set_user(self, value: bool) -> Self {
910         return self.update_flags(Arch::ENTRY_FLAG_USER, value);
911     }
912 
913     /// 用户态是否可以访问当前页表项
914     #[inline(always)]
has_user(&self) -> bool915     pub fn has_user(&self) -> bool {
916         return self.has_flag(Arch::ENTRY_FLAG_USER);
917     }
918 
919     /// 设置当前页表项的可写性, 如果为true,那么将当前页表项的权限设置为可写, 否则设置为只读
920     ///
921     /// ## 返回值
922     ///
923     /// 更新后的页表项.
924     ///
925     /// **请注意,**本函数会取得当前页表项的所有权,因此返回的页表项不是原来的页表项
926     #[must_use]
927     #[inline(always)]
set_write(self, value: bool) -> Self928     pub fn set_write(self, value: bool) -> Self {
929         #[cfg(target_arch = "x86_64")]
930         {
931             // 有的架构同时具有可写和不可写的标志位,因此需要同时更新
932             return self
933                 .update_flags(Arch::ENTRY_FLAG_READONLY, !value)
934                 .update_flags(Arch::ENTRY_FLAG_READWRITE, value);
935         }
936 
937         #[cfg(target_arch = "riscv64")]
938         {
939             if value {
940                 return self.update_flags(Arch::ENTRY_FLAG_READWRITE, true);
941             } else {
942                 return self
943                     .update_flags(Arch::ENTRY_FLAG_READONLY, true)
944                     .update_flags(Arch::ENTRY_FLAG_WRITEABLE, false);
945             }
946         }
947     }
948 
949     /// 当前页表项是否可写
950     #[inline(always)]
has_write(&self) -> bool951     pub fn has_write(&self) -> bool {
952         // 有的架构同时具有可写和不可写的标志位,因此需要同时判断
953         return self.data & (Arch::ENTRY_FLAG_READWRITE | Arch::ENTRY_FLAG_READONLY)
954             == Arch::ENTRY_FLAG_READWRITE;
955     }
956 
957     /// 设置当前页表项的可执行性, 如果为true,那么将当前页表项的权限设置为可执行, 否则设置为不可执行
958     #[must_use]
959     #[inline(always)]
set_execute(self, mut value: bool) -> Self960     pub fn set_execute(self, mut value: bool) -> Self {
961         #[cfg(target_arch = "x86_64")]
962         {
963             // 如果xd位被保留,那么将可执行性设置为true
964             if crate::arch::mm::X86_64MMArch::is_xd_reserved() {
965                 value = true;
966             }
967         }
968 
969         // 有的架构同时具有可执行和不可执行的标志位,因此需要同时更新
970         return self
971             .update_flags(Arch::ENTRY_FLAG_NO_EXEC, !value)
972             .update_flags(Arch::ENTRY_FLAG_EXEC, value);
973     }
974 
975     /// 当前页表项是否可执行
976     #[inline(always)]
has_execute(&self) -> bool977     pub fn has_execute(&self) -> bool {
978         // 有的架构同时具有可执行和不可执行的标志位,因此需要同时判断
979         return self.data & (Arch::ENTRY_FLAG_EXEC | Arch::ENTRY_FLAG_NO_EXEC)
980             == Arch::ENTRY_FLAG_EXEC;
981     }
982 
983     /// 设置当前页表项的缓存策略
984     ///
985     /// ## 参数
986     ///
987     /// - value: 如果为true,那么将当前页表项的缓存策略设置为不缓存。
988     #[inline(always)]
set_page_cache_disable(self, value: bool) -> Self989     pub fn set_page_cache_disable(self, value: bool) -> Self {
990         return self.update_flags(Arch::ENTRY_FLAG_CACHE_DISABLE, value);
991     }
992 
993     /// 获取当前页表项的缓存策略
994     ///
995     /// ## 返回值
996     ///
997     /// 如果当前页表项的缓存策略为不缓存,那么返回true,否则返回false。
998     #[inline(always)]
has_page_cache_disable(&self) -> bool999     pub fn has_page_cache_disable(&self) -> bool {
1000         return self.has_flag(Arch::ENTRY_FLAG_CACHE_DISABLE);
1001     }
1002 
1003     /// 设置当前页表项的写穿策略
1004     ///
1005     /// ## 参数
1006     ///
1007     /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。
1008     #[inline(always)]
set_page_write_through(self, value: bool) -> Self1009     pub fn set_page_write_through(self, value: bool) -> Self {
1010         return self.update_flags(Arch::ENTRY_FLAG_WRITE_THROUGH, value);
1011     }
1012 
1013     #[inline(always)]
set_page_global(self, value: bool) -> Self1014     pub fn set_page_global(self, value: bool) -> Self {
1015         return self.update_flags(MMArch::ENTRY_FLAG_GLOBAL, value);
1016     }
1017 
1018     /// 获取当前页表项的写穿策略
1019     ///
1020     /// ## 返回值
1021     ///
1022     /// 如果当前页表项的写穿策略为写穿,那么返回true,否则返回false。
1023     #[inline(always)]
has_page_write_through(&self) -> bool1024     pub fn has_page_write_through(&self) -> bool {
1025         return self.has_flag(Arch::ENTRY_FLAG_WRITE_THROUGH);
1026     }
1027 
1028     /// 设置当前页表是否为脏页
1029     ///
1030     /// ## 参数
1031     ///
1032     /// - value: 如果为true,那么将当前页表项的写穿策略设置为写穿。
1033     #[inline(always)]
set_dirty(self, value: bool) -> Self1034     pub fn set_dirty(self, value: bool) -> Self {
1035         return self.update_flags(Arch::ENTRY_FLAG_DIRTY, value);
1036     }
1037 
1038     /// 设置当前页表被访问
1039     ///
1040     /// ## 参数
1041     ///
1042     /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。
1043     #[inline(always)]
set_access(self, value: bool) -> Self1044     pub fn set_access(self, value: bool) -> Self {
1045         return self.update_flags(Arch::ENTRY_FLAG_ACCESSED, value);
1046     }
1047 
1048     /// 设置指向的页是否为大页
1049     ///
1050     /// ## 参数
1051     ///
1052     /// - value: 如果为true,那么将当前页表项的访问标志设置为已访问。
1053     #[inline(always)]
set_huge_page(self, value: bool) -> Self1054     pub fn set_huge_page(self, value: bool) -> Self {
1055         return self.update_flags(Arch::ENTRY_FLAG_HUGE_PAGE, value);
1056     }
1057 
1058     /// MMIO内存的页表项标志
1059     #[inline(always)]
mmio_flags() -> Self1060     pub fn mmio_flags() -> Self {
1061         #[cfg(target_arch = "x86_64")]
1062         {
1063             Self::new()
1064                 .set_user(false)
1065                 .set_write(true)
1066                 .set_execute(true)
1067                 .set_page_cache_disable(true)
1068                 .set_page_write_through(true)
1069                 .set_page_global(true)
1070         }
1071 
1072         #[cfg(target_arch = "riscv64")]
1073         {
1074             Self::new()
1075                 .set_user(false)
1076                 .set_write(true)
1077                 .set_execute(true)
1078                 .set_page_global(true)
1079         }
1080     }
1081 }
1082 
1083 impl<Arch: MemoryManagementArch> fmt::Debug for EntryFlags<Arch> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1084     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1085         f.debug_struct("EntryFlags")
1086             .field("bits", &format_args!("{:#0x}", self.data))
1087             .field("present", &self.present())
1088             .field("has_write", &self.has_write())
1089             .field("has_execute", &self.has_execute())
1090             .field("has_user", &self.has_user())
1091             .finish()
1092     }
1093 }
1094 
1095 /// 页表映射器
1096 #[derive(Hash)]
1097 pub struct PageMapper<Arch, F> {
1098     /// 页表类型
1099     table_kind: PageTableKind,
1100     /// 根页表物理地址
1101     table_paddr: PhysAddr,
1102     /// 页分配器
1103     frame_allocator: F,
1104     phantom: PhantomData<fn() -> Arch>,
1105 }
1106 
1107 impl<Arch: MemoryManagementArch, F: FrameAllocator> PageMapper<Arch, F> {
1108     /// 创建新的页面映射器
1109     ///
1110     /// ## 参数
1111     /// - table_kind 页表类型
1112     /// - table_paddr 根页表物理地址
1113     /// - allocator 页分配器
1114     ///
1115     /// ## 返回值
1116     ///
1117     /// 页面映射器
new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self1118     pub unsafe fn new(table_kind: PageTableKind, table_paddr: PhysAddr, allocator: F) -> Self {
1119         return Self {
1120             table_kind,
1121             table_paddr,
1122             frame_allocator: allocator,
1123             phantom: PhantomData,
1124         };
1125     }
1126 
1127     /// 创建页表,并为这个页表创建页面映射器
create(table_kind: PageTableKind, mut allocator: F) -> Option<Self>1128     pub unsafe fn create(table_kind: PageTableKind, mut allocator: F) -> Option<Self> {
1129         let table_paddr = allocator.allocate_one()?;
1130         // 清空页表
1131         let table_vaddr = Arch::phys_2_virt(table_paddr)?;
1132         Arch::write_bytes(table_vaddr, 0, Arch::PAGE_SIZE);
1133         return Some(Self::new(table_kind, table_paddr, allocator));
1134     }
1135 
1136     /// 获取当前页表的页面映射器
1137     #[inline(always)]
current(table_kind: PageTableKind, allocator: F) -> Self1138     pub unsafe fn current(table_kind: PageTableKind, allocator: F) -> Self {
1139         let table_paddr = Arch::table(table_kind);
1140         return Self::new(table_kind, table_paddr, allocator);
1141     }
1142 
1143     /// 判断当前页表分配器所属的页表是否是当前页表
1144     #[inline(always)]
is_current(&self) -> bool1145     pub fn is_current(&self) -> bool {
1146         return unsafe { self.table().phys() == Arch::table(self.table_kind) };
1147     }
1148 
1149     /// 将当前页表分配器所属的页表设置为当前页表
1150     #[inline(always)]
make_current(&self)1151     pub unsafe fn make_current(&self) {
1152         Arch::set_table(self.table_kind, self.table_paddr);
1153     }
1154 
1155     /// 获取当前页表分配器所属的根页表的结构体
1156     #[inline(always)]
table(&self) -> PageTable<Arch>1157     pub fn table(&self) -> PageTable<Arch> {
1158         // 由于只能通过new方法创建PageMapper,因此这里假定table_paddr是有效的
1159         return unsafe {
1160             PageTable::new(VirtAddr::new(0), self.table_paddr, Arch::PAGE_LEVELS - 1)
1161         };
1162     }
1163 
1164     /// 获取当前PageMapper所对应的页分配器实例的引用
1165     #[inline(always)]
1166     #[allow(dead_code)]
allocator_ref(&self) -> &F1167     pub fn allocator_ref(&self) -> &F {
1168         return &self.frame_allocator;
1169     }
1170 
1171     /// 获取当前PageMapper所对应的页分配器实例的可变引用
1172     #[inline(always)]
allocator_mut(&mut self) -> &mut F1173     pub fn allocator_mut(&mut self) -> &mut F {
1174         return &mut self.frame_allocator;
1175     }
1176 
1177     /// 从当前PageMapper的页分配器中分配一个物理页,并将其映射到指定的虚拟地址
map( &mut self, virt: VirtAddr, flags: EntryFlags<Arch>, ) -> Option<PageFlush<Arch>>1178     pub unsafe fn map(
1179         &mut self,
1180         virt: VirtAddr,
1181         flags: EntryFlags<Arch>,
1182     ) -> Option<PageFlush<Arch>> {
1183         compiler_fence(Ordering::SeqCst);
1184         let phys: PhysAddr = self.frame_allocator.allocate_one()?;
1185         compiler_fence(Ordering::SeqCst);
1186 
1187         unsafe {
1188             let vaddr = MMArch::phys_2_virt(phys).unwrap();
1189             MMArch::write_bytes(vaddr, 0, MMArch::PAGE_SIZE);
1190         }
1191 
1192         let mut page_manager_guard: SpinLockGuard<'static, PageManager> =
1193             page_manager_lock_irqsave();
1194         if !page_manager_guard.contains(&phys) {
1195             page_manager_guard.insert(phys, &Arc::new(Page::new(false, phys)))
1196         }
1197         drop(page_manager_guard);
1198         return self.map_phys(virt, phys, flags);
1199     }
1200 
1201     /// 映射一个物理页到指定的虚拟地址
map_phys( &mut self, virt: VirtAddr, phys: PhysAddr, flags: EntryFlags<Arch>, ) -> Option<PageFlush<Arch>>1202     pub unsafe fn map_phys(
1203         &mut self,
1204         virt: VirtAddr,
1205         phys: PhysAddr,
1206         flags: EntryFlags<Arch>,
1207     ) -> Option<PageFlush<Arch>> {
1208         // 验证虚拟地址和物理地址是否对齐
1209         if !(virt.check_aligned(Arch::PAGE_SIZE) && phys.check_aligned(Arch::PAGE_SIZE)) {
1210             error!(
1211                 "Try to map unaligned page: virt={:?}, phys={:?}",
1212                 virt, phys
1213             );
1214             return None;
1215         }
1216 
1217         let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
1218 
1219         // TODO: 验证flags是否合法
1220 
1221         // 创建页表项
1222         let entry = PageEntry::new(phys, flags);
1223         let mut table = self.table();
1224         loop {
1225             let i = table.index_of(virt)?;
1226 
1227             assert!(i < Arch::PAGE_ENTRY_NUM);
1228             if table.level() == 0 {
1229                 compiler_fence(Ordering::SeqCst);
1230 
1231                 table.set_entry(i, entry);
1232                 compiler_fence(Ordering::SeqCst);
1233                 return Some(PageFlush::new(virt));
1234             } else {
1235                 let next_table = table.next_level_table(i);
1236                 if let Some(next_table) = next_table {
1237                     table = next_table;
1238                     // debug!("Mapping {:?} to next level table...", virt);
1239                 } else {
1240                     // 分配下一级页表
1241                     let frame = self.frame_allocator.allocate_one()?;
1242 
1243                     // 清空这个页帧
1244                     MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
1245                     // 设置页表项的flags
1246                     let flags: EntryFlags<Arch> =
1247                         EntryFlags::new_page_table(virt.kind() == PageTableKind::User);
1248 
1249                     // 把新分配的页表映射到当前页表
1250                     table.set_entry(i, PageEntry::new(frame, flags));
1251 
1252                     // 获取新分配的页表
1253                     table = table.next_level_table(i)?;
1254                 }
1255             }
1256         }
1257     }
1258 
1259     /// 进行大页映射
map_huge_page( &mut self, virt: VirtAddr, flags: EntryFlags<Arch>, ) -> Option<PageFlush<Arch>>1260     pub unsafe fn map_huge_page(
1261         &mut self,
1262         virt: VirtAddr,
1263         flags: EntryFlags<Arch>,
1264     ) -> Option<PageFlush<Arch>> {
1265         // 验证虚拟地址是否对齐
1266         if !(virt.check_aligned(Arch::PAGE_SIZE)) {
1267             error!("Try to map unaligned page: virt={:?}", virt);
1268             return None;
1269         }
1270 
1271         let virt = VirtAddr::new(virt.data() & (!Arch::PAGE_NEGATIVE_MASK));
1272 
1273         let mut table = self.table();
1274         loop {
1275             let i = table.index_of(virt)?;
1276             assert!(i < Arch::PAGE_ENTRY_NUM);
1277             let next_table = table.next_level_table(i);
1278             if let Some(next_table) = next_table {
1279                 table = next_table;
1280             } else {
1281                 break;
1282             }
1283         }
1284 
1285         // 支持2M、1G大页,即页表层级为1、2级的页表可以映射大页
1286         if table.level == 0 || table.level > 2 {
1287             return None;
1288         }
1289 
1290         let (phys, count) = self.frame_allocator.allocate(PageFrameCount::new(
1291             Arch::PAGE_ENTRY_NUM.pow(table.level as u32),
1292         ))?;
1293 
1294         MMArch::write_bytes(
1295             MMArch::phys_2_virt(phys).unwrap(),
1296             0,
1297             MMArch::PAGE_SIZE * count.data(),
1298         );
1299 
1300         table.set_entry(
1301             table.index_of(virt)?,
1302             PageEntry::new(phys, flags.set_huge_page(true)),
1303         )?;
1304         Some(PageFlush::new(virt))
1305     }
1306 
1307     /// 为虚拟地址分配指定层级的页表
1308     /// ## 参数
1309     ///
1310     /// - `virt`: 虚拟地址
1311     /// - `level`: 指定页表层级
1312     ///
1313     /// ## 返回值
1314     /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表
1315     /// - None: 对应页表不存在
allocate_table( &mut self, virt: VirtAddr, level: usize, ) -> Option<PageTable<Arch>>1316     pub unsafe fn allocate_table(
1317         &mut self,
1318         virt: VirtAddr,
1319         level: usize,
1320     ) -> Option<PageTable<Arch>> {
1321         let table = self.get_table(virt, level + 1)?;
1322         let i = table.index_of(virt)?;
1323         let frame = self.frame_allocator.allocate_one()?;
1324 
1325         // 清空这个页帧
1326         MMArch::write_bytes(MMArch::phys_2_virt(frame).unwrap(), 0, MMArch::PAGE_SIZE);
1327 
1328         // 设置页表项的flags
1329         let flags: EntryFlags<Arch> =
1330             EntryFlags::new_page_table(virt.kind() == PageTableKind::User);
1331 
1332         table.set_entry(i, PageEntry::new(frame, flags));
1333         table.next_level_table(i)
1334     }
1335 
1336     /// 获取虚拟地址的指定层级页表
1337     /// ## 参数
1338     ///
1339     /// - `virt`: 虚拟地址
1340     /// - `level`: 指定页表层级
1341     ///
1342     /// ## 返回值
1343     /// - Some(PageTable<Arch>): 虚拟地址对应层级的页表
1344     /// - None: 对应页表不存在
get_table(&self, virt: VirtAddr, level: usize) -> Option<PageTable<Arch>>1345     pub fn get_table(&self, virt: VirtAddr, level: usize) -> Option<PageTable<Arch>> {
1346         let mut table = self.table();
1347         if level > Arch::PAGE_LEVELS - 1 {
1348             return None;
1349         }
1350 
1351         unsafe {
1352             loop {
1353                 if table.level == level {
1354                     return Some(table);
1355                 }
1356                 let i = table.index_of(virt)?;
1357                 assert!(i < Arch::PAGE_ENTRY_NUM);
1358 
1359                 table = table.next_level_table(i)?;
1360             }
1361         }
1362     }
1363 
1364     /// 获取虚拟地址在指定层级页表的PageEntry
1365     /// ## 参数
1366     ///
1367     /// - `virt`: 虚拟地址
1368     /// - `level`: 指定页表层级
1369     ///
1370     /// ## 返回值
1371     /// - Some(PageEntry<Arch>): 虚拟地址在指定层级的页表的有效PageEntry
1372     /// - None: 无对应的有效PageEntry
get_entry(&self, virt: VirtAddr, level: usize) -> Option<PageEntry<Arch>>1373     pub fn get_entry(&self, virt: VirtAddr, level: usize) -> Option<PageEntry<Arch>> {
1374         let table = self.get_table(virt, level)?;
1375         let i = table.index_of(virt)?;
1376         let entry = unsafe { table.entry(i) }?;
1377 
1378         if !entry.empty() {
1379             Some(entry)
1380         } else {
1381             None
1382         }
1383 
1384         // let mut table = self.table();
1385         // if level > Arch::PAGE_LEVELS - 1 {
1386         //     return None;
1387         // }
1388         // unsafe {
1389         //     loop {
1390         //         let i = table.index_of(virt)?;
1391         //         assert!(i < Arch::PAGE_ENTRY_NUM);
1392 
1393         //         if table.level == level {
1394         //             let entry = table.entry(i)?;
1395         //             if !entry.empty() {
1396         //                 return Some(entry);
1397         //             } else {
1398         //                 return None;
1399         //             }
1400         //         }
1401 
1402         //         table = table.next_level_table(i)?;
1403         //     }
1404         // }
1405     }
1406 
1407     /// 拷贝用户空间映射
1408     /// ## 参数
1409     ///
1410     /// - `umapper`: 要拷贝的用户空间
1411     /// - `copy_on_write`: 是否写时复制
clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool)1412     pub unsafe fn clone_user_mapping(&mut self, umapper: &mut Self, copy_on_write: bool) {
1413         let old_table = umapper.table();
1414         let new_table = self.table();
1415         let allocator = self.allocator_mut();
1416         // 顶级页表的[0, PAGE_KERNEL_INDEX)项为用户空间映射
1417         for entry_index in 0..Arch::PAGE_KERNEL_INDEX {
1418             if let Some(next_table) = old_table.next_level_table(entry_index) {
1419                 let table = next_table.clone(allocator, copy_on_write).unwrap();
1420                 let old_entry = old_table.entry(entry_index).unwrap();
1421                 let entry = PageEntry::new(table.phys(), old_entry.flags());
1422                 new_table.set_entry(entry_index, entry);
1423             }
1424         }
1425     }
1426 
1427     /// 将物理地址映射到具有线性偏移量的虚拟地址
1428     #[allow(dead_code)]
map_linearly( &mut self, phys: PhysAddr, flags: EntryFlags<Arch>, ) -> Option<(VirtAddr, PageFlush<Arch>)>1429     pub unsafe fn map_linearly(
1430         &mut self,
1431         phys: PhysAddr,
1432         flags: EntryFlags<Arch>,
1433     ) -> Option<(VirtAddr, PageFlush<Arch>)> {
1434         let virt: VirtAddr = Arch::phys_2_virt(phys)?;
1435         return self.map_phys(virt, phys, flags).map(|flush| (virt, flush));
1436     }
1437 
1438     /// 修改虚拟地址的页表项的flags,并返回页表项刷新器
1439     ///
1440     /// 请注意,需要在修改完flags后,调用刷新器的flush方法,才能使修改生效
1441     ///
1442     /// ## 参数
1443     /// - virt 虚拟地址
1444     /// - flags 新的页表项的flags
1445     ///
1446     /// ## 返回值
1447     ///
1448     /// 如果修改成功,返回刷新器,否则返回None
remap( &mut self, virt: VirtAddr, flags: EntryFlags<Arch>, ) -> Option<PageFlush<Arch>>1449     pub unsafe fn remap(
1450         &mut self,
1451         virt: VirtAddr,
1452         flags: EntryFlags<Arch>,
1453     ) -> Option<PageFlush<Arch>> {
1454         return self
1455             .visit(virt, |p1, i| {
1456                 let mut entry = p1.entry(i)?;
1457 
1458                 entry.set_flags(flags);
1459                 p1.set_entry(i, entry);
1460                 Some(PageFlush::new(virt))
1461             })
1462             .flatten();
1463     }
1464 
1465     /// 根据虚拟地址,查找页表,获取对应的物理地址和页表项的flags
1466     ///
1467     /// ## 参数
1468     ///
1469     /// - virt 虚拟地址
1470     ///
1471     /// ## 返回值
1472     ///
1473     /// 如果查找成功,返回物理地址和页表项的flags,否则返回None
translate(&self, virt: VirtAddr) -> Option<(PhysAddr, EntryFlags<Arch>)>1474     pub fn translate(&self, virt: VirtAddr) -> Option<(PhysAddr, EntryFlags<Arch>)> {
1475         let entry: PageEntry<Arch> = self.visit(virt, |p1, i| unsafe { p1.entry(i) })??;
1476         let paddr = entry.address().ok()?;
1477         let flags = entry.flags();
1478         return Some((paddr, flags));
1479     }
1480 
1481     /// 取消虚拟地址的映射,释放页面,并返回页表项刷新器
1482     ///
1483     /// 请注意,需要在取消映射后,调用刷新器的flush方法,才能使修改生效
1484     ///
1485     /// ## 参数
1486     ///
1487     /// - virt 虚拟地址
1488     /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
1489     ///
1490     /// ## 返回值
1491     /// 如果取消成功,返回刷新器,否则返回None
1492     #[allow(dead_code)]
unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>>1493     pub unsafe fn unmap(&mut self, virt: VirtAddr, unmap_parents: bool) -> Option<PageFlush<Arch>> {
1494         let (paddr, _, flusher) = self.unmap_phys(virt, unmap_parents)?;
1495         self.frame_allocator.free_one(paddr);
1496         return Some(flusher);
1497     }
1498 
1499     /// 取消虚拟地址的映射,并返回物理地址和页表项的flags
1500     ///
1501     /// ## 参数
1502     ///
1503     /// - vaddr 虚拟地址
1504     /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
1505     ///
1506     /// ## 返回值
1507     ///
1508     /// 如果取消成功,返回物理地址和页表项的flags,否则返回None
unmap_phys( &mut self, virt: VirtAddr, unmap_parents: bool, ) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>)>1509     pub unsafe fn unmap_phys(
1510         &mut self,
1511         virt: VirtAddr,
1512         unmap_parents: bool,
1513     ) -> Option<(PhysAddr, EntryFlags<Arch>, PageFlush<Arch>)> {
1514         if !virt.check_aligned(Arch::PAGE_SIZE) {
1515             error!("Try to unmap unaligned page: virt={:?}", virt);
1516             return None;
1517         }
1518 
1519         let table = self.table();
1520         return unmap_phys_inner(virt, &table, unmap_parents, self.allocator_mut())
1521             .map(|(paddr, flags)| (paddr, flags, PageFlush::<Arch>::new(virt)));
1522     }
1523 
1524     /// 在页表中,访问虚拟地址对应的页表项,并调用传入的函数F
visit<T>( &self, virt: VirtAddr, f: impl FnOnce(&mut PageTable<Arch>, usize) -> T, ) -> Option<T>1525     fn visit<T>(
1526         &self,
1527         virt: VirtAddr,
1528         f: impl FnOnce(&mut PageTable<Arch>, usize) -> T,
1529     ) -> Option<T> {
1530         let mut table = self.table();
1531         unsafe {
1532             loop {
1533                 let i = table.index_of(virt)?;
1534                 if table.level() == 0 {
1535                     return Some(f(&mut table, i));
1536                 } else {
1537                     table = table.next_level_table(i)?;
1538                 }
1539             }
1540         }
1541     }
1542 }
1543 
1544 /// 取消页面映射,返回被取消映射的页表项的:【物理地址】和【flags】
1545 ///
1546 /// ## 参数
1547 ///
1548 /// - vaddr 虚拟地址
1549 /// - table 页表
1550 /// - unmap_parents 是否在父页表内,取消空闲子页表的映射
1551 /// - allocator 页面分配器(如果页表从这个分配器分配,那么在取消映射时,也需要归还到这个分配器内)
1552 ///
1553 /// ## 返回值
1554 ///
1555 /// 如果取消成功,返回被取消映射的页表项的:【物理地址】和【flags】,否则返回None
unmap_phys_inner<Arch: MemoryManagementArch>( vaddr: VirtAddr, table: &PageTable<Arch>, unmap_parents: bool, allocator: &mut impl FrameAllocator, ) -> Option<(PhysAddr, EntryFlags<Arch>)>1556 unsafe fn unmap_phys_inner<Arch: MemoryManagementArch>(
1557     vaddr: VirtAddr,
1558     table: &PageTable<Arch>,
1559     unmap_parents: bool,
1560     allocator: &mut impl FrameAllocator,
1561 ) -> Option<(PhysAddr, EntryFlags<Arch>)> {
1562     // 获取页表项的索引
1563     let i = table.index_of(vaddr)?;
1564 
1565     // 如果当前是最后一级页表,直接取消页面映射
1566     if table.level() == 0 {
1567         let entry = table.entry(i)?;
1568         table.set_entry(i, PageEntry::from_usize(0));
1569         return Some((entry.address().ok()?, entry.flags()));
1570     }
1571 
1572     let subtable = table.next_level_table(i)?;
1573     // 递归地取消映射
1574     let result = unmap_phys_inner(vaddr, &subtable, unmap_parents, allocator)?;
1575 
1576     // TODO: This is a bad idea for architectures where the kernel mappings are done in the process tables,
1577     // as these mappings may become out of sync
1578     if unmap_parents {
1579         // 如果子页表已经没有映射的页面了,就取消子页表的映射
1580 
1581         // 检查子页表中是否还有映射的页面
1582         let x = (0..Arch::PAGE_ENTRY_NUM)
1583             .map(|k| subtable.entry(k).expect("invalid page entry"))
1584             .any(|e| e.present());
1585         if !x {
1586             // 如果没有,就取消子页表的映射
1587             table.set_entry(i, PageEntry::from_usize(0));
1588             // 释放子页表
1589             allocator.free_one(subtable.phys());
1590         }
1591     }
1592 
1593     return Some(result);
1594 }
1595 
1596 impl<Arch, F: Debug> Debug for PageMapper<Arch, F> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result1597     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1598         f.debug_struct("PageMapper")
1599             .field("table_paddr", &self.table_paddr)
1600             .field("frame_allocator", &self.frame_allocator)
1601             .finish()
1602     }
1603 }
1604 
1605 /// 页表刷新器的trait
1606 pub trait Flusher<Arch: MemoryManagementArch> {
1607     /// 取消对指定的page flusher的刷新
consume(&mut self, flush: PageFlush<Arch>)1608     fn consume(&mut self, flush: PageFlush<Arch>);
1609 }
1610 
1611 /// 用于刷新某个虚拟地址的刷新器。这个刷新器一经产生,就必须调用flush()方法,
1612 /// 否则会造成对页表的更改被忽略,这是不安全的
1613 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
1614 pub struct PageFlush<Arch: MemoryManagementArch> {
1615     virt: VirtAddr,
1616     phantom: PhantomData<Arch>,
1617 }
1618 
1619 impl<Arch: MemoryManagementArch> PageFlush<Arch> {
new(virt: VirtAddr) -> Self1620     pub fn new(virt: VirtAddr) -> Self {
1621         return Self {
1622             virt,
1623             phantom: PhantomData,
1624         };
1625     }
1626 
flush(self)1627     pub fn flush(self) {
1628         unsafe { Arch::invalidate_page(self.virt) };
1629     }
1630 
1631     /// 忽略掉这个刷新器
ignore(self)1632     pub unsafe fn ignore(self) {
1633         mem::forget(self);
1634     }
1635 }
1636 
1637 impl<Arch: MemoryManagementArch> Drop for PageFlush<Arch> {
drop(&mut self)1638     fn drop(&mut self) {
1639         unsafe {
1640             MMArch::invalidate_page(self.virt);
1641         }
1642     }
1643 }
1644 
1645 /// 用于刷新整个页表的刷新器。这个刷新器一经产生,就必须调用flush()方法,
1646 /// 否则会造成对页表的更改被忽略,这是不安全的
1647 #[must_use = "The flusher must call the 'flush()', or the changes to page table will be unsafely ignored."]
1648 pub struct PageFlushAll<Arch: MemoryManagementArch> {
1649     phantom: PhantomData<fn() -> Arch>,
1650 }
1651 
1652 #[allow(dead_code)]
1653 impl<Arch: MemoryManagementArch> PageFlushAll<Arch> {
new() -> Self1654     pub fn new() -> Self {
1655         return Self {
1656             phantom: PhantomData,
1657         };
1658     }
1659 
flush(self)1660     pub fn flush(self) {
1661         unsafe { Arch::invalidate_all() };
1662     }
1663 
1664     /// 忽略掉这个刷新器
ignore(self)1665     pub unsafe fn ignore(self) {
1666         mem::forget(self);
1667     }
1668 }
1669 
1670 impl<Arch: MemoryManagementArch> Flusher<Arch> for PageFlushAll<Arch> {
1671     /// 为page flush all 实现consume,消除对单个页面的刷新。(刷新整个页表了就不需要刷新单个页面了)
consume(&mut self, flush: PageFlush<Arch>)1672     fn consume(&mut self, flush: PageFlush<Arch>) {
1673         unsafe { flush.ignore() };
1674     }
1675 }
1676 
1677 impl<Arch: MemoryManagementArch, T: Flusher<Arch> + ?Sized> Flusher<Arch> for &mut T {
1678     /// 允许一个flusher consume掉另一个flusher
consume(&mut self, flush: PageFlush<Arch>)1679     fn consume(&mut self, flush: PageFlush<Arch>) {
1680         <T as Flusher<Arch>>::consume(self, flush);
1681     }
1682 }
1683 
1684 impl<Arch: MemoryManagementArch> Flusher<Arch> for () {
consume(&mut self, _flush: PageFlush<Arch>)1685     fn consume(&mut self, _flush: PageFlush<Arch>) {}
1686 }
1687 
1688 impl<Arch: MemoryManagementArch> Drop for PageFlushAll<Arch> {
drop(&mut self)1689     fn drop(&mut self) {
1690         unsafe {
1691             Arch::invalidate_all();
1692         }
1693     }
1694 }
1695 
1696 /// 未在当前CPU上激活的页表的刷新器
1697 ///
1698 /// 如果页表没有在当前cpu上激活,那么需要发送ipi到其他核心,尝试在其他核心上刷新页表
1699 ///
1700 /// TODO: 这个方式很暴力,也许把它改成在指定的核心上刷新页表会更好。(可以测试一下开销)
1701 #[derive(Debug)]
1702 pub struct InactiveFlusher;
1703 
1704 impl InactiveFlusher {
new() -> Self1705     pub fn new() -> Self {
1706         return Self {};
1707     }
1708 }
1709 
1710 impl Flusher<MMArch> for InactiveFlusher {
consume(&mut self, flush: PageFlush<MMArch>)1711     fn consume(&mut self, flush: PageFlush<MMArch>) {
1712         unsafe {
1713             flush.ignore();
1714         }
1715     }
1716 }
1717 
1718 impl Drop for InactiveFlusher {
drop(&mut self)1719     fn drop(&mut self) {
1720         // 发送刷新页表的IPI
1721         send_ipi(IpiKind::FlushTLB, IpiTarget::Other);
1722     }
1723 }
1724 
1725 /// # 把一个地址向下对齐到页大小
round_down_to_page_size(addr: usize) -> usize1726 pub fn round_down_to_page_size(addr: usize) -> usize {
1727     addr & !(MMArch::PAGE_SIZE - 1)
1728 }
1729 
1730 /// # 把一个地址向上对齐到页大小
round_up_to_page_size(addr: usize) -> usize1731 pub fn round_up_to_page_size(addr: usize) -> usize {
1732     round_down_to_page_size(addr + MMArch::PAGE_SIZE - 1)
1733 }
1734