ostd/specs/mm/page_table/node/
owners.rs1use vstd::cell::pcell_maybe_uninit;
2use vstd::prelude::*;
3
4use vstd::cell;
5use vstd::simple_pptr::*;
6
7use crate::mm::frame::meta::MetaSlot;
8use crate::mm::frame::meta::mapping::{max_meta_slots, meta_addr};
9use crate::mm::kspace::{LINEAR_MAPPING_BASE_VADDR, VMALLOC_BASE_VADDR};
10use crate::mm::paddr_to_vaddr;
11use crate::mm::page_table::PageTableGuard;
12use crate::mm::page_table::*;
13use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr};
14use crate::specs::arch::kspace::FRAME_METADATA_RANGE;
15use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
16use crate::specs::arch::paging_consts::PagingConsts;
17use crate::specs::mm::frame::mapping::{META_SLOT_SIZE, frame_to_index, meta_to_frame};
18use crate::specs::mm::frame::meta_owners::*;
19use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
20use crate::specs::mm::page_table::owners::INC_LEVELS;
21
22use vstd_extra::array_ptr;
23use vstd_extra::cast_ptr::Repr;
24use vstd_extra::ghost_tree::TreePath;
25use vstd_extra::ownership::*;
26
27verus! {
28
29pub tracked struct PageMetaOwner {
30 pub nr_children: pcell_maybe_uninit::PointsTo<u16>,
31 pub stray: pcell_maybe_uninit::PointsTo<bool>,
32}
33
34impl Inv for PageMetaOwner {
35 open spec fn inv(self) -> bool {
36 &&& self.nr_children.is_init()
37 &&& 0 <= self.nr_children.value() <= NR_ENTRIES
38 &&& self.stray.is_init()
39 }
40}
41
42pub ghost struct PageMetaModel {
43 pub nr_children: u16,
44 pub stray: bool,
45}
46
47impl Inv for PageMetaModel {
48 open spec fn inv(self) -> bool {
49 true
50 }
51}
52
53impl View for PageMetaOwner {
54 type V = PageMetaModel;
55
56 open spec fn view(&self) -> <Self as View>::V {
57 PageMetaModel { nr_children: self.nr_children.value(), stray: self.stray.value() }
58 }
59}
60
61impl InvView for PageMetaOwner {
62 proof fn view_preserves_inv(self) {
63 }
64}
65
66impl<C: PageTableConfig> OwnerOf for PageTablePageMeta<C> {
67 type Owner = PageMetaOwner;
68
69 open spec fn wf(self, owner: Self::Owner) -> bool {
70 &&& self.nr_children.id() == owner.nr_children.id()
71 &&& self.stray.id() == owner.stray.id()
72 &&& 0 <= owner.nr_children.value() <= NR_ENTRIES
73 }
74}
75
76pub tracked struct NodeOwner<C: PageTableConfig> {
77 pub meta_own: PageMetaOwner,
78 pub children_perm: array_ptr::PointsTo<C::E, NR_ENTRIES>,
79 pub level: PagingLevel,
80 pub tree_level: int,
81 pub slot_index: usize,
85}
86
87impl<C: PageTableConfig> Inv for NodeOwner<C> {
88 open spec fn inv(self) -> bool {
89 &&& self.meta_own.inv()
90 &&& 0 <= self.meta_own.nr_children.value() <= NR_ENTRIES
91 &&& 1 <= self.level <= NR_LEVELS
92 &&& self.children_perm.is_init_all()
93 &&& self.children_perm.addr() == paddr_to_vaddr(meta_to_frame(meta_addr(self.slot_index)))
94 &&& self.tree_level == INC_LEVELS - self.level - 1
95 &&& self.slot_index < max_meta_slots() as usize
96 &&& FRAME_METADATA_RANGE.start <= meta_addr(self.slot_index) < FRAME_METADATA_RANGE.end
97 &&& meta_addr(self.slot_index) % META_SLOT_SIZE == 0
98 &&& meta_to_frame(meta_addr(self.slot_index)) < VMALLOC_BASE_VADDR
99 - LINEAR_MAPPING_BASE_VADDR
100 &&& meta_to_frame(meta_addr(self.slot_index)) < MAX_PADDR
101 &&& meta_to_frame(meta_addr(self.slot_index)) == self.children_perm.addr()
102 &&& self.slot_index == frame_to_index(meta_to_frame(meta_addr(self.slot_index)))
103 }
104}
105
106impl<C: PageTableConfig> NodeOwner<C> {
107 pub open spec fn meta_addr_self(self) -> Vaddr {
110 meta_addr(self.slot_index)
111 }
112
113 pub open spec fn meta_perm_of(
116 self,
117 regions: MetaRegionOwners,
118 ) -> vstd_extra::cast_ptr::PointsTo<MetaSlot, Metadata<PageTablePageMeta<C>>> {
119 vstd_extra::cast_ptr::PointsTo::new_spec(
120 regions.slots[self.slot_index],
121 regions.slot_owners[self.slot_index].inner_perms,
122 )
123 }
124
125 pub open spec fn metaregion_sound_node(self, regions: MetaRegionOwners) -> bool {
129 let idx = self.slot_index;
130 &&& regions.slots.contains_key(idx)
131 &&& self.meta_perm_of(regions).is_init()
132 &&& self.meta_perm_of(regions).wf(&self.meta_perm_of(regions).inner_perms)
133 &&& self.meta_perm_of(regions).value().metadata.wf(self.meta_own)
134 &&& self.level == self.meta_perm_of(regions).value().metadata.level
135 &&& self.meta_own.nr_children.id() == self.meta_perm_of(
136 regions,
137 ).value().metadata.nr_children.id()
138 }
139}
140
141impl<C: PageTableConfig> NodeOwner<C> {
142 pub uninterp spec fn set_children_perm(self, idx: usize, pte: C::E) -> Self;
145
146 #[verifier::external_body]
147 pub axiom fn set_children_perm_axiom(self, idx: usize, pte: C::E)
148 requires
149 self.inv(),
150 idx < NR_ENTRIES,
151 ensures
152 self.set_children_perm(idx, pte).inv(),
153 self.set_children_perm(idx, pte).meta_own == self.meta_own,
154 self.set_children_perm(idx, pte).slot_index == self.slot_index,
155 self.set_children_perm(idx, pte).level == self.level,
156 self.set_children_perm(idx, pte).tree_level == self.tree_level,
157 self.set_children_perm(idx, pte).children_perm.addr() == self.children_perm.addr(),
158 self.set_children_perm(idx, pte).children_perm.value()
159 == self.children_perm.value().update(idx as int, pte),
160 ;
161
162 pub axiom fn nr_children_absent_slot_bound(self, idx: usize)
173 requires
174 self.inv(),
175 idx < NR_ENTRIES,
176 !self.children_perm.value()[idx as int].is_present(),
177 ensures
178 self.meta_own.nr_children.value() < NR_ENTRIES,
179 ;
180
181 pub axiom fn nr_children_present_slot_bound(self, idx: usize)
185 requires
186 self.inv(),
187 idx < NR_ENTRIES,
188 self.children_perm.value()[idx as int].is_present(),
189 ensures
190 self.meta_own.nr_children.value() > 0,
191 ;
192}
193
194impl<'rcu, C: PageTableConfig> NodeOwner<C> {
195 pub open spec fn relate_guard(self, guard: PageTableGuard<'rcu, C>) -> bool {
196 &&& guard.inner.inner@.ptr.addr() == self.meta_addr_self()
197 &&& guard.inner.inner@.wf(self)
198 }
199}
200
201pub ghost struct NodeModel<C: PageTableConfig> {
202 pub level: PagingLevel,
203 pub _phantom: core::marker::PhantomData<C>,
204}
205
206impl<C: PageTableConfig> Inv for NodeModel<C> {
207 open spec fn inv(self) -> bool {
208 true
209 }
210}
211
212impl<C: PageTableConfig> View for NodeOwner<C> {
213 type V = NodeModel<C>;
214
215 open spec fn view(&self) -> <Self as View>::V {
216 NodeModel { level: self.level, _phantom: core::marker::PhantomData }
217 }
218}
219
220impl<C: PageTableConfig> InvView for NodeOwner<C> {
221 proof fn view_preserves_inv(self) {
222 }
223}
224
225impl<C: PageTableConfig> OwnerOf for PageTableNode<C> {
226 type Owner = NodeOwner<C>;
227
228 open spec fn wf(self, owner: Self::Owner) -> bool {
229 &&& self.ptr.addr() == owner.meta_addr_self()
230 }
231}
232
233impl<C: PageTableConfig> PageTableNode<C> {
234 pub open spec fn invariants(self, owner: NodeOwner<C>) -> bool {
235 &&& owner.inv()
236 &&& self.wf(
237 owner,
238 )
239 }
244}
245
246}