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