Skip to main content

page_table_generic/
table.rs

1use core::ops::{Deref, DerefMut, Range};
2
3use ax_memory_addr::MemoryAddr;
4
5use crate::{
6    FrameAllocator, PageTableEntry, PagingError, PagingResult, PhysAddr, PteConfigOf, TableMeta,
7    VirtAddr,
8    frame::Frame,
9    map::{MapConfig, MapRecursiveConfig, UnmapConfig, UnmapRecursiveConfig},
10    walk::{PageTableWalker, WalkConfig},
11};
12
13const TARGETED_FLUSH_LIMIT: usize = 32;
14
15pub struct PageTable<T: TableMeta, A: FrameAllocator> {
16    inner: PageTableRef<T, A>,
17    #[cfg(feature = "copy-from")]
18    borrowed_root_entries: Option<Range<usize>>,
19}
20
21impl<T: TableMeta, A: FrameAllocator> PageTable<T, A> {
22    pub const VALID_BITS: usize = Frame::<T, A>::PT_VALID_BITS;
23
24    /// 创建一个新的页表
25    pub fn new(allocator: A) -> PagingResult<Self> {
26        let inner = unsafe { PageTableRef::new(allocator) }?;
27        Ok(Self {
28            inner,
29            #[cfg(feature = "copy-from")]
30            borrowed_root_entries: None,
31        })
32    }
33
34    pub const fn root_paddr(&self) -> PhysAddr {
35        self.inner.root.paddr
36    }
37
38    /// Deep-copies source root entries that are absent from this page table.
39    ///
40    /// Leaf mappings keep referring to the same physical memory, while every
41    /// copied intermediate page-table frame is independently owned by this
42    /// page table. Existing destination root entries are left unchanged.
43    ///
44    /// If allocation fails, entries copied before the failure remain installed
45    /// and are reclaimed normally when this page table is dropped.
46    ///
47    /// # Errors
48    ///
49    /// Returns an error if the range overflows or wraps around the root table,
50    /// or if an intermediate page-table frame cannot be allocated.
51    pub fn clone_missing_root_entries_from(
52        &mut self,
53        other: &PageTableRef<T, A>,
54        start_vaddr: VirtAddr,
55        size: usize,
56    ) -> PagingResult {
57        let Some(entries) = Self::root_entry_range(start_vaddr, size)? else {
58            return Ok(());
59        };
60
61        let root_level = Frame::<T, A>::PT_LEVEL;
62        let mut changed = false;
63        for index in entries {
64            changed |= self
65                .inner
66                .root
67                .clone_entry_from(&other.root, index, root_level)?;
68        }
69        if changed {
70            T::flush(None);
71        }
72        Ok(())
73    }
74
75    /// Shares root page-table entries from another page table.
76    ///
77    /// Mappings below the shared root entries remain owned by the source and
78    /// changes made there are visible through both page tables.
79    ///
80    /// # Safety
81    ///
82    /// The source page table must outlive this page table. The caller must
83    /// also prevent this page table from modifying or unmapping the shared
84    /// virtual-address range.
85    #[cfg(feature = "copy-from")]
86    pub unsafe fn share_root_entries_from(
87        &mut self,
88        other: &Self,
89        start_vaddr: VirtAddr,
90        size: usize,
91    ) -> PagingResult {
92        if size == 0 {
93            return Ok(());
94        }
95        if self.borrowed_root_entries.is_some() {
96            return Err(PagingError::hierarchy_error(
97                "Page table already contains shared root entries",
98            ));
99        }
100
101        let Some(entries) = Self::root_entry_range(start_vaddr, size)? else {
102            return Ok(());
103        };
104        let root_level = Frame::<T, A>::PT_LEVEL;
105
106        for index in entries.clone() {
107            self.inner.root.dealloc_entry_recursive(index, root_level);
108            self.inner.root.as_slice_mut()[index] = other.inner.root.as_slice()[index];
109        }
110        self.borrowed_root_entries = Some(entries);
111        T::flush(None);
112        Ok(())
113    }
114
115    fn root_entry_range(start_vaddr: VirtAddr, size: usize) -> PagingResult<Option<Range<usize>>> {
116        if size == 0 {
117            return Ok(None);
118        }
119        let end_vaddr = start_vaddr
120            .as_usize()
121            .checked_add(size)
122            .ok_or_else(|| PagingError::address_overflow("root_entry_range"))?;
123        let root_level = Frame::<T, A>::PT_LEVEL;
124        let start_index = Frame::<T, A>::virt_to_index(start_vaddr, root_level);
125        let end_index =
126            Frame::<T, A>::virt_to_index(VirtAddr::from_usize(end_vaddr - 1), root_level) + 1;
127        if start_index >= end_index {
128            return Err(PagingError::invalid_range(
129                "Range must be contiguous in the root page table",
130            ));
131        }
132        Ok(Some(start_index..end_index))
133    }
134
135    #[cfg(feature = "copy-from")]
136    fn detach_borrowed_root_entries(&mut self) {
137        let Some(entries) = self.borrowed_root_entries.take() else {
138            return;
139        };
140        for index in entries {
141            self.inner.root.as_slice_mut()[index].clear();
142        }
143    }
144}
145
146impl<T: TableMeta, A: FrameAllocator> Drop for PageTable<T, A> {
147    fn drop(&mut self) {
148        #[cfg(feature = "copy-from")]
149        self.detach_borrowed_root_entries();
150        unsafe {
151            // 释放所有页表帧,但不释放映射的物理页
152            self.deallocate();
153        }
154    }
155}
156
157impl<T: TableMeta, A: FrameAllocator> Deref for PageTable<T, A> {
158    type Target = PageTableRef<T, A>;
159
160    fn deref(&self) -> &Self::Target {
161        &self.inner
162    }
163}
164
165impl<T: TableMeta, A: FrameAllocator> DerefMut for PageTable<T, A> {
166    fn deref_mut(&mut self) -> &mut Self::Target {
167        &mut self.inner
168    }
169}
170
171#[derive(Clone, Copy)]
172pub struct PageTableRef<T: TableMeta, A: FrameAllocator> {
173    pub root: Frame<T, A>,
174}
175
176impl<T: TableMeta, A: FrameAllocator> core::fmt::Debug for PageTableRef<T, A>
177where
178    T::P: core::fmt::Debug,
179{
180    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
181        f.debug_struct("PageTable")
182            .field(
183                "root_paddr",
184                &format_args!("{:#x}", self.root.paddr.as_usize()),
185            )
186            .field("table_levels", &T::LEVEL_BITS.len())
187            .field("max_block_level", &T::MAX_BLOCK_LEVEL)
188            .field("page_size", &format_args!("{:#x}", T::PAGE_SIZE))
189            .finish()
190    }
191}
192
193impl<T: TableMeta, A: FrameAllocator> PageTableRef<T, A> {
194    /// 创建一个新的页表
195    ///
196    /// # Safety
197    ///
198    /// 调用者必须确保提供的FrameAllocator是有效的,并且在页表生命周期内保持有效
199    pub unsafe fn new(allocator: A) -> PagingResult<Self> {
200        let root = Frame::new_root(allocator)?;
201        Ok(Self { root })
202    }
203
204    pub fn from_paddr(paddr: PhysAddr, allocator: A) -> Self {
205        let root = Frame::from_root_paddr(paddr, allocator);
206        Self { root }
207    }
208
209    /// Maps one page with the requested page size.
210    pub fn map_page(
211        &mut self,
212        vaddr: VirtAddr,
213        paddr: PhysAddr,
214        page_size: usize,
215        config: PteConfigOf<T>,
216    ) -> PagingResult {
217        let Some(level) = Frame::<T, A>::level_for_page_size(page_size) else {
218            return Err(PagingError::invalid_size(
219                "Page size is not represented by the page-table levels",
220            ));
221        };
222        if level > 1 && level > T::MAX_BLOCK_LEVEL {
223            return Err(PagingError::invalid_size(
224                "Page size exceeds the architecture's block-mapping level",
225            ));
226        }
227        self.map(&MapConfig {
228            vaddr: vaddr.align_down(page_size),
229            paddr: paddr.align_down(page_size),
230            size: page_size,
231            pte: config,
232            allow_huge: level > 1,
233            flush: true,
234        })
235    }
236
237    /// Maps a contiguous virtual region, choosing large pages when possible.
238    /// Mappings installed by this call are rolled back if a later page fails.
239    /// TLB invalidation is deferred and batched until the region has been updated.
240    pub fn map_region(
241        &mut self,
242        start_vaddr: VirtAddr,
243        get_paddr: impl Fn(VirtAddr) -> PhysAddr,
244        size: usize,
245        config: PteConfigOf<T>,
246        allow_huge: bool,
247    ) -> PagingResult {
248        if size == 0 {
249            return Err(PagingError::invalid_size("Region size cannot be zero"));
250        }
251        if !start_vaddr.as_usize().is_multiple_of(T::PAGE_SIZE)
252            || !size.is_multiple_of(T::PAGE_SIZE)
253        {
254            return Err(PagingError::alignment_error(
255                "Region start and size must be base-page aligned",
256            ));
257        }
258        start_vaddr.as_usize().checked_add(size).ok_or_else(|| {
259            PagingError::address_overflow("Virtual address overflow in map_region")
260        })?;
261        self.validate_address_width(start_vaddr, size, "map_region")?;
262
263        let mut offset = 0;
264        let mut flush_addrs = heapless::Vec::<VirtAddr, TARGETED_FLUSH_LIMIT>::new();
265        let mut full_flush = false;
266        let result = loop {
267            if offset >= size {
268                break Ok(());
269            }
270            let vaddr = start_vaddr + offset;
271            let paddr = get_paddr(vaddr);
272            let remaining = size - offset;
273            let page_size = largest_page_size::<T, A>(vaddr, paddr, remaining, allow_huge);
274            if let Err(err) = self.map(&MapConfig {
275                vaddr: vaddr.align_down(page_size),
276                paddr: paddr.align_down(page_size),
277                size: page_size,
278                pte: config,
279                allow_huge: page_size > T::PAGE_SIZE,
280                flush: false,
281            }) {
282                let rollback_result = if offset == 0 {
283                    Ok(())
284                } else {
285                    self.unmap_with_config(&UnmapConfig {
286                        start_vaddr,
287                        size: offset,
288                        flush: false,
289                    })
290                };
291                break match rollback_result {
292                    Ok(()) => Err(err),
293                    Err(rollback_err) => Err(rollback_err),
294                };
295            }
296            if !full_flush && flush_addrs.push(vaddr).is_err() {
297                full_flush = true;
298                flush_addrs.clear();
299            }
300            offset += page_size;
301        };
302
303        if full_flush {
304            T::flush(None);
305        } else {
306            for vaddr in flush_addrs {
307                T::flush(Some(vaddr));
308            }
309        }
310        result
311    }
312
313    /// Unmaps one page and returns its physical address, flags, and page size.
314    pub fn unmap_page(
315        &mut self,
316        vaddr: VirtAddr,
317    ) -> PagingResult<(PhysAddr, PteConfigOf<T>, usize)> {
318        let (pte, level) = self
319            .root
320            .find_occupied_leaf(vaddr, Frame::<T, A>::PT_LEVEL)?;
321        let page_size = Frame::<T, A>::level_size(level);
322        let is_dir = level > 1;
323        let paddr = pte.paddr(is_dir);
324        let config = pte.config(is_dir);
325        self.unmap_with_config(&UnmapConfig {
326            start_vaddr: vaddr.align_down(page_size),
327            size: page_size,
328            flush: true,
329        })?;
330        Ok((paddr, config, page_size))
331    }
332
333    /// Changes one existing mapping's flags and returns its page size.
334    pub fn protect_page(&mut self, vaddr: VirtAddr, config: PteConfigOf<T>) -> PagingResult<usize> {
335        let page_size = self
336            .root
337            .protect_recursive(vaddr, config, Frame::<T, A>::PT_LEVEL)?;
338        T::flush(Some(vaddr));
339        Ok(page_size)
340    }
341
342    /// Changes flags for a region. Unmapped base pages are skipped.
343    pub fn protect_region(
344        &mut self,
345        start_vaddr: VirtAddr,
346        size: usize,
347        config: PteConfigOf<T>,
348    ) -> PagingResult {
349        let end = start_vaddr
350            .as_usize()
351            .checked_add(size)
352            .ok_or_else(|| PagingError::address_overflow("protect_region"))?;
353        let mut vaddr = start_vaddr;
354        while vaddr.as_usize() < end {
355            match self.protect_page(vaddr, config) {
356                Ok(page_size) => vaddr += page_size,
357                Err(PagingError::NotMapped) => vaddr += T::PAGE_SIZE,
358                Err(err) => return Err(err),
359            }
360        }
361        Ok(())
362    }
363
364    /// Remaps one existing mapping and returns its page size.
365    pub fn remap_page(
366        &mut self,
367        vaddr: VirtAddr,
368        paddr: PhysAddr,
369        config: PteConfigOf<T>,
370    ) -> PagingResult<usize> {
371        let page_size = self
372            .root
373            .remap_recursive(vaddr, paddr, config, Frame::<T, A>::PT_LEVEL)?;
374        T::flush(Some(vaddr));
375        Ok(page_size)
376    }
377
378    /// Queries one mapping and returns the translated physical address, flags, and page size.
379    pub fn query(&self, vaddr: VirtAddr) -> PagingResult<(PhysAddr, PteConfigOf<T>, usize)> {
380        let (paddr, pte, level) = self.translate_with_level(vaddr)?;
381        Ok((
382            paddr,
383            pte.config(level > 1),
384            Frame::<T, A>::level_size(level),
385        ))
386    }
387
388    /// 映射虚拟地址范围到物理地址范围
389    pub fn map(&mut self, config: &MapConfig<PteConfigOf<T>>) -> PagingResult {
390        // 验证输入参数
391        self.validate_map_config(config)?;
392
393        // 检查大小溢出
394        if config.vaddr.as_usize().checked_add(config.size).is_none()
395            || config.paddr.as_usize().checked_add(config.size).is_none()
396        {
397            return Err(PagingError::address_overflow(
398                "Virtual or physical address overflow",
399            ));
400        }
401        self.validate_address_width(config.vaddr, config.size, "map")?;
402
403        self.root.map_range_recursive(MapRecursiveConfig {
404            start_vaddr: config.vaddr,
405            start_paddr: config.paddr,
406            end_vaddr: config.vaddr + config.size,
407            level: Frame::<T, A>::PT_LEVEL,
408            allow_huge: config.allow_huge,
409            flush: config.flush,
410            pte_template: config.pte,
411        })?;
412
413        Ok(())
414    }
415
416    /// 取消映射虚拟地址范围
417    ///
418    /// # 参数
419    /// - `start_vaddr`: 要取消映射的起始虚拟地址
420    /// - `size`: 要取消映射的大小(字节)
421    ///
422    /// # 返回值
423    /// - `Ok(())`: 取消映射成功
424    /// - `Err(PagingError)`: 取消映射失败
425    ///
426    /// # 行为
427    /// - 清除指定虚拟地址范围内的所有页表项
428    /// - 自动回收空的子页表帧
429    /// - 支持大页和普通页面的取消映射
430    /// - 根据配置刷新TLB
431    pub fn unmap(&mut self, start_vaddr: VirtAddr, size: usize) -> PagingResult<()> {
432        // 验证输入参数
433        self.validate_unmap_params(start_vaddr, size)?;
434
435        // 检查大小溢出
436        let end_vaddr: VirtAddr = match start_vaddr.as_usize().checked_add(size) {
437            Some(end) => VirtAddr::from_usize(end),
438            None => {
439                return Err(PagingError::address_overflow(
440                    "Virtual address overflow in unmap",
441                ));
442            }
443        };
444        self.validate_address_width(start_vaddr, size, "unmap")?;
445
446        self.root.unmap_range_recursive(UnmapRecursiveConfig {
447            start_vaddr,
448            end_vaddr,
449            level: Frame::<T, A>::PT_LEVEL,
450            flush: true, // 默认刷新TLB确保一致性
451        })?;
452
453        Ok(())
454    }
455
456    /// 使用配置对象取消映射
457    pub fn unmap_with_config(&mut self, config: &UnmapConfig) -> PagingResult<()> {
458        self.validate_unmap_params(config.start_vaddr, config.size)?;
459
460        let end_vaddr = match config.start_vaddr.as_usize().checked_add(config.size) {
461            Some(end) => VirtAddr::from_usize(end),
462            None => {
463                return Err(PagingError::address_overflow(
464                    "Virtual address overflow in unmap_with_config",
465                ));
466            }
467        };
468        self.validate_address_width(config.start_vaddr, config.size, "unmap_with_config")?;
469
470        self.root.unmap_range_recursive(UnmapRecursiveConfig {
471            start_vaddr: config.start_vaddr,
472            end_vaddr,
473            level: Frame::<T, A>::PT_LEVEL,
474            flush: config.flush,
475        })?;
476
477        Ok(())
478    }
479
480    /// 验证取消映射参数的有效性
481    fn validate_unmap_params(&self, start_vaddr: VirtAddr, size: usize) -> PagingResult<()> {
482        if size == 0 {
483            return Err(PagingError::invalid_size("Size cannot be zero in unmap"));
484        }
485
486        // 检查虚拟地址是否页对齐
487        if !start_vaddr.as_usize().is_multiple_of(T::PAGE_SIZE) {
488            return Err(PagingError::alignment_error(
489                "Start virtual address not page aligned in unmap",
490            ));
491        }
492
493        // 检查大小是否页对齐
494        if !size.is_multiple_of(T::PAGE_SIZE) {
495            return Err(PagingError::alignment_error(
496                "Size not page aligned in unmap",
497            ));
498        }
499
500        Ok(())
501    }
502
503    /// 创建页表遍历迭代器
504    pub fn walk_all(&self, config: WalkConfig) -> PageTableWalker<'_, T, A> {
505        PageTableWalker::new(self, config)
506    }
507
508    pub fn walk(
509        &self,
510        start_vaddr: VirtAddr,
511        end_vaddr: VirtAddr,
512    ) -> impl Iterator<Item = crate::walk::PteInfo<T::P>> + '_ {
513        let config = WalkConfig {
514            start_vaddr,
515            end_vaddr,
516        };
517        PageTableWalker::new(self, config).filter(|p| p.pte.present())
518    }
519
520    /// 遍历所有有效的最终映射页表项(过滤掉无效项和中间级别的页表指针)
521    pub fn walk_valid(&self) -> impl Iterator<Item = crate::walk::PteInfo<T::P>> + '_ {
522        self.walk(0.into(), usize::MAX.into())
523            .filter(|p| p.pte.present() && p.is_final_mapping)
524    }
525
526    /// 验证映射配置的有效性
527    fn validate_map_config(&self, config: &MapConfig<PteConfigOf<T>>) -> PagingResult {
528        if config.size == 0 {
529            return Err(PagingError::invalid_size("Size cannot be zero"));
530        }
531
532        // 检查虚拟地址和物理地址是否页对齐
533        if !config.vaddr.as_usize().is_multiple_of(T::PAGE_SIZE) {
534            return Err(PagingError::alignment_error(
535                "Virtual address not page aligned",
536            ));
537        }
538
539        if !config.paddr.as_usize().is_multiple_of(T::PAGE_SIZE) {
540            return Err(PagingError::alignment_error(
541                "Physical address not page aligned",
542            ));
543        }
544
545        Ok(())
546    }
547
548    fn validate_address_width(
549        &self,
550        start_vaddr: VirtAddr,
551        size: usize,
552        operation: &'static str,
553    ) -> PagingResult<()> {
554        if !T::STRICT_ADDRESS_WIDTH {
555            return Ok(());
556        }
557        let Some(end) = start_vaddr.as_usize().checked_add(size) else {
558            return Err(PagingError::address_overflow(
559                "Virtual address range overflow",
560            ));
561        };
562        let last = end.saturating_sub(1);
563        if !Self::is_addr_in_width(start_vaddr.as_usize()) || !Self::is_addr_in_width(last) {
564            return Err(PagingError::address_overflow(operation));
565        }
566        Ok(())
567    }
568
569    pub const fn page_size() -> usize {
570        T::PAGE_SIZE
571    }
572
573    pub const fn table_levels() -> usize {
574        T::LEVEL_BITS.len()
575    }
576
577    pub const fn valid_bits() -> usize {
578        Frame::<T, A>::PT_VALID_BITS
579    }
580
581    fn is_addr_in_width(addr: usize) -> bool {
582        let valid_bits = Self::valid_bits();
583        if valid_bits >= usize::BITS as usize {
584            return true;
585        }
586        addr < (1usize << valid_bits)
587    }
588
589    /// 销毁整个页表结构
590    ///
591    /// 此方法会:
592    /// 1. 递归释放根帧及所有子页表帧
593    /// 2. 清除所有页表项(设为invalid)
594    /// 3. 不释放映射的物理页(数据页/大页)
595    ///
596    /// # Safety
597    /// 调用者必须确保:
598    /// - 没有其他代码在访问这个页表
599    /// - 没有CPU正在使用这个页表进行地址翻译
600    /// - 调用后不再使用这个PageTable实例
601    pub unsafe fn destroy(mut self) {
602        self.root.deallocate_recursive(Frame::<T, A>::PT_LEVEL);
603    }
604
605    /// 释放页表占用的所有页表帧
606    ///
607    /// 与destroy()不同,这个方法保留PageTable结构,
608    /// 但释放所有关联的页表帧。调用后PageTable不再可用。
609    ///
610    /// 释放行为:
611    /// - 释放所有页表帧
612    /// - 清除所有页表项(设为invalid)
613    /// - 不释放映射的物理页(数据页/大页)
614    ///
615    /// # Safety
616    /// 调用者必须确保:
617    /// - 没有其他代码在访问这个页表
618    /// - 没有CPU正在使用这个页表进行地址翻译
619    pub unsafe fn deallocate(&mut self) {
620        self.root.deallocate_recursive(Frame::<T, A>::PT_LEVEL);
621    }
622
623    /// 释放页表中的指定映射区域
624    ///
625    /// 释放指定虚拟地址范围内的所有页表项和子页表帧
626    /// 在释放前将相关PTE设为invalid
627    pub fn deallocate_range(&mut self, start_vaddr: VirtAddr, end_vaddr: VirtAddr) -> PagingResult {
628        if start_vaddr >= end_vaddr {
629            return Err(PagingError::invalid_range(
630                "Start address must be less than end address",
631            ));
632        }
633
634        // TODO: 实现范围释放逻辑
635        // 这里需要实现:
636        // 1. 遍历指定虚拟地址范围
637        // 2. 释放对应的页表项和子页表
638        // 3. 处理部分页表项的情况
639
640        Ok(())
641    }
642
643    /// 通过虚拟地址查询页表项
644    ///
645    /// # 参数
646    /// - `vaddr`: 要查询的虚拟地址
647    ///
648    /// # 返回值
649    /// - `Ok(T::P)`: 找到的页表项,包含物理地址信息
650    /// - `Err(PagingError)`: 查询失败,原因可能包括:
651    ///   - 地址未映射
652    ///   - 页表项无效
653    ///   - 页表层次结构错误
654    pub fn translate(&self, vaddr: VirtAddr) -> PagingResult<(PhysAddr, T::P)> {
655        self.translate_with_level(vaddr)
656            .map(|(phys_addr, pte, _)| (phys_addr, pte))
657    }
658
659    /// Translates a virtual address and returns the matched PTE level.
660    pub fn translate_with_level(&self, vaddr: VirtAddr) -> PagingResult<(PhysAddr, T::P, usize)> {
661        if T::STRICT_ADDRESS_WIDTH && !Self::is_addr_in_width(vaddr.as_usize()) {
662            return Err(PagingError::address_overflow("translate"));
663        }
664
665        let (pte, level) = self
666            .root
667            .translate_recursive_with_level(vaddr, Frame::<T, A>::PT_LEVEL)?;
668
669        let is_huge = pte.huge(level > 1);
670        let pte_paddr = pte.paddr(level > 1);
671
672        // 根据页表项类型计算正确的偏移
673        let (phys_addr, _) = if is_huge {
674            // 大页映射:需要使用实际级别的大小来计算偏移
675            let level_size = Frame::<T, A>::level_size(level);
676            let offset_in_page = vaddr.as_usize() % level_size;
677            (
678                PhysAddr::from_usize(pte_paddr.as_usize() + offset_in_page),
679                level_size,
680            )
681        } else {
682            // 普通页面映射:使用页面大小
683            let offset_in_page = vaddr.as_usize() % T::PAGE_SIZE;
684            (
685                PhysAddr::from_usize(pte_paddr.as_usize() + offset_in_page),
686                T::PAGE_SIZE,
687            )
688        };
689
690        Ok((phys_addr, pte, level))
691    }
692
693    /// 通过虚拟地址查询物理地址(便利方法)
694    ///
695    /// # 参数
696    /// - `vaddr`: 要查询的虚拟地址
697    ///
698    /// # 返回值
699    /// - `Ok(PhysAddr)`: 找到的物理地址
700    /// - `Err(PagingError)`: 查询失败
701    pub fn translate_phys(&self, vaddr: VirtAddr) -> PagingResult<PhysAddr> {
702        let (p, _) = self.translate(vaddr)?;
703        Ok(p)
704    }
705
706    /// 检查虚拟地址是否已映射
707    ///
708    /// 这是一个便利方法,用于快速检查地址是否已映射而不需要获取页表项
709    ///
710    /// # 参数
711    /// - `vaddr`: 要检查的虚拟地址
712    ///
713    /// # 返回值
714    /// - `true`: 地址已映射
715    /// - `false`: 地址未映射
716    pub fn is_mapped(&self, vaddr: VirtAddr) -> bool {
717        self.translate(vaddr).is_ok()
718    }
719
720    /// 获取页表的根帧物理地址
721    pub fn root_paddr(&self) -> crate::PhysAddr {
722        self.root.paddr
723    }
724}
725
726fn largest_page_size<T: TableMeta, A: FrameAllocator>(
727    vaddr: VirtAddr,
728    paddr: PhysAddr,
729    remaining: usize,
730    allow_huge: bool,
731) -> usize {
732    if allow_huge {
733        let max_level = Frame::<T, A>::PT_LEVEL.min(T::MAX_BLOCK_LEVEL);
734        for level in (2..=max_level).rev() {
735            let page_size = Frame::<T, A>::level_size(level);
736            if vaddr.is_aligned(page_size) && paddr.is_aligned(page_size) && remaining >= page_size
737            {
738                return page_size;
739            }
740        }
741    }
742    T::PAGE_SIZE
743}