1use super::{Pos, Visitor};
2use crate::{PageTable, Pte, VmMeta, PPN};
3use core::{fmt, marker::PhantomData, ptr::NonNull};
4
5pub struct PageTableFormatter<Meta: VmMeta, F: Fn(PPN<Meta>) -> NonNull<Pte<Meta>>> {
9 pub pt: PageTable<Meta>,
11 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 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 fn pte(&mut self, pte: Pte<Meta>, pos: Pos<Meta>) {
61 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 for _ in 0..level {
98 write!(self.f, " - ").unwrap();
99 for _ in 0..18 {
100 write!(self.f, "-").unwrap();
101 }
102 }
103 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 if pte.is_valid() {
115 self.ppn(pte.ppn(), 0);
116 self.pte(pte, target);
117 }
118 target.next()
119 }
120}