ostd/specs/mm/page_table/cursor/
tree_lemmas.rs1use core::ops::Range;
9
10use vstd::prelude::*;
11
12use vstd_extra::{ghost_tree::*, ownership::*};
13
14use crate::specs::{
15 arch::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE},
16 mm::page_table::{
17 cursor::owners::{CursorContinuation, CursorOwner},
18 node::entry_owners::EntryOwner,
19 owners::*,
20 },
21};
22
23use crate::mm::{Paddr, PagingLevel, Vaddr, page_prop::PageProperty, page_size, page_table::*};
24
25verus! {
26
27impl<'rcu, C: PageTableConfig> CursorContinuation<'rcu, C> {
29 pub proof fn map_children_lift(
31 self,
32 f: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool,
33 g: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool,
34 )
35 requires
36 self.inv(),
37 self.map_children(f),
38 OwnerSubtree::implies(f, g),
39 ensures
40 self.map_children(g),
41 {
42 assert forall|j: int|
43 #![auto]
44 0 <= j < self.children.len()
45 && self.children[j] is Some implies self.children[j].unwrap().subtree_satisfies(
46 self.path().push_tail(j),
47 g,
48 ) by {
49 self.inv_children_unroll(j);
50 OwnerSubtree::lemma_subtree_satisfies_implies(
51 self.children[j].unwrap(),
52 self.path().push_tail(j),
53 f,
54 g,
55 );
56 };
57 }
58
59 pub proof fn map_children_lift_skip_idx(
63 self,
64 cont0: Self,
65 idx: int,
66 f: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool,
67 g: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool,
68 )
69 requires
70 0 <= idx < NR_ENTRIES,
71 OwnerSubtree::implies(f, g),
72 cont0.inv(),
73 cont0.map_children(f),
74 self.path() == cont0.path(),
75 self.children.len() == cont0.children.len(),
76 forall|j: int|
77 #![auto]
78 0 <= j < NR_ENTRIES && j != idx ==> self.children[j] == cont0.children[j],
79 self.children[idx] is Some ==> self.children[idx]->0.subtree_satisfies(
80 self.path().push_tail(idx as int),
81 g,
82 ),
83 ensures
84 self.map_children(g),
85 {
86 assert forall|j: int|
87 #![auto]
88 0 <= j < self.children.len()
89 && self.children[j] is Some implies self.children[j].unwrap().subtree_satisfies(
90 self.path().push_tail(j),
91 g,
92 ) by {
93 if j != idx {
94 cont0.inv_children_unroll(j);
95 OwnerSubtree::lemma_subtree_satisfies_implies(
96 cont0.children[j].unwrap(),
97 cont0.path().push_tail(j),
98 f,
99 g,
100 );
101 }
102 };
103 }
104
105 pub proof fn as_subtree_restore(self, child: Self)
106 requires
107 self.inv(),
108 child.inv(),
109 self.all_but_index_some(),
110 child.all_some(),
111 ensures
112 self.restore(child).0.as_subtree() == self.put_child(child.as_subtree()).as_subtree(),
113 {
114 assert(self.put_child(child.as_subtree()).children == self.children.update(
115 self.idx as int,
116 Some(child.as_subtree()),
117 ));
118 }
119}
120
121impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
123 pub proof fn map_children_implies(
124 self,
125 f: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool,
126 g: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool,
127 )
128 requires
129 self.inv(),
130 OwnerSubtree::implies(f, g),
131 forall|i: int|
132 #![trigger self.continuations[i]]
133 self.level - 1 <= i < NR_LEVELS ==> self.continuations[i].map_children(f),
134 ensures
135 forall|i: int|
136 #![trigger self.continuations[i]]
137 self.level - 1 <= i < NR_LEVELS ==> self.continuations[i].map_children(g),
138 {
139 assert forall|i: int|
140 #![trigger self.continuations[i]]
141 self.level - 1 <= i < NR_LEVELS implies self.continuations[i].map_children(g) by {
142 let cont = self.continuations[i];
143 reveal(CursorContinuation::inv_children);
144 assert forall|j: int|
145 #![trigger cont.children[j]]
146 0 <= j < cont.children.len()
147 && cont.children[j] is Some implies cont.children[j].unwrap().subtree_satisfies(
148 cont.path().push_tail(j),
149 g,
150 ) by {
151 cont.inv_children_unroll(j);
152 OwnerSubtree::lemma_subtree_satisfies_implies(
153 cont.children[j].unwrap(),
154 cont.path().push_tail(j),
155 f,
156 g,
157 );
158 }
159 }
160 }
161
162 pub proof fn cur_entry_node_implies_level_gt_1(self)
164 requires
165 self.inv(),
166 self.cur_entry_owner().is_node(),
167 ensures
168 self.level > 1,
169 {
170 self.cur_subtree_inv();
171 }
172
173 #[verifier::spinoff_prover]
180 pub proof fn frame_not_fits_implies_level_gt_1(
181 self,
182 cur_entry_fits_range: bool,
183 cur_va: Vaddr,
184 end: Vaddr,
185 )
186 requires
187 self.inv(),
188 self.cur_entry_owner().is_frame(),
189 !cur_entry_fits_range,
190 cur_va < end,
191 cur_va == self.cur_va(),
193 cur_entry_fits_range == (cur_va == self.cur_va_range().start.to_vaddr()
195 && self.cur_va_range().end.to_vaddr() <= end),
196 cur_va as nat % PAGE_SIZE as nat == 0,
198 end as nat % PAGE_SIZE as nat == 0,
199 ensures
200 self.level > 1,
201 {
202 if self.level == 1 {
208 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_spec_level1();
209 self.va.align_down_concrete(1);
210 self.va.aligned_align_up_advances(1);
212 }
214 }
215
216 pub open spec fn not_in_tree(self, owner: EntryOwner<C>) -> bool {
218 self.map_full_tree(
219 |owner0: EntryOwner<C>, path: TreePath<NR_ENTRIES>| owner0.meta_slot_paddr_neq(owner),
220 )
221 }
222
223 pub proof fn absent_not_in_tree(self, owner: EntryOwner<C>)
224 requires
225 self.inv(),
226 owner.inv(),
227 owner.is_absent(),
228 ensures
229 self.not_in_tree(owner),
230 {
231 let g = |e: EntryOwner<C>, p: TreePath<NR_ENTRIES>| e.meta_slot_paddr_neq(owner);
232 let nsp = PageTableOwner::<C>::not_in_scope_pred();
233 assert(OwnerSubtree::implies(nsp, g)) by {
234 assert forall|entry: EntryOwner<C>, path: TreePath<NR_ENTRIES>|
235 entry.inv() && nsp(entry, path) implies #[trigger] g(entry, path) by {};
236 };
237 assert forall|i: int|
238 #![trigger self.continuations[i]]
239 self.level - 1 <= i < NR_LEVELS implies self.continuations[i].map_children(g) by {
240 let cont = self.continuations[i];
241 reveal(CursorContinuation::inv_children);
242 assert forall|j: int|
243 0 <= j < NR_ENTRIES
244 && #[trigger] cont.children[j] is Some implies cont.children[j].unwrap().subtree_satisfies(
245 cont.path().push_tail(j), g) by {
246 cont.inv_children_unroll(j);
247 PageTableOwner::tree_not_in_scope(
248 cont.children[j].unwrap(),
249 cont.path().push_tail(j),
250 );
251 cont.children[j].unwrap().lemma_subtree_satisfies_implies(
252 cont.path().push_tail(j),
253 nsp,
254 g,
255 );
256 };
257 };
258 }
259}
260
261}