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_root(allocator)?;
78        Ok(Self { root })
79    }
80
81    pub fn from_paddr(paddr: PhysAddr, allocator: A) -> Self {
82        let root = Frame::from_root_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        self.validate_address_width(config.vaddr, config.size, "map")?;
100
101        self.root.map_range_recursive(MapRecursiveConfig {
102            start_vaddr: config.vaddr,
103            start_paddr: config.paddr,
104            end_vaddr: config.vaddr + config.size,
105            level: Frame::<T, A>::PT_LEVEL,
106            allow_huge: config.allow_huge,
107            flush: config.flush,
108            pte_template: config.pte,
109        })?;
110
111        Ok(())
112    }
113
114    /// 取消映射虚拟地址范围
115    ///
116    /// # 参数
117    /// - `start_vaddr`: 要取消映射的起始虚拟地址
118    /// - `size`: 要取消映射的大小(字节)
119    ///
120    /// # 返回值
121    /// - `Ok(())`: 取消映射成功
122    /// - `Err(PagingError)`: 取消映射失败
123    ///
124    /// # 行为
125    /// - 清除指定虚拟地址范围内的所有页表项
126    /// - 自动回收空的子页表帧
127    /// - 支持大页和普通页面的取消映射
128    /// - 根据配置刷新TLB
129    pub fn unmap(&mut self, start_vaddr: VirtAddr, size: usize) -> PagingResult<()> {
130        // 验证输入参数
131        self.validate_unmap_params(start_vaddr, size)?;
132
133        // 检查大小溢出
134        let end_vaddr: VirtAddr = match start_vaddr.raw().checked_add(size) {
135            Some(end) => VirtAddr::new(end),
136            None => {
137                return Err(PagingError::address_overflow(
138                    "Virtual address overflow in unmap",
139                ));
140            }
141        };
142        self.validate_address_width(start_vaddr, size, "unmap")?;
143
144        self.root.unmap_range_recursive(UnmapRecursiveConfig {
145            start_vaddr,
146            end_vaddr,
147            level: Frame::<T, A>::PT_LEVEL,
148            flush: true, // 默认刷新TLB确保一致性
149        })?;
150
151        Ok(())
152    }
153
154    /// 使用配置对象取消映射
155    pub fn unmap_with_config(&mut self, config: &UnmapConfig) -> PagingResult<()> {
156        self.validate_unmap_params(config.start_vaddr, config.size)?;
157
158        let end_vaddr = match config.start_vaddr.raw().checked_add(config.size) {
159            Some(end) => VirtAddr::new(end),
160            None => {
161                return Err(PagingError::address_overflow(
162                    "Virtual address overflow in unmap_with_config",
163                ));
164            }
165        };
166        self.validate_address_width(config.start_vaddr, config.size, "unmap_with_config")?;
167
168        self.root.unmap_range_recursive(UnmapRecursiveConfig {
169            start_vaddr: config.start_vaddr,
170            end_vaddr,
171            level: Frame::<T, A>::PT_LEVEL,
172            flush: config.flush,
173        })?;
174
175        Ok(())
176    }
177
178    /// 验证取消映射参数的有效性
179    fn validate_unmap_params(&self, start_vaddr: VirtAddr, size: usize) -> PagingResult<()> {
180        if size == 0 {
181            return Err(PagingError::invalid_size("Size cannot be zero in unmap"));
182        }
183
184        // 检查虚拟地址是否页对齐
185        if !start_vaddr.raw().is_multiple_of(T::PAGE_SIZE) {
186            return Err(PagingError::alignment_error(
187                "Start virtual address not page aligned in unmap",
188            ));
189        }
190
191        // 检查大小是否页对齐
192        if !size.is_multiple_of(T::PAGE_SIZE) {
193            return Err(PagingError::alignment_error(
194                "Size not page aligned in unmap",
195            ));
196        }
197
198        Ok(())
199    }
200
201    /// 创建页表遍历迭代器
202    pub fn walk_all(&self, config: WalkConfig) -> PageTableWalker<'_, T, A> {
203        PageTableWalker::new(self, config)
204    }
205
206    pub fn walk(
207        &self,
208        start_vaddr: VirtAddr,
209        end_vaddr: VirtAddr,
210    ) -> impl Iterator<Item = crate::walk::PteInfo<T::P>> + '_ {
211        let config = WalkConfig {
212            start_vaddr,
213            end_vaddr,
214        };
215        PageTableWalker::new(self, config).filter(|p| p.pte.to_config(false).valid)
216    }
217
218    /// 遍历所有有效的最终映射页表项(过滤掉无效项和中间级别的页表指针)
219    pub fn walk_valid(&self) -> impl Iterator<Item = crate::walk::PteInfo<T::P>> + '_ {
220        self.walk(0.into(), usize::MAX.into()).filter(|p| {
221            let config = p.pte.to_config(false);
222            config.valid && p.is_final_mapping
223        })
224    }
225
226    /// 验证映射配置的有效性
227    fn validate_map_config(&self, config: &MapConfig) -> PagingResult {
228        if config.size == 0 {
229            return Err(PagingError::invalid_size("Size cannot be zero"));
230        }
231
232        // 检查虚拟地址和物理地址是否页对齐
233        if !config.vaddr.raw().is_multiple_of(T::PAGE_SIZE) {
234            return Err(PagingError::alignment_error(
235                "Virtual address not page aligned",
236            ));
237        }
238
239        if !config.paddr.raw().is_multiple_of(T::PAGE_SIZE) {
240            return Err(PagingError::alignment_error(
241                "Physical address not page aligned",
242            ));
243        }
244
245        Ok(())
246    }
247
248    fn validate_address_width(
249        &self,
250        start_vaddr: VirtAddr,
251        size: usize,
252        operation: &'static str,
253    ) -> PagingResult<()> {
254        if !T::STRICT_ADDRESS_WIDTH {
255            return Ok(());
256        }
257        let Some(end) = start_vaddr.raw().checked_add(size) else {
258            return Err(PagingError::address_overflow(
259                "Virtual address range overflow",
260            ));
261        };
262        let last = end.saturating_sub(1);
263        if !Self::is_addr_in_width(start_vaddr.raw()) || !Self::is_addr_in_width(last) {
264            return Err(PagingError::address_overflow(operation));
265        }
266        Ok(())
267    }
268
269    pub const fn page_size() -> usize {
270        T::PAGE_SIZE
271    }
272
273    pub const fn table_levels() -> usize {
274        T::LEVEL_BITS.len()
275    }
276
277    pub const fn valid_bits() -> usize {
278        Frame::<T, A>::PT_VALID_BITS
279    }
280
281    fn is_addr_in_width(addr: usize) -> bool {
282        let valid_bits = Self::valid_bits();
283        if valid_bits >= usize::BITS as usize {
284            return true;
285        }
286        addr < (1usize << valid_bits)
287    }
288
289    /// 销毁整个页表结构
290    ///
291    /// 此方法会:
292    /// 1. 递归释放根帧及所有子页表帧
293    /// 2. 清除所有页表项(设为invalid)
294    /// 3. 不释放映射的物理页(数据页/大页)
295    ///
296    /// # Safety
297    /// 调用者必须确保:
298    /// - 没有其他代码在访问这个页表
299    /// - 没有CPU正在使用这个页表进行地址翻译
300    /// - 调用后不再使用这个PageTable实例
301    pub unsafe fn destroy(mut self) {
302        self.root.deallocate_recursive(Frame::<T, A>::PT_LEVEL);
303    }
304
305    /// 释放页表占用的所有页表帧
306    ///
307    /// 与destroy()不同,这个方法保留PageTable结构,
308    /// 但释放所有关联的页表帧。调用后PageTable不再可用。
309    ///
310    /// 释放行为:
311    /// - 释放所有页表帧
312    /// - 清除所有页表项(设为invalid)
313    /// - 不释放映射的物理页(数据页/大页)
314    ///
315    /// # Safety
316    /// 调用者必须确保:
317    /// - 没有其他代码在访问这个页表
318    /// - 没有CPU正在使用这个页表进行地址翻译
319    pub unsafe fn deallocate(&mut self) {
320        self.root.deallocate_recursive(Frame::<T, A>::PT_LEVEL);
321    }
322
323    /// 释放页表中的指定映射区域
324    ///
325    /// 释放指定虚拟地址范围内的所有页表项和子页表帧
326    /// 在释放前将相关PTE设为invalid
327    pub fn deallocate_range(&mut self, start_vaddr: VirtAddr, end_vaddr: VirtAddr) -> PagingResult {
328        if start_vaddr >= end_vaddr {
329            return Err(PagingError::invalid_range(
330                "Start address must be less than end address",
331            ));
332        }
333
334        // TODO: 实现范围释放逻辑
335        // 这里需要实现:
336        // 1. 遍历指定虚拟地址范围
337        // 2. 释放对应的页表项和子页表
338        // 3. 处理部分页表项的情况
339
340        Ok(())
341    }
342
343    /// 通过虚拟地址查询页表项
344    ///
345    /// # 参数
346    /// - `vaddr`: 要查询的虚拟地址
347    ///
348    /// # 返回值
349    /// - `Ok(T::P)`: 找到的页表项,包含物理地址信息
350    /// - `Err(PagingError)`: 查询失败,原因可能包括:
351    ///   - 地址未映射
352    ///   - 页表项无效
353    ///   - 页表层次结构错误
354    pub fn translate(&self, vaddr: VirtAddr) -> PagingResult<(PhysAddr, T::P)> {
355        self.translate_with_level(vaddr)
356            .map(|(phys_addr, pte, _)| (phys_addr, pte))
357    }
358
359    /// Translates a virtual address and returns the matched PTE level.
360    pub fn translate_with_level(&self, vaddr: VirtAddr) -> PagingResult<(PhysAddr, T::P, usize)> {
361        if T::STRICT_ADDRESS_WIDTH && !Self::is_addr_in_width(vaddr.raw()) {
362            return Err(PagingError::address_overflow("translate"));
363        }
364
365        let (pte, level) = self
366            .root
367            .translate_recursive_with_level(vaddr, Frame::<T, A>::PT_LEVEL)?;
368
369        let pte_config = pte.to_config(level > 1);
370
371        // 根据页表项类型计算正确的偏移
372        let (phys_addr, _) = if pte_config.huge {
373            // 大页映射:需要使用实际级别的大小来计算偏移
374            let level_size = Frame::<T, A>::level_size(level);
375            let offset_in_page = vaddr.raw() % level_size;
376            (
377                PhysAddr::new(pte_config.paddr.raw() + offset_in_page),
378                level_size,
379            )
380        } else {
381            // 普通页面映射:使用页面大小
382            let offset_in_page = vaddr.raw() % T::PAGE_SIZE;
383            (
384                PhysAddr::new(pte_config.paddr.raw() + offset_in_page),
385                T::PAGE_SIZE,
386            )
387        };
388
389        Ok((phys_addr, pte, level))
390    }
391
392    /// 通过虚拟地址查询物理地址(便利方法)
393    ///
394    /// # 参数
395    /// - `vaddr`: 要查询的虚拟地址
396    ///
397    /// # 返回值
398    /// - `Ok(PhysAddr)`: 找到的物理地址
399    /// - `Err(PagingError)`: 查询失败
400    pub fn translate_phys(&self, vaddr: VirtAddr) -> PagingResult<PhysAddr> {
401        let (p, _) = self.translate(vaddr)?;
402        Ok(p)
403    }
404
405    /// 检查虚拟地址是否已映射
406    ///
407    /// 这是一个便利方法,用于快速检查地址是否已映射而不需要获取页表项
408    ///
409    /// # 参数
410    /// - `vaddr`: 要检查的虚拟地址
411    ///
412    /// # 返回值
413    /// - `true`: 地址已映射
414    /// - `false`: 地址未映射
415    pub fn is_mapped(&self, vaddr: VirtAddr) -> bool {
416        self.translate(vaddr).is_ok()
417    }
418
419    /// 获取页表的根帧物理地址
420    pub fn root_paddr(&self) -> crate::PhysAddr {
421        self.root.paddr
422    }
423}