Skip to main content

page_table_generic/
lib.rs

1#![no_std]
2
3use core::fmt::Debug;
4
5mod def;
6pub mod frame;
7mod map;
8mod table;
9mod walk;
10
11pub use def::*;
12pub use frame::Frame;
13pub use map::*;
14pub use table::*;
15pub use walk::*;
16
17pub type PagingResult<T = ()> = Result<T, PagingError>;
18
19pub trait FrameAllocator: Clone + Sync + Send + 'static {
20    fn alloc_frame(&self) -> Option<PhysAddr>;
21
22    fn dealloc_frame(&self, frame: PhysAddr);
23
24    fn phys_to_virt(&self, paddr: PhysAddr) -> *mut u8;
25
26    fn alloc_frames(&self, frames: usize, _align: usize) -> Option<PhysAddr> {
27        if frames == 1 {
28            self.alloc_frame()
29        } else {
30            None
31        }
32    }
33
34    fn dealloc_frames(&self, start: PhysAddr, frames: usize, frame_size: usize) {
35        if frames == 1 {
36            self.dealloc_frame(start);
37            return;
38        }
39        for i in 0..frames {
40            self.dealloc_frame(PhysAddr::new(start.raw() + i * frame_size));
41        }
42    }
43}
44
45pub trait TableMeta: Sync + Send + Clone + Copy + 'static {
46    type P: PageTableEntry;
47
48    /// 页面大小(支持4KB、16KB、64KB等)
49    const PAGE_SIZE: usize;
50
51    /// 各级索引位数数组,从最高级到最低级
52    const LEVEL_BITS: &[usize];
53
54    /// 大页最高支持的级别
55    const MAX_BLOCK_LEVEL: usize;
56
57    /// Whether addresses must fit the address width described by [`LEVEL_BITS`].
58    const STRICT_ADDRESS_WIDTH: bool = false;
59
60    /// 刷新TLB
61    fn flush(vaddr: Option<VirtAddr>);
62}
63
64pub trait PageTableEntry: Debug + Sync + Send + Clone + Copy + Sized + 'static {
65    /// 从 PteConfig 创建页表项
66    ///
67    /// # 参数
68    /// - `config`: 包含所有页表项配置的结构
69    ///
70    /// # 返回
71    /// 新的页表项实例
72    fn from_config(config: PteConfig) -> Self;
73
74    /// 将页表项转换为 PteConfig
75    ///
76    /// # 参数
77    /// - `is_dir`: 是否为目录项(影响物理地址布局解析)
78    ///   - true: 目录项(可能包含大页映射或子页表指针)
79    ///   - false: 页表项(叶子级别,基本页映射)
80    ///
81    /// # 返回
82    /// 包含当前页表项所有状态的 PteConfig
83    fn to_config(&self, is_dir: bool) -> PteConfig;
84
85    fn valid(&self) -> bool;
86}
87
88pub trait PageTableOp: Send + 'static {
89    fn addr(&self) -> PhysAddr;
90    fn map(&mut self, config: &MapConfig) -> PagingResult;
91    fn unmap(&mut self, virt_start: VirtAddr, size: usize) -> Result<(), PagingError>;
92}
93
94impl<T: TableMeta, A: FrameAllocator> PageTableOp for PageTable<T, A> {
95    fn addr(&self) -> PhysAddr {
96        self.root_paddr()
97    }
98
99    fn map(&mut self, config: &MapConfig) -> PagingResult {
100        PageTableRef::map(self, config)
101    }
102
103    fn unmap(&mut self, virt_start: VirtAddr, size: usize) -> PagingResult {
104        PageTableRef::unmap(self, virt_start, size)
105    }
106}
107
108impl<T: TableMeta, A: FrameAllocator> PageTableOp for PageTableRef<T, A> {
109    fn addr(&self) -> PhysAddr {
110        self.root_paddr()
111    }
112
113    fn map(&mut self, config: &MapConfig) -> PagingResult {
114        self.map(config)
115    }
116
117    fn unmap(&mut self, virt_start: VirtAddr, size: usize) -> Result<(), PagingError> {
118        self.unmap(virt_start, size)
119    }
120}