ostd/specs/mm/page_table/node/
child.rs1use vstd::prelude::*;
2
3use vstd_extra::ownership::*;
4
5use crate::mm::frame::*;
6use crate::mm::page_prop::PageProperty;
7use crate::mm::page_table::*;
8use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr};
9use crate::specs::arch::mm::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
10use crate::specs::arch::paging_consts::PagingConsts;
11use crate::specs::mm::frame::meta_owners::MetaSlotOwner;
12use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
13
14verus! {
15
16impl<C: PageTableConfig> OwnerOf for Child<C> {
17 type Owner = EntryOwner<C>;
18
19 open spec fn wf(self, owner: Self::Owner) -> bool {
20 match self {
21 Self::PageTable(node) => {
22 &&& owner.is_node()
23 &&& node.ptr.addr() == owner.node.unwrap().meta_perm.addr()
24 &&& node.index() == frame_to_index(meta_to_frame(node.ptr.addr()))
25 },
26 Self::Frame(paddr, level, prop) => {
27 &&& owner.is_frame()
28 &&& owner.frame.unwrap().mapped_pa == paddr
29 &&& owner.frame.unwrap().prop == prop
30 &&& level == owner.parent_level
31 },
32 Self::None => owner.is_absent(),
33 }
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.0.ptr.addr() == owner.node.unwrap().meta_perm.addr()
46 },
47 Self::Frame(paddr, level, prop) => {
48 &&& owner.is_frame()
49 &&& owner.frame.unwrap().mapped_pa == paddr
50 &&& owner.frame.unwrap().prop == prop
51 },
52 Self::None => owner.is_absent(),
53 }
54 }
55}
56
57impl<C: PageTableConfig> Child<C> {
58
59 pub open spec fn get_node(self) -> Option<PageTableNode<C>> {
60 match self {
61 Self::PageTable(node) => Some(node),
62 _ => None,
63 }
64 }
65
66 pub open spec fn get_frame_tuple(self) -> Option<(Paddr, PagingLevel, PageProperty)> {
67 match self {
68 Self::Frame(paddr, level, prop) => Some((paddr, level, prop)),
69 _ => None,
70 }
71 }
72
73 pub open spec fn into_pte_frame_spec(self, tuple: (Paddr, PagingLevel, PageProperty)) -> C::E {
74 let (paddr, level, prop) = tuple;
75 C::E::new_page_spec(paddr, level, prop)
76 }
77
78
79 pub open spec fn into_pte_none_spec(self) -> C::E {
80 C::E::new_absent_spec()
81 }
82
83
84 pub open spec fn from_pte_spec(pte: C::E, level: PagingLevel, regions: MetaRegionOwners) -> Self {
85 if !pte.is_present() {
86 Self::None
87 } else if pte.is_last(level) {
88 Self::Frame(pte.paddr(), level, pte.prop())
89 } else {
90 Self::PageTable(PageTableNode::from_raw_spec(pte.paddr()))
91 }
92 }
93
94 pub open spec fn from_pte_frame_spec(pte: C::E, level: PagingLevel) -> Self {
95 Self::Frame(pte.paddr(), level, pte.prop())
96 }
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()
105 &&& regions.inv()
106 &&& self.wf(owner)
107 &&& owner.relate_region(regions)
108 &&& owner.in_scope
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.relate_region(regions)
118 &&& !owner.in_scope
119 }
120}
121
122impl<C: PageTableConfig> EntryOwner<C> {
123
124 pub open spec fn from_pte_regions_spec(self, regions: MetaRegionOwners) -> MetaRegionOwners {
125 if self.is_node() {
126 let index = frame_to_index(self.meta_slot_paddr().unwrap());
127 let old_slot = regions.slot_owners[index];
128 let new_slot = MetaSlotOwner {
129 raw_count: 0usize,
130 ..old_slot
131 };
132 MetaRegionOwners {
133 slots: regions.slots.insert(index, self.node.unwrap().meta_perm.points_to),
134 slot_owners: regions.slot_owners.insert(index, new_slot),
135 }
136 } else {
137 regions
138 }
139 }
140
141 pub open spec fn into_pte_regions_spec(self, regions: MetaRegionOwners) -> MetaRegionOwners {
142 if self.is_node() {
143 let index = frame_to_index(self.meta_slot_paddr().unwrap());
144 let old_slot = regions.slot_owners[index];
145 let new_slot = MetaSlotOwner {
146 raw_count: (old_slot.raw_count + 1) as usize,
147 ..old_slot
148 };
149 MetaRegionOwners {
150 slots: regions.slots,
151 slot_owners: regions.slot_owners.insert(index, new_slot),
152 ..regions
153 }
154 } else {
155 regions
156 }
157 }
158
159 pub open spec fn into_pte_owner_spec(self) -> EntryOwner<C> {
160 EntryOwner {
161 in_scope: false,
162 ..self
163 }
164 }
165
166 pub open spec fn from_pte_owner_spec(self) -> EntryOwner<C> {
167 EntryOwner {
168 in_scope: true,
169 ..self
170 }
171 }
172
173 pub open spec fn pte_invariants(self, pte: C::E, regions: MetaRegionOwners) -> bool {
176 &&& self.inv()
177 &&& regions.inv()
178 &&& self.match_pte(pte, self.parent_level)
179 &&& self.relate_region(regions)
180 &&& !self.in_scope
181 }
182
183}
184
185}