page_table/table/
mod.rs

1mod fmt;
2mod pos;
3mod visit;
4
5use crate::{Pte, VmMeta, VPN};
6use core::{
7    ops::{Index, IndexMut, Range},
8    ptr::NonNull,
9};
10use visit::{walk_inner, walk_inner_mut};
11
12pub use fmt::PageTableFormatter;
13pub use pos::Pos;
14pub use visit::{Decorator, Update, Visitor};
15
16/// 页表。
17///
18/// 不持有页表的所有权,因为页表总是在一些物理页帧上。
19pub struct PageTable<Meta: VmMeta> {
20    mem: &'static mut [Pte<Meta>],
21    base: VPN<Meta>,
22    level: usize,
23}
24
25impl<Meta: VmMeta> PageTable<Meta> {
26    /// 从指向第一个页表项的指针创建页表。
27    ///
28    /// # Safety
29    ///
30    /// 同 [from_raw_parts_mut](core::slice::from_raw_parts_mut).
31    #[inline]
32    pub unsafe fn from_raw_parts(ptr: NonNull<Pte<Meta>>, base: VPN<Meta>, level: usize) -> Self {
33        Self {
34            // 显然需要 level <= Meta::MAX_LEVEL
35            mem: core::slice::from_raw_parts_mut(ptr.as_ptr(), 1 << Meta::LEVEL_BITS[level]),
36            base: base.floor(level),
37            level,
38        }
39    }
40
41    /// 从指向根页表的指针创建页表。
42    ///
43    /// # Safety
44    ///
45    /// 同 [from_raw_parts_mut](core::slice::from_raw_parts_mut).
46    #[inline]
47    pub unsafe fn from_root(root: NonNull<Pte<Meta>>) -> Self {
48        Self::from_raw_parts(root, VPN::ZERO, Meta::MAX_LEVEL)
49    }
50
51    /// 获取指向第一个页表项的指针。
52    #[inline]
53    pub const fn as_ptr(&self) -> *const Pte<Meta> {
54        self.mem.as_ptr()
55    }
56
57    /// 获取页表级别。
58    #[inline]
59    pub const fn level(&self) -> usize {
60        self.level
61    }
62
63    /// 获取页表容纳的虚页号范围。
64    #[inline]
65    pub fn range(&self) -> Range<VPN<Meta>> {
66        self.base..self.base + Meta::pages_in_table(self.level)
67    }
68
69    /// 使用访问器 `visitor` 遍历页表。
70    #[inline]
71    pub fn walk(&self, mut target: Pos<Meta>, visitor: &mut impl Visitor<Meta>) {
72        walk_inner(self, visitor, &mut target);
73    }
74
75    /// 使用访问器 `visitor` 遍历并修改页表。
76    #[inline]
77    pub fn walk_mut(&mut self, mut target: Pos<Meta>, visitor: &mut impl Decorator<Meta>) {
78        walk_inner_mut(self, visitor, &mut target);
79    }
80}
81
82impl<Meta: VmMeta> Index<usize> for PageTable<Meta> {
83    type Output = Pte<Meta>;
84
85    #[inline]
86    fn index(&self, index: usize) -> &Self::Output {
87        &self.mem[index]
88    }
89}
90
91impl<Meta: VmMeta> IndexMut<usize> for PageTable<Meta> {
92    #[inline]
93    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
94        &mut self.mem[index]
95    }
96}