Skip to main content

page_table_generic/
table.rs

1use core::ops::{Deref, DerefMut};
2
3use crate::{
4    FrameAllocator, PageTableEntry, PagingError, PagingResult, PhysAddr, TableMeta, VirtAddr,
5    frame::Frame,
6    map::{MapConfig, MapRecursiveConfig, UnmapConfig, UnmapRecursiveConfig},
7    walk::{PageTableWalker, WalkConfig},
8};
9
10pub struct PageTable<T: TableMeta, A: FrameAllocator> {
11    inner: PageTableRef<T, A>,
12}
13
14impl<T: TableMeta, A: FrameAllocator> PageTable<T, A> {
15    pub const VALID_BITS: usize = Frame::<T, A>::PT_VALID_BITS;
16
17    /// 创建一个新的页表
18    pub fn new(allocator: A) -> PagingResult<Self> {
19        let inner = unsafe { PageTableRef::new(allocator) }?;
20        Ok(Self { inner })
21    }
22
23    pub fn valid_bits(&self) -> usize {
24        Frame::<T, A>::PT_VALID_BITS
25    }
26}
27
28impl<T: TableMeta, A: FrameAllocator> Drop for PageTable<T, A> {
29    fn drop(&mut self) {
30        unsafe {
31            // 释放所有页表帧,但不释放映射的物理页
32            self.deallocate();
33        }
34    }
35}
36
37impl<T: TableMeta, A: FrameAllocator> Deref for PageTable<T, A> {
38    type Target = PageTableRef<T, A>;
39
40    fn deref(&self) -> &Self::Target {
41        &self.inner
42    }
43}
44
45impl<T: TableMeta, A: FrameAllocator> DerefMut for PageTable<T, A> {
46    fn deref_mut(&mut self) -> &mut Self::Target {
47        &mut self.inner
48    }
49}
50
51#[derive(Clone, Copy)]
52pub struct PageTableRef<T: TableMeta, A: FrameAllocator> {
53    pub root: Frame<T, A>,
54}
55
56impl<T: TableMeta, A: FrameAllocator> core::fmt::Debug for PageTableRef<T, A>
57where
58    T::P: core::fmt::Debug,
59{
60    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
61        f.debug_struct("PageTable")
62            .field("root_paddr", &format_args!("{:#x}", self.root.paddr.raw()))
63            .field("table_levels", &T::LEVEL_BITS.len())
64            .field("max_block_level", &T::MAX_BLOCK_LEVEL)
65            .field("page_size", &format_args!("{:#x}", T::PAGE_SIZE))
66            .finish()
67    }
68}
69
70impl<T: TableMeta, A: FrameAllocator> PageTableRef<T, A> {
71    /// 创建一个新的页表
72    ///
73    /// # Safety
74    ///
75    /// 调用者必须确保提供的FrameAllocator是有效的,并且在页表生命周期内保持有效
76    pub unsafe fn new(allocator: A) -> PagingResult<Self> {
77        let root = Frame::new(allocator)?;
78        Ok(Self { root })
79    }
80
81    pub fn from_paddr(paddr: PhysAddr, allocator: A) -> Self {
82        let root = Frame::from_paddr(paddr, allocator);
83        Self { root }
84    }
85
86    /// 映射虚拟地址范围到物理地址范围
87    pub fn map(&mut self, config: &MapConfig) -> PagingResult {
88        // 验证输入参数
89        self.validate_map_config(config)?;
90
91        // 检查大小溢出
92        if config.vaddr.raw().checked_add(config.size).is_none()
93            || config.paddr.raw().checked_add(config.size).is_none()
94        {
95            return Err(PagingError::address_overflow(
96                "Virtual or physical address overflow",
97            ));
98        }
99
100        self.root.map_range_recursive(MapRecursiveConfig {
101            start_vaddr: config.vaddr,
102            start_paddr: config.paddr,
103            end_vaddr: config.vaddr + config.size,
104            level: Frame::<T, A>::PT_LEVEL,
105            allow_huge: config.allow_huge,
106            flush: config.flush,
107            pte_template: config.pte,
108        })?;
109
110        Ok(())
111    }
112
113    /// 取消映射虚拟地址范围
114    ///
115    /// # 参数
116    /// - `start_vaddr`: 要取消映射的起始虚拟地址
117    /// - `size`: 要取消映射的大小(字节)
118    ///
119    /// # 返回值
120    /// - `Ok(())`: 取消映射成功
121    /// - `Err(PagingError)`: 取消映射失败
122    ///
123    /// # 行为
124    /// - 清除指定虚拟地址范围内的所有页表项
125    /// - 自动回收空的子页表帧
126    /// - 支持大页和普通页面的取消映射
127    /// - 根据配置刷新TLB
128    pub fn unmap(&mut self, start_vaddr: VirtAddr, size: usize) -> PagingResult<()> {
129        // 验证输入参数
130        self.validate_unmap_params(start_vaddr, size)?;
131
132        // 检查大小溢出
133        let end_vaddr: VirtAddr = match start_vaddr.raw().checked_add(size) {
134            Some(end) => VirtAddr::new(end),
135            None => {
136                return Err(PagingError::address_overflow(
137                    "Virtual address overflow in unmap",
138                ));
139            }
140        };
141
142        self.root.unmap_range_recursive(UnmapRecursiveConfig {
143            start_vaddr,
144            end_vaddr,
145            level: Frame::<T, A>::PT_LEVEL,
146            flush: true, // 默认刷新TLB确保一致性
147        })?;
148
149        Ok(())
150    }
151
152    /// 使用配置对象取消映射
153    pub fn unmap_with_config(&mut self, config: &UnmapConfig) -> PagingResult<()> {
154        self.validate_unmap_params(config.start_vaddr, config.size)?;
155
156        let end_vaddr = match config.start_vaddr.raw().checked_add(config.size) {
157            Some(end) => VirtAddr::new(end),
158            None => {
159                return Err(PagingError::address_overflow(
160                    "Virtual address overflow in unmap_with_config",
161                ));
162            }
163        };
164
165        self.root.unmap_range_recursive(UnmapRecursiveConfig {
166            start_vaddr: config.start_vaddr,
167            end_vaddr,
168            level: Frame::<T, A>::PT_LEVEL,
169            flush: config.flush,
170        })?;
171
172        Ok(())
173    }
174
175    /// 验证取消映射参数的有效性
176    fn validate_unmap_params(&self, start_vaddr: VirtAddr, size: usize) -> PagingResult<()> {
177        if size == 0 {
178            return Err(PagingError::invalid_size("Size cannot be zero in unmap"));
179        }
180
181        // 检查虚拟地址是否页对齐
182        if !start_vaddr.raw().is_multiple_of(T::PAGE_SIZE) {
183            return Err(PagingError::alignment_error(
184                "Start virtual address not page aligned in unmap",
185            ));
186        }
187
188        // 检查大小是否页对齐
189        if !size.is_multiple_of(T::PAGE_SIZE) {
190            return Err(PagingError::alignment_error(
191                "Size not page aligned in unmap",
192            ));
193        }
194
195        Ok(())
196    }
197
198    /// 创建页表遍历迭代器
199    pub fn walk_all(&self, config: WalkConfig) -> PageTableWalker<'_, T, A> {
200        PageTableWalker::new(self, config)
201    }
202
203    pub fn walk(
204        &self,
205        start_vaddr: VirtAddr,
206        end_vaddr: VirtAddr,
207    ) -> impl Iterator<Item = crate::walk::PteInfo<T::P>> + '_ {
208        let config = WalkConfig {
209            start_vaddr,
210            end_vaddr,
211        };
212        PageTableWalker::new(self, config).filter(|p| p.pte.to_config(false).valid)
213    }
214
215    /// 遍历所有有效的最终映射页表项(过滤掉无效项和中间级别的页表指针)
216    pub fn walk_valid(&self) -> impl Iterator<Item = crate::walk::PteInfo<T::P>> + '_ {
217        self.walk(0.into(), usize::MAX.into()).filter(|p| {
218            let config = p.pte.to_config(false);
219            config.valid && p.is_final_mapping
220        })
221    }
222
223    /// 验证映射配置的有效性
224    fn validate_map_config(&self, config: &MapConfig) -> PagingResult {
225        if config.size == 0 {
226            return Err(PagingError::invalid_size("Size cannot be zero"));
227        }
228
229        // 检查虚拟地址和物理地址是否页对齐
230        if !config.vaddr.raw().is_multiple_of(T::PAGE_SIZE) {
231            return Err(PagingError::alignment_error(
232                "Virtual address not page aligned",
233            ));
234        }
235
236        if !config.paddr.raw().is_multiple_of(T::PAGE_SIZE) {
237            return Err(PagingError::alignment_error(
238                "Physical address not page aligned",
239            ));
240        }
241
242        Ok(())
243    }
244
245    pub const fn page_size() -> usize {
246        T::PAGE_SIZE
247    }
248
249    pub const fn table_levels() -> usize {
250        T::LEVEL_BITS.len()
251    }
252
253    pub const fn valid_bits() -> usize {
254        Frame::<T, A>::PT_VALID_BITS
255    }
256
257    /// 销毁整个页表结构
258    ///
259    /// 此方法会:
260    /// 1. 递归释放根帧及所有子页表帧
261    /// 2. 清除所有页表项(设为invalid)
262    /// 3. 不释放映射的物理页(数据页/大页)
263    ///
264    /// # Safety
265    /// 调用者必须确保:
266    /// - 没有其他代码在访问这个页表
267    /// - 没有CPU正在使用这个页表进行地址翻译
268    /// - 调用后不再使用这个PageTable实例
269    pub unsafe fn destroy(mut self) {
270        self.root.deallocate_recursive(Frame::<T, A>::PT_LEVEL);
271    }
272
273    /// 释放页表占用的所有页表帧
274    ///
275    /// 与destroy()不同,这个方法保留PageTable结构,
276    /// 但释放所有关联的页表帧。调用后PageTable不再可用。
277    ///
278    /// 释放行为:
279    /// - 释放所有页表帧
280    /// - 清除所有页表项(设为invalid)
281    /// - 不释放映射的物理页(数据页/大页)
282    ///
283    /// # Safety
284    /// 调用者必须确保:
285    /// - 没有其他代码在访问这个页表
286    /// - 没有CPU正在使用这个页表进行地址翻译
287    pub unsafe fn deallocate(&mut self) {
288        self.root.deallocate_recursive(Frame::<T, A>::PT_LEVEL);
289    }
290
291    /// 释放页表中的指定映射区域
292    ///
293    /// 释放指定虚拟地址范围内的所有页表项和子页表帧
294    /// 在释放前将相关PTE设为invalid
295    pub fn deallocate_range(&mut self, start_vaddr: VirtAddr, end_vaddr: VirtAddr) -> PagingResult {
296        if start_vaddr >= end_vaddr {
297            return Err(PagingError::invalid_range(
298                "Start address must be less than end address",
299            ));
300        }
301
302        // TODO: 实现范围释放逻辑
303        // 这里需要实现:
304        // 1. 遍历指定虚拟地址范围
305        // 2. 释放对应的页表项和子页表
306        // 3. 处理部分页表项的情况
307
308        Ok(())
309    }
310
311    /// 通过虚拟地址查询页表项
312    ///
313    /// # 参数
314    /// - `vaddr`: 要查询的虚拟地址
315    ///
316    /// # 返回值
317    /// - `Ok(T::P)`: 找到的页表项,包含物理地址信息
318    /// - `Err(PagingError)`: 查询失败,原因可能包括:
319    ///   - 地址未映射
320    ///   - 页表项无效
321    ///   - 页表层次结构错误
322    ///
323    pub fn translate(&self, vaddr: VirtAddr) -> PagingResult<(PhysAddr, T::P)> {
324        let (pte, level) = self
325            .root
326            .translate_recursive_with_level(vaddr, Frame::<T, A>::PT_LEVEL)?;
327
328        let pte_config = pte.to_config(level > 1);
329
330        // 根据页表项类型计算正确的偏移
331        let (phys_addr, _) = if pte_config.huge {
332            // 大页映射:需要使用实际级别的大小来计算偏移
333            let level_size = Frame::<T, A>::level_size(level);
334            let offset_in_page = vaddr.raw() % level_size;
335            (
336                PhysAddr::new(pte_config.paddr.raw() + offset_in_page),
337                level_size,
338            )
339        } else {
340            // 普通页面映射:使用页面大小
341            let offset_in_page = vaddr.raw() % T::PAGE_SIZE;
342            (
343                PhysAddr::new(pte_config.paddr.raw() + offset_in_page),
344                T::PAGE_SIZE,
345            )
346        };
347
348        Ok((phys_addr, pte))
349    }
350
351    /// 通过虚拟地址查询物理地址(便利方法)
352    ///
353    /// # 参数
354    /// - `vaddr`: 要查询的虚拟地址
355    ///
356    /// # 返回值
357    /// - `Ok(PhysAddr)`: 找到的物理地址
358    /// - `Err(PagingError)`: 查询失败
359    ///
360    pub fn translate_phys(&self, vaddr: VirtAddr) -> PagingResult<PhysAddr> {
361        let (p, _) = self.translate(vaddr)?;
362        Ok(p)
363    }
364
365    /// 检查虚拟地址是否已映射
366    ///
367    /// 这是一个便利方法,用于快速检查地址是否已映射而不需要获取页表项
368    ///
369    /// # 参数
370    /// - `vaddr`: 要检查的虚拟地址
371    ///
372    /// # 返回值
373    /// - `true`: 地址已映射
374    /// - `false`: 地址未映射
375    pub fn is_mapped(&self, vaddr: VirtAddr) -> bool {
376        self.translate(vaddr).is_ok()
377    }
378
379    /// 获取页表的根帧物理地址
380    pub fn root_paddr(&self) -> crate::PhysAddr {
381        self.root.paddr
382    }
383}