ostd/specs/mm/page_table/node/
child.rs1use vstd::prelude::*;
2
3use vstd_extra::ownership::*;
4
5use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
6
7use crate::arch::mm::PagingConsts;
8use crate::mm::{
9 Paddr, PagingConstsTrait, PagingLevel, Vaddr,
10 frame::{meta::mapping::meta_to_frame, *},
11 page_prop::PageProperty,
12 page_table::*,
13};
14
15verus! {
16
17impl<C: PageTableConfig> OwnerOf for Child<C> {
18 type Owner = EntryOwner<C>;
19
20 open spec fn wf(self, owner: Self::Owner) -> bool {
21 match self {
22 Self::PageTable(node) => {
23 &&& owner.is_node()
24 &&& node.ptr.addr() == owner.node().meta_vaddr()
25 &&& node.index() == frame_to_index(meta_to_frame(node.ptr.addr()))
26 },
27 Self::Frame(paddr, level, prop) => {
28 &&& owner.is_frame()
29 &&& owner.frame().mapped_pa == paddr
30 &&& owner.frame().prop == prop
31 &&& level == owner.parent_level
32 },
33 Self::None => owner.is_absent(),
34 }
35 }
36}
37
38impl<'a, C: PageTableConfig> OwnerOf for ChildRef<'a, C> {
39 type Owner = EntryOwner<C>;
40
41 open spec fn wf(self, owner: Self::Owner) -> bool {
42 match self {
43 Self::PageTable(node) => {
44 &&& owner.is_node()
45 &&& node.inner@.ptr.addr() == owner.node().meta_vaddr()
46 },
47 Self::Frame(paddr, level, prop) => {
48 &&& owner.is_frame()
49 &&& owner.frame().mapped_pa == paddr
50 &&& owner.frame().prop == prop
51 },
52 Self::None => owner.is_absent(),
53 }
54 }
55}
56
57impl<C: PageTableConfig> Child<C> {
58 pub open spec fn get_node(self) -> Option<PageTableNode<C>> {
59 match self {
60 Self::PageTable(node) => Some(node),
61 _ => None,
62 }
63 }
64
65 pub open spec fn get_frame_tuple(self) -> Option<(Paddr, PagingLevel, PageProperty)> {
66 match self {
67 Self::Frame(paddr, level, prop) => Some((paddr, level, prop)),
68 _ => None,
69 }
70 }
71
72 pub open spec fn into_pte_frame_spec(self, tuple: (Paddr, PagingLevel, PageProperty)) -> C::E {
73 let (paddr, level, prop) = tuple;
74 C::E::new_page_spec(paddr, level, prop)
75 }
76
77 pub open spec fn into_pte_none_spec(self) -> C::E {
78 C::E::new_absent_spec()
79 }
80
81 pub open spec fn from_pte_spec(
82 pte: C::E,
83 level: PagingLevel,
84 regions: MetaRegionOwners,
85 ) -> Self {
86 if !pte.is_present() {
87 Self::None
88 } else if pte.is_last(level) {
89 Self::Frame(pte.paddr(), level, pte.prop())
90 } else {
91 Self::PageTable(PageTableNode::from_raw_spec(pte.paddr()))
92 }
93 }
94
95 pub open spec fn from_pte_frame_spec(pte: C::E, level: PagingLevel) -> Self {
96 Self::Frame(pte.paddr(), level, pte.prop())
97 }
98
99 pub open spec fn from_pte_pt_spec(paddr: Paddr, regions: MetaRegionOwners) -> Self {
100 Self::PageTable(PageTableNode::from_raw_spec(paddr))
101 }
102
103 pub open spec fn invariants(self, owner: EntryOwner<C>, regions: MetaRegionOwners) -> bool {
104 &&& owner.inv_base()
105 &&& regions.inv()
106 &&& self.wf(owner)
107 &&& match self {
108 Self::Frame(paddr, level, prop) => C::E::new_page_req(paddr, level, prop),
109 _ => true,
110 }
111 &&& owner.metaregion_sound(regions)
112 }
113}
114
115impl<C: PageTableConfig> ChildRef<'_, C> {
116 pub open spec fn invariants(self, owner: EntryOwner<C>, regions: MetaRegionOwners) -> bool {
117 &&& owner.inv()
118 &&& regions.inv()
119 &&& self.wf(owner)
120 &&& owner.metaregion_sound(regions)
121 }
122}
123
124impl<C: PageTableConfig> EntryOwner<C> {
125 pub open spec fn from_pte_regions_spec(self, regions: MetaRegionOwners) -> MetaRegionOwners {
126 if self.is_node() {
127 let index = frame_to_index(self.meta_slot_paddr()->0);
128 MetaRegionOwners {
129 frame_obligations: regions.frame_obligations.insert(index),
130 ..regions
131 }
132 } else {
133 regions
134 }
135 }
136
137 pub open spec fn into_pte_regions_spec(self, regions: MetaRegionOwners) -> MetaRegionOwners {
138 if self.is_node() {
139 let index = frame_to_index(self.meta_slot_paddr()->0);
140 MetaRegionOwners {
146 frame_obligations: regions.frame_obligations.remove(index),
147 ..regions
148 }
149 } else {
150 regions
153 }
154 }
155
156 pub open spec fn into_pte_owner_spec(self) -> EntryOwner<C> {
157 self
158 }
159
160 pub open spec fn from_pte_owner_spec(self) -> EntryOwner<C> {
161 self
162 }
163
164 pub open spec fn pte_invariants(self, pte: C::E, regions: MetaRegionOwners) -> bool {
167 &&& self.inv()
168 &&& regions.inv()
169 &&& self.match_pte(pte, self.parent_level)
170 &&& self.metaregion_sound(regions)
171 }
172}
173
174}