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