page_table/table/
fmt.rs

1use super::{Pos, Visitor};
2use crate::{PageTable, Pte, VmMeta, PPN};
3use core::{fmt, marker::PhantomData, ptr::NonNull};
4
5/// 页表格式化器。
6///
7/// 为了遍历,需要知道在当前地址空间访问物理页的方法。
8pub struct PageTableFormatter<Meta: VmMeta, F: Fn(PPN<Meta>) -> NonNull<Pte<Meta>>> {
9    /// 根页表。
10    pub pt: PageTable<Meta>,
11    /// 物理页转换为指针。
12    pub f: F,
13}
14
15impl<Meta: VmMeta, F: Fn(PPN<Meta>) -> NonNull<Pte<Meta>>> fmt::Debug
16    for PageTableFormatter<Meta, F>
17{
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        self.pt.walk(
20            Pos {
21                vpn: self.pt.base,
22                level: 0,
23            },
24            &mut FmtVisitor {
25                f,
26                t: &self.f,
27                max_level: self.pt.level,
28                level: self.pt.level + 1,
29                _phantom: PhantomData,
30            },
31        );
32        Ok(())
33    }
34}
35
36struct FmtVisitor<'f1, 'f2, Meta: VmMeta, T: Fn(PPN<Meta>) -> NonNull<Pte<Meta>>> {
37    f: &'f1 mut fmt::Formatter<'f2>,
38    t: T,
39    max_level: usize,
40    level: usize,
41    _phantom: PhantomData<Meta>,
42}
43
44impl<'f1, 'f2, Meta: VmMeta, T: Fn(PPN<Meta>) -> NonNull<Pte<Meta>>> FmtVisitor<'f1, 'f2, Meta, T> {
45    /// 打印一个物理页号。
46    fn ppn(&mut self, ppn: PPN<Meta>, level: usize) {
47        if level >= self.level {
48            writeln!(self.f).unwrap();
49            for _ in level..self.max_level {
50                for _ in 0..18 {
51                    write!(self.f, " ").unwrap();
52                }
53                write!(self.f, " - ").unwrap();
54            }
55        }
56        write!(self.f, "{:#018x}", ppn.val()).unwrap();
57    }
58
59    /// 打印一个页表项。
60    fn pte(&mut self, pte: Pte<Meta>, pos: Pos<Meta>) {
61        // 打印映射的虚址范围和自定义的权限位
62        let range = pos.vpn.vaddr_range(pos.level);
63        write!(
64            self.f,
65            " {:#018x}..{:#018x} (",
66            range.start.val(),
67            range.end.val()
68        )
69        .unwrap();
70        Meta::fmt_flags(self.f, pte.flags().val()).unwrap();
71        write!(self.f, ")").unwrap();
72        self.level = pos.level;
73    }
74}
75
76impl<'f1, 'f2, Meta: VmMeta, T: Fn(PPN<Meta>) -> NonNull<Pte<Meta>>> Visitor<Meta>
77    for FmtVisitor<'f1, 'f2, Meta, T>
78{
79    #[inline]
80    fn meet(
81        &mut self,
82        level: usize,
83        pte: Pte<Meta>,
84        _target: Pos<Meta>,
85    ) -> Option<core::ptr::NonNull<Pte<Meta>>> {
86        self.ppn(pte.ppn(), level);
87        write!(self.f, " - ").unwrap();
88        self.level = level;
89        Some((self.t)(pte.ppn()))
90    }
91
92    #[inline]
93    fn block(&mut self, level: usize, pte: Pte<Meta>, target: Pos<Meta>) -> Pos<Meta> {
94        if pte.is_valid() {
95            self.ppn(pte.ppn(), level);
96            // 打印一些横线
97            for _ in 0..level {
98                write!(self.f, " - ").unwrap();
99                for _ in 0..18 {
100                    write!(self.f, "-").unwrap();
101                }
102            }
103            // 打印映射的虚址范围和自定义的权限位
104            self.pte(pte, Pos { level, ..target });
105        }
106        Pos {
107            level: 0,
108            ..Pos::new(target.vpn, level).next()
109        }
110    }
111
112    fn arrive(&mut self, pte: Pte<Meta>, target: Pos<Meta>) -> Pos<Meta> {
113        // 如果有效,要打印信息
114        if pte.is_valid() {
115            self.ppn(pte.ppn(), 0);
116            self.pte(pte, target);
117        }
118        target.next()
119    }
120}