ostd/specs/mm/page_table/cursor/
cursor_fn_lemmas.rs1use vstd::{arithmetic::power2::pow2, prelude::*};
3use vstd_extra::{ghost_tree::*, ownership::*};
4
5use crate::specs::{
6 arch::*,
7 mm::{
8 frame::meta_region_owners::MetaRegionOwners,
9 page_table::{
10 Mapping,
11 cursor::owners::{CursorContinuation, CursorOwner},
12 lemma_pte_index_bound, nat_align_down,
13 owners::*,
14 pte_index_spec,
15 },
16 },
17};
18
19use crate::mm::{PagingConstsTrait, PagingLevel, Vaddr, page_size, page_table::*};
20use core::ops::Range;
21
22verus! {
23
24broadcast use group_ghost_tree_lemmas;
25
26impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
27 pub proof fn protect_preserves_cursor_inv_metaregion(
28 self,
29 other: Self,
30 regions: MetaRegionOwners,
31 )
32 requires
33 self.inv(),
34 self.in_locked_range(),
35 !self.popped_too_high,
36 self.metaregion_sound(regions),
37 self.cur_entry_owner().is_frame(),
38 other.cur_entry_owner().is_frame(),
39 other.cur_entry_owner().inv(),
40 other.cur_entry_owner().frame().mapped_pa == self.cur_entry_owner().frame().mapped_pa,
42 other.cur_entry_owner().path == self.cur_entry_owner().path,
43 other.cur_entry_owner().parent_level == self.cur_entry_owner().parent_level,
44 self.level == other.level,
46 self.guard_level == other.guard_level,
47 self.va == other.va,
48 self.prefix == other.prefix,
49 self.popped_too_high == other.popped_too_high,
50 forall|i: int|
52 self.level <= i < NR_LEVELS ==> #[trigger] self.continuations[i]
53 == other.continuations[i],
54 other.continuations[self.level - 1].inv(),
56 other.continuations[self.level - 1].all_some(),
57 other.continuations[self.level - 1].idx == self.continuations[self.level - 1].idx,
58 other.continuations[self.level - 1].entry_own.parent_level
59 == self.continuations[self.level - 1].entry_own.parent_level,
60 other.continuations[self.level - 1].guard.inner.inner@.ptr.addr()
61 == self.continuations[self.level - 1].guard.inner.inner@.ptr.addr(),
62 other.continuations[self.level - 1].path() == self.continuations[self.level - 1].path(),
63 other.continuations.dom() =~= self.continuations.dom(),
64 forall|j: int|
65 0 <= j < NR_ENTRIES && j != self.continuations[self.level - 1].idx
66 ==> #[trigger] other.continuations[self.level - 1].children[j]
67 == self.continuations[self.level - 1].children[j],
68 ({
69 let new_child = other.continuations[self.level
70 - 1].children[other.continuations[self.level - 1].idx as int]->0;
71 let new_path = other.continuations[self.level - 1].path().push_tail(
72 other.continuations[self.level - 1].idx as int,
73 );
74 new_child.subtree_satisfies(
75 new_path,
76 PageTableOwner::<C>::metaregion_sound_pred(regions),
77 )
78 }),
79 other.continuations[self.level - 1].entry_own.metaregion_sound(regions),
80 ensures
81 other.inv(),
82 other.metaregion_sound(regions),
83 {
84 self.lemma_cur_pte_index();
85 other.map_branch_none_inv_holds(self);
86
87 let f = PageTableOwner::<C>::metaregion_sound_pred(regions);
88 let L = self.level as int;
89 let idx = self.continuations[L - 1].idx as int;
90
91 assert forall|i: int|
92 #![trigger other.continuations[i]]
93 other.level - 1 <= i < NR_LEVELS implies other.continuations[i].map_children(f) by {
94 reveal(CursorContinuation::map_children);
95 if i > L - 1 {
96 assert(other.continuations[i] == self.continuations[i]);
97 assert(self.continuations[i].map_children(f));
98 } else {
99 assert(i == L - 1);
100 let o_cont = other.continuations[L - 1];
101 let s_cont = self.continuations[L - 1];
102 reveal(CursorContinuation::inv_children);
103 assert forall|j: int|
104 #![trigger o_cont.children[j]]
105 0 <= j < o_cont.children.len()
106 && o_cont.children[j] is Some implies o_cont.children[j].unwrap().subtree_satisfies(
107 o_cont.path().push_tail(j), f) by {
108 if j != idx {
109 assert(o_cont.children[j] == s_cont.children[j]);
110 s_cont.lemma_inv_children_unroll(j);
111 }
112 };
113 }
114 };
115
116 reveal(CursorOwner::path_metaregion_sound);
117 assert forall|i: int|
118 #![trigger other.continuations[i]]
119 other.level - 1 <= i
120 < NR_LEVELS implies other.continuations[i].entry_own.metaregion_sound(regions) by {
121 if i > L - 1 {
122 assert(other.continuations[i] == self.continuations[i]);
123 self.lemma_inv_continuation(i);
124 }
125 };
126 }
127
128 pub proof fn map_branch_none_inv_holds(self, owner0: Self)
129 requires
130 owner0.inv(),
131 self.in_locked_range(),
136 !self.popped_too_high,
137 forall|j: int|
138 0 <= j < NR_ENTRIES && j != owner0.continuations[owner0.level - 1].idx ==> (
139 #[trigger] self.continuations[self.level - 1].children[j])
140 == owner0.continuations[owner0.level - 1].children[j],
141 self.level == owner0.level,
142 self.va == owner0.va,
143 self.guard_level == owner0.guard_level,
144 self.prefix == owner0.prefix,
145 self.popped_too_high == owner0.popped_too_high,
146 forall|i: int|
148 self.level <= i < NR_LEVELS ==> #[trigger] self.continuations[i]
149 == owner0.continuations[i],
150 self.continuations[self.level - 1].inv(),
152 self.continuations[self.level - 1].all_some(),
153 self.continuations[self.level - 1].idx == owner0.continuations[owner0.level - 1].idx,
154 self.continuations[self.level - 1].entry_own.parent_level
155 == owner0.continuations[owner0.level - 1].entry_own.parent_level,
156 self.continuations[self.level - 1].guard.inner.inner@.ptr.addr()
158 == owner0.continuations[owner0.level - 1].guard.inner.inner@.ptr.addr(),
159 self.continuations[self.level - 1].path() == owner0.continuations[owner0.level
160 - 1].path(),
161 pte_index_spec::<C>(self.cur_va(), (self.level - 1 + 1) as PagingLevel)
162 == self.continuations[self.level - 1].idx,
163 self.continuations.dom() =~= owner0.continuations.dom(),
165 ensures
166 self.inv(),
167 {
168 let L = self.level as int;
169 C::lemma_paging_consts_properties();
170 lemma_pte_index_bound::<C>(self.cur_va(), self.level);
171 assert(pte_index_spec::<C>(self.va, (self.level - 1 + 1) as PagingLevel)
172 == self.continuations[self.level - 1].idx);
173 assert(self.continuations[L - 1].level() == self.level);
174 assert(self.continuations.contains_key(L - 1));
175 if self.level < NR_LEVELS {
177 assert(self.continuations[NR_LEVELS - 1] == owner0.continuations[NR_LEVELS - 1]);
180 } else {
181 owner0.lemma_in_locked_range_top_index_lt_top_end();
187 assert(self.continuations[NR_LEVELS - 1].idx == pte_index_spec::<C>(
188 self.va,
189 (NR_LEVELS - 1 + 1) as PagingLevel,
190 ));
191 assert(self.continuations[NR_LEVELS - 1].idx == owner0.continuations[owner0.level
192 - 1].idx);
193 assert(C::TOP_LEVEL_INDEX_RANGE().start <= owner0.continuations[owner0.level - 1].idx
194 < C::TOP_LEVEL_INDEX_RANGE().end);
195 assert(forall|j: int|
196 0 <= j < NR_ENTRIES && !(C::TOP_LEVEL_INDEX_RANGE().start <= j
197 < C::TOP_LEVEL_INDEX_RANGE().end) ==> (#[trigger] self.continuations[NR_LEVELS
198 - 1].children[j]) is Some ==> (self.continuations[NR_LEVELS
199 - 1].children[j].unwrap().value().is_borrowed() || self.continuations[NR_LEVELS
200 - 1].children[j].unwrap().value().is_absent()));
201 }
202 }
203
204 pub proof fn map_branch_none_no_new_mappings(self, owner0: Self)
206 requires
207 owner0.inv(),
208 owner0.in_locked_range(),
209 self.inv(),
210 self.in_locked_range(),
211 self.level == owner0.level,
212 self.va == owner0.va,
213 forall|i: int|
214 self.level <= i < NR_LEVELS ==> #[trigger] self.continuations[i]
215 == owner0.continuations[i],
216 owner0.continuations[owner0.level - 1].children[owner0.continuations[owner0.level
218 - 1].idx as int] is Some,
219 owner0.continuations[owner0.level - 1].children[owner0.continuations[owner0.level
220 - 1].idx as int]->0.value().is_absent(),
221 self.continuations[self.level - 1].children[self.continuations[self.level
222 - 1].idx as int] is Some,
223 self.continuations[self.level - 1].children[self.continuations[self.level
224 - 1].idx as int]->0.value().is_node(),
225 self.continuations[self.level - 1].path() == owner0.continuations[owner0.level
227 - 1].path(),
228 forall|j: int|
229 0 <= j < NR_ENTRIES && j != owner0.continuations[owner0.level - 1].idx as int
230 ==> #[trigger] self.continuations[self.level - 1].children[j]
231 == owner0.continuations[owner0.level - 1].children[j],
232 PageTableOwner(
234 self.continuations[self.level - 1].children[self.continuations[self.level
235 - 1].idx as int]->0,
236 ).view_rec(
237 self.continuations[self.level - 1].path().push_tail(
238 self.continuations[self.level - 1].idx as int,
239 ),
240 ) =~= Set::<Mapping>::empty(),
241 ensures
242 self.view_mappings() == owner0.view_mappings(),
243 {
244 broadcast use {CursorContinuation::group_lemmas, CursorOwner::group_lemmas};
245
246 let L = self.level as int;
247 let cont = self.continuations[L - 1];
248 let cont0 = owner0.continuations[L - 1];
249 let idx = cont0.idx as int;
250
251 assert(cont.view_mappings() == cont0.view_mappings()) by {
252 cont0.lemma_inv_children_unroll(idx);
253 PageTableOwner(cont0.children[idx].unwrap()).view_rec_absent_empty(
254 cont0.path().push_tail(idx as int),
255 );
256 assert forall|m: Mapping|
257 cont.view_mappings().contains(m) implies cont0.view_mappings().contains(m) by {
258 let j = choose|j: int|
259 0 <= j < cont.children.len() && #[trigger] cont.children[j] is Some
260 && PageTableOwner(cont.children[j].unwrap()).view_rec(
261 cont.path().push_tail(j),
262 ).contains(m);
263 if j == idx {
264 assert(false);
266 } else {
267 assert(cont.children[j] == cont0.children[j]);
268 }
269 };
270 assert forall|m: Mapping|
271 cont0.view_mappings().contains(m) implies cont.view_mappings().contains(m) by {
272 let j = choose|j: int|
273 0 <= j < cont0.children.len() && #[trigger] cont0.children[j] is Some
274 && PageTableOwner(cont0.children[j].unwrap()).view_rec(
275 cont0.path().push_tail(j),
276 ).contains(m);
277 if j == idx {
278 assert(false);
280 } else {
281 assert(cont0.children[j] == cont.children[j]);
282 }
283 };
284 };
285 assert(self.view_mappings() == owner0.view_mappings()) by {
287 assert forall|m: Mapping|
288 self.view_mappings().contains(m) implies owner0.view_mappings().contains(m) by {
289 let i = choose|i: int|
290 self.level - 1 <= i < NR_LEVELS
291 && #[trigger] self.continuations[i].view_mappings().contains(m);
292 if i == L - 1 {
293 assert(cont0.view_mappings().contains(m));
294 } else {
295 assert(owner0.continuations[i] == self.continuations[i]);
296 }
297 };
298 assert forall|m: Mapping|
299 owner0.view_mappings().contains(m) implies self.view_mappings().contains(m) by {
300 let i = choose|i: int|
301 owner0.level - 1 <= i < NR_LEVELS
302 && #[trigger] owner0.continuations[i].view_mappings().contains(m);
303 if i == L - 1 {
304 assert(cont.view_mappings().contains(m));
305 } else {
306 assert(self.continuations[i] == owner0.continuations[i]);
307 }
308 };
309 };
310 }
311}
312
313}