1use vstd::prelude::*;
2
3use vstd_extra::{
4 arithmetic::{
5 lemma_nat_align_down_monotone, lemma_nat_align_down_within_block, nat_align_down,
6 },
7 ghost_tree::*,
8 ownership::*,
9};
10
11use crate::specs::{
12 arch::{NR_ENTRIES, NR_LEVELS},
13 mm::page_table::{
14 AbstractVaddr, Mapping,
15 cursor::{owners::*, page_size_lemmas::lemma_page_size_divides},
16 owners::{
17 INC_LEVELS, OwnerSubtree, PageTableOwner, lemma_vaddr_of_eq_int,
18 sibling_paths_disjoint, vaddr, vaddr_of,
19 },
20 },
21};
22
23use crate::mm::{PagingLevel, Vaddr, page_size, page_table::*};
24
25verus! {
26
27broadcast use group_ghost_tree_lemmas;
28impl<'rcu, C: PageTableConfig> CursorContinuation<'rcu, C> {
31 pub proof fn as_page_table_owner_preserves_view_mappings(self)
32 requires
33 self.inv(),
34 self.all_some(),
35 ensures
36 self.as_page_table_owner().view_rec(self.path()) == self.view_mappings(),
37 self.as_subtree().inv(),
38 PageTableOwner(self.as_subtree()).pt_inv(),
39 {
40 broadcast use {CursorContinuation::group_lemmas, PageTableOwner::group_lemmas};
41
42 self.inv_children_unroll_all();
43 self.as_subtree_inv();
44 self.as_page_table_owner_pt_inv();
45 let pto = self.as_page_table_owner();
46 assert(self.as_page_table_owner().view_rec(self.path()) == self.view_mappings()) by {
47 assert forall|m: Mapping|
48 #![auto]
49 self.view_mappings().contains(m) implies pto.view_rec(self.path()).contains(m) by {
50 let i = choose|i: int|
51 #![auto]
52 0 <= i < self.children.len() && self.children[i] is Some && PageTableOwner(
53 self.children[i].unwrap(),
54 ).view_rec(self.path().push_tail(i)).contains(m);
55 assert(pto.view_rec(self.path()).contains(m));
56 };
57 assert forall|m: Mapping|
58 pto.view_rec(self.path()).contains(
59 m,
60 ) implies #[trigger] self.view_mappings().contains(m) by {
61 let i = choose|i: int|
62 #![auto]
63 0 <= i < pto.0.children().len() && pto.0.children()[i] is Some
64 && PageTableOwner(pto.0.children()[i].unwrap()).view_rec(
65 self.path().push_tail(i),
66 ).contains(m);
67 };
68 };
69 }
70
71 pub proof fn view_mappings_take_child(self)
72 requires
73 self.inv(),
74 self.all_some(),
75 ensures
76 self.take_child().1.view_mappings() == self.view_mappings()
77 - self.view_mappings_take_child_spec(),
78 {
79 broadcast use CursorContinuation::group_lemmas;
80
81 self.inv_children_unroll_all();
82 let def = self.take_child().1.view_mappings();
83 let diff = self.view_mappings() - self.view_mappings_take_child_spec();
84 assert forall|m: Mapping| diff.contains(m) implies def.contains(m) by {
85 let i = choose|i: int|
86 0 <= i < self.children.len() && #[trigger] self.children[i] is Some
87 && PageTableOwner(self.children[i].unwrap()).view_rec(
88 self.path().push_tail(i),
89 ).contains(m);
90 assert(i != self.idx);
91 assert(self.take_child().1.children[i] is Some);
92 };
93 assert forall|m: Mapping| #![trigger def.contains(m)] def.contains(m) implies diff.contains(
94 m,
95 ) by {
96 let left = self.take_child().1;
97 assert(left.view_mappings().contains(m));
98 let wi = choose|i: int|
100 #![auto]
101 0 <= i < left.children.len() && left.children[i] is Some && PageTableOwner(
102 left.children[i].unwrap(),
103 ).view_rec(left.path().push_tail(i)).contains(m);
104 if self.view_mappings_take_child_spec().contains(m) {
105 assert(PageTableOwner(self.children[self.idx as int].unwrap()).view_rec(
106 self.path().push_tail(self.idx as int),
107 ).contains(m));
108 let i = choose|i: int|
109 0 <= i < left.children.len() && #[trigger] left.children[i] is Some
110 && PageTableOwner(left.children[i].unwrap()).view_rec(
111 left.path().push_tail(i),
112 ).contains(m);
113 assert(PageTableOwner(left.children[i as int].unwrap()).view_rec(
114 left.path().push_tail(i),
115 ).contains(m));
116
117 PageTableOwner(self.children[self.idx as int].unwrap()).view_rec_vaddr_range(
118 self.path().push_tail(self.idx as int),
119 m,
120 );
121 PageTableOwner(left.children[i as int].unwrap()).view_rec_vaddr_range(
122 left.path().push_tail(i),
123 m,
124 );
125
126 let size = page_size((INC_LEVELS - self.path().len() - 1) as PagingLevel);
127 sibling_paths_disjoint::<C>(self.path(), self.idx as int, i, size);
129 lemma_vaddr_of_eq_int::<C>(self.path().push_tail(self.idx as int));
130 lemma_vaddr_of_eq_int::<C>(self.path().push_tail(i));
131 }
132 };
133 }
134
135 pub proof fn view_mappings_put_child(self, child: OwnerSubtree<C>)
136 requires
137 self.inv(),
138 child.inv(),
139 self.all_but_index_some(),
140 ensures
141 self.put_child(child).view_mappings() == self.view_mappings() + PageTableOwner(
142 child,
143 ).view_rec(self.path().push_tail(self.idx as int)),
144 {
145 broadcast use CursorContinuation::group_lemmas;
146
147 let def = self.put_child(child).view_mappings();
148 let sum = self.view_mappings() + PageTableOwner(child).view_rec(
149 self.path().push_tail(self.idx as int),
150 );
151 assert forall|m: Mapping| sum.contains(m) implies def.contains(m) by {
152 if self.view_mappings().contains(m) {
153 let i = choose|i: int|
154 0 <= i < self.children.len() && #[trigger] self.children[i] is Some
155 && PageTableOwner(self.children[i].unwrap()).view_rec(
156 self.path().push_tail(i),
157 ).contains(m);
158 assert(self.put_child(child).children[i] == self.children[i]);
159 self.put_child(child).lemma_view_mappings_intro(m, i);
160 } else {
161 assert(PageTableOwner(child).view_rec(
162 self.path().push_tail(self.idx as int),
163 ).contains(m));
164 assert(self.put_child(child).children[self.idx as int] == Some(child));
165 self.put_child(child).lemma_view_mappings_intro(m, self.idx as int);
166 }
167 };
168 assert forall|m: Mapping| def.contains(m) implies sum.contains(m) by {
169 let i = choose|i: int|
170 0 <= i < self.put_child(child).children.len() && #[trigger] self.put_child(
171 child,
172 ).children[i] is Some && PageTableOwner(
173 self.put_child(child).children[i].unwrap(),
174 ).view_rec(self.put_child(child).path().push_tail(i)).contains(m);
175 if i == self.idx {
176 } else {
177 assert(self.children[i] == self.put_child(child).children[i]);
178 }
179 };
180 }
181}
182
183impl<'rcu, C: PageTableConfig> CursorContinuation<'rcu, C> {
184 proof fn as_subtree_inv(self)
186 requires
187 self.inv(),
188 self.all_some(),
189 ensures
190 self.as_subtree().inv(),
191 {
192 self.inv_children_unroll_all();
193 }
194
195 proof fn as_page_table_owner_pt_inv(self)
196 requires
197 self.inv(),
198 self.all_some(),
199 ensures
200 PageTableOwner(self.as_subtree()).pt_inv(),
201 {
202 self.as_subtree_inv();
203 let st = self.as_subtree();
204 let depth = (INC_LEVELS - st.level()) as nat;
205 assert forall|i: int|
206 #![trigger st.children()[i]]
207 0 <= i < NR_ENTRIES implies PageTableOwner::<C>::pt_edge_at(st, i) && PageTableOwner(
208 st.children()[i].unwrap(),
209 ).pt_inv_at_depth((depth - 1) as nat) by {
210 self.inv_children_rel_unroll(i);
211 self.pt_inv_children_unroll(i);
212 };
213 }
214}
215
216impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
218 pub proof fn cur_subtree_eq_filtered_mappings_path(self)
221 requires
222 self.inv(),
223 self.in_locked_range(),
224 ensures
225 ({
226 let subtree_va = vaddr_of::<C>(self.cur_subtree().value().path) as int;
227 let size = page_size(self.level) as int;
228 PageTableOwner(self.cur_subtree())@.mappings == self@.mappings.filter(
229 |m: Mapping| subtree_va <= m.va_range.start < subtree_va + size,
230 )
231 }),
232 {
233 broadcast use {CursorContinuation::group_lemmas, CursorOwner::group_lemmas};
234
235 let cur_subtree = self.cur_subtree();
236 let cur_path = cur_subtree.value().path;
237 let subtree_va = vaddr_of::<C>(cur_path) as int;
238 let size = page_size(self.level) as int;
239
240 let subtree_mappings = PageTableOwner(cur_subtree)@.mappings;
241 let filtered = self@.mappings.filter(
242 |m: Mapping| subtree_va <= m.va_range.start < subtree_va + size,
243 );
244
245 self.cur_subtree_inv();
246
247 let cont = self.continuations[self.level - 1];
248 self.inv_continuation(self.level - 1);
249 cont.inv_children_rel_unroll(self.index() as int);
250 assert forall|m: Mapping| subtree_mappings.contains(m) implies filtered.contains(m) by {
254 assert(cont.children[self.index() as int] is Some);
256 assert(cont.children[self.index() as int].unwrap() == cur_subtree);
257
258 PageTableOwner(cur_subtree).view_rec_vaddr_range(cur_path, m);
262 };
263
264 assert forall|m: Mapping| filtered.contains(m) implies subtree_mappings.contains(m) by {
266 let i = choose|i: int|
268 self.level - 1 <= i < NR_LEVELS
269 && #[trigger] self.continuations[i].view_mappings().contains(m);
270 self.inv_continuation(i);
271
272 let cont_i = self.continuations[i];
273 let j = choose|j: int|
274 #![auto]
275 0 <= j < NR_ENTRIES && cont_i.children[j] is Some && PageTableOwner(
276 cont_i.children[j].unwrap(),
277 ).view_rec(cont_i.path().push_tail(j)).contains(m);
278
279 cont_i.inv_children_unroll(j);
280 PageTableOwner(cont_i.children[j].unwrap()).view_rec_vaddr_range(
281 cont_i.path().push_tail(j),
282 m,
283 );
284
285 if i == self.level - 1 {
286 if j as usize == self.index() {
287 assert(cont_i.children[j] == Some(cur_subtree));
290 assert(cont_i.path().push_tail(j) == cur_path);
291 assert(subtree_mappings == PageTableOwner(cur_subtree).view_rec(cur_path));
292 assert(PageTableOwner(cur_subtree).view_rec(cur_path).contains(m));
293 assert(subtree_mappings.contains(m));
294 } else {
295 let sib_size = page_size((INC_LEVELS - cont.path().len() - 1) as PagingLevel);
297 sibling_paths_disjoint::<C>(cont.path(), self.index() as int, j, sib_size);
298 lemma_vaddr_of_eq_int::<C>(cont.path().push_tail(self.index() as int));
301 lemma_vaddr_of_eq_int::<C>(cont.path().push_tail(j));
302 assert(false); }
304 } else {
305 if j as usize != cont_i.idx as int {
306 self.subtree_va_in_ancestor_range(i);
308
309 let sib_size = page_size((INC_LEVELS - cont_i.path().len() - 1) as PagingLevel);
311 sibling_paths_disjoint::<C>(cont_i.path(), cont_i.idx as int, j, sib_size);
312 lemma_vaddr_of_eq_int::<C>(cont_i.path().push_tail(cont_i.idx as int));
313 lemma_vaddr_of_eq_int::<C>(cont_i.path().push_tail(j));
314 lemma_vaddr_of_eq_int::<C>(cur_path);
315 assert(false); } else {
317 assert(cont_i.children[cont_i.idx as int] is None);
318 assert(false); }
320 }
321 };
322
323 assert(subtree_mappings == filtered);
324 }
325
326 pub proof fn cur_subtree_eq_filtered_mappings(self)
329 requires
330 self.inv(),
331 self.in_locked_range(),
332 ensures
333 ({
334 let start = nat_align_down(
335 self@.cur_va as nat,
336 page_size(self.level) as nat,
337 ) as Vaddr;
338 let size = page_size(self.level);
339 PageTableOwner(self.cur_subtree())@.mappings == self@.mappings.filter(
340 |m: Mapping| start <= m.va_range.start < start + size,
341 )
342 }),
343 {
344 self.cur_subtree_eq_filtered_mappings_path();
349 self.cur_va_in_cont_child_range(self.level - 1);
350 self.va.to_path_vaddr_concrete(self.level - 1);
351 let cur_path = self.cur_subtree().value().path;
352 let ps = page_size(self.level);
353 lemma_vaddr_of_eq_int::<C>(cur_path);
354 vstd_extra::arithmetic::lemma_nat_align_down_sound(self@.cur_va as nat, ps as nat);
357 let nad = nat_align_down(self@.cur_va as nat, ps as nat);
358 assert(nad as Vaddr == nad);
359 assert(nad as Vaddr == vaddr_of::<C>(cur_path));
360 }
361
362 proof fn cur_va_in_cont_child_range(self, lvl: int)
366 requires
367 self.inv(),
368 self.in_locked_range(),
369 self.level - 1 <= lvl < NR_LEVELS,
370 ensures
371 vaddr(self.continuations[lvl].path().push_tail(self.continuations[lvl].idx as int))
372 + self.va.leading_bits * 0x1_0000_0000_0000int <= self.cur_va(),
373 self.cur_va() < vaddr(
374 self.continuations[lvl].path().push_tail(self.continuations[lvl].idx as int),
375 ) + self.va.leading_bits * 0x1_0000_0000_0000int + page_size((lvl + 1) as PagingLevel),
376 vaddr(self.continuations[lvl].path().push_tail(self.continuations[lvl].idx as int))
377 == vaddr(self.va.to_path(lvl)),
378 {
379 let cont = self.continuations[lvl];
380 let child_path = cont.path().push_tail(cont.idx as int);
381 let va_path = self.va.to_path(lvl);
382
383 self.va.to_path_len(lvl);
384 assert forall|k: int| 0 <= k < child_path.len() implies child_path[k] == va_path[k] by {
385 self.va.to_path_index(lvl, k);
386 };
387
388 self.va.to_path_inv(lvl);
389 AbstractVaddr::rec_vaddr_eq_if_indices_eq(child_path, va_path, 0);
390 self.va.vaddr_range_from_path(lvl);
391 }
392
393 proof fn subtree_va_in_ancestor_range(self, lvl: int)
396 requires
397 self.inv(),
398 self.in_locked_range(),
399 self.level - 1 < lvl < NR_LEVELS,
400 ensures
401 ({
402 let subtree_va = vaddr(self.cur_subtree().value().path);
403 let idx_path_va = vaddr(
404 self.continuations[lvl].path().push_tail(self.continuations[lvl].idx as int),
405 );
406 &&& idx_path_va <= subtree_va
407 &&& subtree_va + page_size(self.level) <= idx_path_va + page_size(
408 (lvl + 1) as PagingLevel,
409 )
410 }),
411 {
412 let cont = self.continuations[self.level - 1];
413 self.inv_continuation(self.level - 1);
414 cont.inv_children_rel_unroll(self.index() as int);
415 self.cur_va_in_cont_child_range(self.level - 1);
418 self.cur_va_in_cont_child_range(lvl);
419 self.va.to_path_vaddr_concrete(self.level - 1);
420 self.va.to_path_vaddr_concrete(lvl);
421
422 let x = self.cur_va() as nat;
423 let fine = page_size(self.level as PagingLevel) as nat;
424 let coarse = page_size((lvl + 1) as PagingLevel) as nat;
425 let shift = self.va.leading_bits * 0x1_0000_0000_0000int;
426
427 let subtree_va = vaddr(self.cur_subtree().value().path);
429 assert(subtree_va == vaddr(self.va.to_path(self.level - 1)));
430 assert(subtree_va + shift == nat_align_down(x, fine));
431
432 let idx_path_va = vaddr(
434 self.continuations[lvl].path().push_tail(self.continuations[lvl].idx as int),
435 );
436 assert(idx_path_va == vaddr(self.va.to_path(lvl)));
437 assert(idx_path_va + shift == nat_align_down(x, coarse));
438
439 lemma_page_size_divides(self.level as PagingLevel, (lvl + 1) as PagingLevel);
440 lemma_nat_align_down_monotone(x, fine, coarse);
441 lemma_nat_align_down_within_block(x, fine, coarse);
442
443 vstd_extra::arithmetic::lemma_nat_align_down_sound(x, fine);
445 vstd_extra::arithmetic::lemma_nat_align_down_sound(x, coarse);
446 }
447
448 pub proof fn subtree_va_ranges_disjoint(self, j: int)
450 requires
451 self.inv(),
452 self.in_locked_range(),
453 0 <= j < NR_ENTRIES,
454 j != self.index(),
455 self.continuations[self.level - 1].children[j] is Some,
456 ensures
457 vaddr(self.continuations[self.level - 1].path().push_tail(j)) + self.va.leading_bits
458 * 0x1_0000_0000_0000int + page_size(self.level as PagingLevel) <= self.cur_va()
459 || self.cur_va() < vaddr(self.continuations[self.level - 1].path().push_tail(j))
460 + self.va.leading_bits * 0x1_0000_0000_0000int,
461 {
462 let cont = self.continuations[self.level - 1];
463 let idx = self.index();
464
465 self.cur_va_in_cont_child_range(self.level - 1);
468
469 let size = page_size((INC_LEVELS - cont.path().len() - 1) as PagingLevel);
471 sibling_paths_disjoint::<C>(cont.path(), idx as int, j, size);
472 }
473
474 pub proof fn higher_level_children_disjoint(self, i: int, j: int)
477 requires
478 self.inv(),
479 self.in_locked_range(),
480 self.level - 1 < i < NR_LEVELS,
481 0 <= j < NR_ENTRIES,
482 j != self.continuations[i].idx,
483 self.continuations[i].children[j] is Some,
484 ensures
485 vaddr(self.continuations[i].path().push_tail(j)) + self.va.leading_bits
486 * 0x1_0000_0000_0000int + page_size((i + 1) as PagingLevel) <= self.cur_va()
487 || self.cur_va() < vaddr(self.continuations[i].path().push_tail(j))
488 + self.va.leading_bits * 0x1_0000_0000_0000int,
489 {
490 let cont = self.continuations[i];
491
492 self.cur_va_in_cont_child_range(i);
495
496 let size = page_size((INC_LEVELS - cont.path().len() - 1) as PagingLevel);
498 sibling_paths_disjoint::<C>(cont.path(), cont.idx as int, j, size);
499 }
500
501 pub proof fn mapping_covering_cur_va_from_cur_subtree(self, m: Mapping)
505 requires
506 self.inv(),
507 self.in_locked_range(),
508 self.view_mappings().contains(m),
509 m.va_range.start <= self.cur_va() < m.va_range.end,
510 ensures
511 PageTableOwner(self.cur_subtree()).view_rec(self.cur_subtree().value().path).contains(
512 m,
513 ),
514 {
515 broadcast use {CursorContinuation::group_lemmas, CursorOwner::group_lemmas};
516
517 let cur_va = self.cur_va();
518
519 let i = choose|i: int|
521 self.level - 1 <= i < NR_LEVELS
522 && #[trigger] self.continuations[i].view_mappings().contains(m);
523 self.inv_continuation(i);
524
525 let cont_i = self.continuations[i];
526 let j = choose|j: int|
527 #![auto]
528 0 <= j < NR_ENTRIES && cont_i.children[j] is Some && PageTableOwner(
529 cont_i.children[j].unwrap(),
530 ).view_rec(cont_i.path().push_tail(j)).contains(m);
531
532 cont_i.inv_children_unroll(j);
533 let child_j = cont_i.children[j].unwrap();
534 let path_j = cont_i.path().push_tail(j);
535 PageTableOwner(child_j).view_rec_vaddr_range(path_j, m);
536 lemma_vaddr_of_eq_int::<C>(path_j);
539
540 if i == self.level - 1 {
541 if j as usize != self.index() {
542 self.subtree_va_ranges_disjoint(j);
543 }
544 } else {
545 if j as usize != cont_i.idx as int {
546 self.higher_level_children_disjoint(i, j);
547 } else {
548 assert(cont_i.children[cont_i.idx as int] is None);
549 assert(false);
550 }
551 }
552 }
553
554 #[verifier::rlimit(60)]
557 pub proof fn view_mappings_replace_lowest(
558 old_self: Self,
559 new_self: Self,
560 old_cont: CursorContinuation<'rcu, C>,
561 new_cont: CursorContinuation<'rcu, C>,
562 )
563 requires
564 old_self.inv(),
565 old_self.in_locked_range(),
566 new_self.inv(),
567 old_self.level == new_self.level,
568 old_self.continuations[old_self.level - 1] == old_cont,
569 new_self.continuations[new_self.level - 1] == new_cont,
570 forall|i: int|
571 old_self.level <= i < NR_LEVELS ==> old_self.continuations[i]
572 == new_self.continuations[i],
573 ensures
574 new_self.view_mappings() == (old_self.view_mappings() - old_cont.view_mappings()).union(
575 new_cont.view_mappings(),
576 ),
577 {
578 broadcast use {CursorContinuation::group_lemmas, CursorOwner::group_lemmas};
579
580 let level = old_self.level;
581
582 assert forall|m: Mapping| new_self.view_mappings().contains(m) implies ((
583 old_self.view_mappings().contains(m) && !old_cont.view_mappings().contains(m))
584 || new_cont.view_mappings().contains(m)) by {
585 let i = choose|i: int|
586 level - 1 <= i < NR_LEVELS
587 && #[trigger] new_self.continuations[i].view_mappings().contains(m);
588 if i == level - 1 {
589 assert(new_cont.view_mappings().contains(m));
590 } else {
591 assert(old_self.continuations[i] == new_self.continuations[i]);
592 assert(old_self.continuations[i].view_mappings().contains(m));
593
594 if old_cont.view_mappings().contains(m) {
595 old_self.inv_continuation(i);
596 old_self.inv_continuation(level - 1);
597 let cont_i = old_self.continuations[i];
598 let j = choose|j: int|
599 #![auto]
600 0 <= j < NR_ENTRIES && cont_i.children[j] is Some && PageTableOwner(
601 cont_i.children[j].unwrap(),
602 ).view_rec(cont_i.path().push_tail(j)).contains(m);
603 cont_i.inv_children_unroll(j);
604 PageTableOwner(cont_i.children[j].unwrap()).view_rec_vaddr_range(
605 cont_i.path().push_tail(j),
606 m,
607 );
608
609 let k = choose|k: int|
610 #![auto]
611 0 <= k < NR_ENTRIES && old_cont.children[k] is Some && PageTableOwner(
612 old_cont.children[k].unwrap(),
613 ).view_rec(old_cont.path().push_tail(k)).contains(m);
614 old_cont.inv_children_unroll(k);
615 PageTableOwner(old_cont.children[k].unwrap()).view_rec_vaddr_range(
616 old_cont.path().push_tail(k),
617 m,
618 );
619
620 if j as usize != cont_i.idx as int {
621 old_self.cur_va_in_cont_child_range(level as int);
622 old_self.va.to_path_vaddr_concrete(level as int);
623 old_self.cur_va_in_cont_child_range(i);
624 old_self.va.to_path_vaddr_concrete(i);
625
626 let x = old_self.cur_va() as nat;
627 let ps_node = page_size((level + 1) as PagingLevel) as nat;
628 let ps_anc = page_size((i + 1) as PagingLevel) as nat;
629
630 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_ge_page_size(
631 (level + 1) as PagingLevel);
632 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_ge_page_size(
633 (i + 1) as PagingLevel);
634 lemma_page_size_divides((level + 1) as PagingLevel, (i + 1) as PagingLevel);
635
636 lemma_nat_align_down_monotone(x, ps_node, ps_anc);
637 lemma_nat_align_down_within_block(x, ps_node, ps_anc);
638 vstd_extra::arithmetic::lemma_nat_align_down_sound(x, ps_node);
639 vstd_extra::arithmetic::lemma_nat_align_down_sound(x, ps_anc);
640
641 let sib_size = page_size(
642 (INC_LEVELS - cont_i.path().len() - 1) as PagingLevel,
643 );
644 sibling_paths_disjoint::<C>(cont_i.path(), cont_i.idx as int, j, sib_size);
645 lemma_vaddr_of_eq_int::<C>(cont_i.path().push_tail(cont_i.idx as int));
647 lemma_vaddr_of_eq_int::<C>(cont_i.path().push_tail(j));
648
649 old_cont.as_subtree_inv();
650 old_cont.as_page_table_owner_preserves_view_mappings();
651 PageTableOwner(old_cont.as_subtree()).view_rec_vaddr_range(
652 old_cont.path(),
653 m,
654 );
655 } else {
656 assert(cont_i.children[cont_i.idx as int] is None);
657 }
658 }
659 }
660 };
661
662 assert forall|m: Mapping|
663 ((old_self.view_mappings().contains(m) && !old_cont.view_mappings().contains(m))
664 || new_cont.view_mappings().contains(m)) implies new_self.view_mappings().contains(
665 m,
666 ) by {
667 if new_cont.view_mappings().contains(m) {
668 assert(new_self.continuations[level - 1].view_mappings().contains(m));
669 } else {
670 let i = choose|i: int|
671 level - 1 <= i < NR_LEVELS
672 && #[trigger] old_self.continuations[i].view_mappings().contains(m);
673 if i == level - 1 {
674 assert(false);
676 } else {
677 assert(new_self.continuations[i] == old_self.continuations[i]);
678 assert(new_self.continuations[i].view_mappings().contains(m));
679 }
680 }
681 };
682
683 assert(new_self.view_mappings() == (old_self.view_mappings()
684 - old_cont.view_mappings()).union(new_cont.view_mappings()));
685 }
686
687 #[verifier::rlimit(120)]
688 pub proof fn as_page_table_owner_preserves_view_mappings(self)
689 requires
690 self.inv(),
691 ensures
692 self.as_page_table_owner().view_rec(self.continuations[3].path())
693 == self.view_mappings(),
694 self.as_page_table_owner().0.inv(),
695 self.as_page_table_owner().0.level() == self.continuations[3].tree_level,
696 self.as_page_table_owner().pt_inv(),
697 {
698 broadcast use CursorOwner::group_lemmas;
699
700 if self.level == 4 {
701 self.continuations[3].as_page_table_owner_preserves_view_mappings();
702 self.inv_continuation(3);
703 assert(self.view_mappings() == self.continuations[3].view_mappings());
704 assert(self.as_page_table_owner().view_rec(self.continuations[3].path())
705 == self.view_mappings());
706 } else if self.level == 3 {
707 let c2 = self.continuations[2];
708 let c3 = self.continuations[3];
709
710 c2.as_page_table_owner_preserves_view_mappings();
711 c2.as_subtree_inv();
712 c3.view_mappings_put_child(c2.as_subtree());
713 c3.as_subtree_restore(c2);
714
715 let l4 = c3.restore(c2).0;
716 c2.as_page_table_owner_pt_inv();
717
718 c2.inv_children_unroll_all();
719 c3.inv_children_unroll_all();
720 l4.as_page_table_owner_preserves_view_mappings();
721
722 assert(self.view_mappings() == self.continuations[2].view_mappings().union(
723 self.continuations[3].view_mappings(),
724 )) by {
725 assert forall|m: Mapping| #[trigger]
726 self.view_mappings().contains(
727 m,
728 ) implies self.continuations[2].view_mappings().contains(m)
729 || self.continuations[3].view_mappings().contains(m) by {
730 let i = choose|i: int|
731 2 <= i < NR_LEVELS
732 && #[trigger] self.continuations[i].view_mappings().contains(m);
733 };
734 };
735 assert(self.as_page_table_owner().view_rec(self.continuations[3].path())
736 == self.view_mappings());
737 } else if self.level == 2 {
738 let c1 = self.continuations[1];
739 let c2 = self.continuations[2];
740 let c3 = self.continuations[3];
741
742 c1.as_page_table_owner_preserves_view_mappings();
743 c1.as_subtree_inv();
744 c2.view_mappings_put_child(c1.as_subtree());
745 c2.as_subtree_restore(c1);
746
747 let l3 = c2.restore(c1).0;
748 c1.as_page_table_owner_pt_inv();
749
750 c1.inv_children_unroll_all();
751 c2.inv_children_unroll_all();
752 l3.as_page_table_owner_preserves_view_mappings();
753 l3.as_subtree_inv();
754 c3.as_subtree_restore(l3);
755 c3.view_mappings_put_child(l3.as_subtree());
756
757 let l4 = c3.restore(l3).0;
758 l3.as_page_table_owner_pt_inv();
759
760 c3.inv_children_unroll_all();
761 l4.as_page_table_owner_preserves_view_mappings();
762
763 assert(self.view_mappings() == c1.view_mappings().union(c2.view_mappings()).union(
764 c3.view_mappings(),
765 )) by {
766 assert forall|m: Mapping| self.view_mappings().contains(m) implies (
767 c1.view_mappings().contains(m) || c2.view_mappings().contains(m)
768 || c3.view_mappings().contains(m)) by {
769 let i = choose|i: int|
770 1 <= i < NR_LEVELS
771 && #[trigger] self.continuations[i].view_mappings().contains(m);
772 };
773 };
774 assert(self.as_page_table_owner().view_rec(self.continuations[3].path())
775 == self.view_mappings());
776 } else {
777 let c0 = self.continuations[0];
779 let c1 = self.continuations[1];
780 let c2 = self.continuations[2];
781 let c3 = self.continuations[3];
782
783 c0.as_page_table_owner_preserves_view_mappings();
784 c0.as_subtree_inv();
785 c1.view_mappings_put_child(c0.as_subtree());
786 c1.as_subtree_restore(c0);
787 let l2 = c1.restore(c0).0;
788 c0.as_page_table_owner_pt_inv();
789
790 c0.inv_children_unroll_all();
791 c1.inv_children_unroll_all();
792 l2.as_page_table_owner_preserves_view_mappings();
793 l2.as_subtree_inv();
794 c2.view_mappings_put_child(l2.as_subtree());
795 c2.as_subtree_restore(l2);
796 let l3 = c2.restore(l2).0;
797 l2.as_page_table_owner_pt_inv();
798
799 c2.inv_children_unroll_all();
800 l3.as_page_table_owner_preserves_view_mappings();
801 l3.as_subtree_inv();
802 c3.view_mappings_put_child(l3.as_subtree());
803 c3.as_subtree_restore(l3);
804 let l4 = c3.restore(l3).0;
805 l3.as_page_table_owner_pt_inv();
806
807 c3.inv_children_unroll_all();
808 l4.as_page_table_owner_preserves_view_mappings();
809
810 assert(self.view_mappings() == c0.view_mappings().union(c1.view_mappings()).union(
811 c2.view_mappings(),
812 ).union(c3.view_mappings())) by {
813 assert forall|m: Mapping| self.view_mappings().contains(m) implies (
814 c0.view_mappings().contains(m) || c1.view_mappings().contains(m)
815 || c2.view_mappings().contains(m) || c3.view_mappings().contains(m)) by {
816 let i = choose|i: int|
817 0 <= i < NR_LEVELS
818 && #[trigger] self.continuations[i].view_mappings().contains(m);
819 };
820 };
821 assert(self.as_page_table_owner().view_rec(self.continuations[3].path())
822 == self.view_mappings());
823 }
824 }
825
826 pub proof fn view_mapping_inv(self)
832 requires
833 self.inv(),
834 ensures
835 forall|m: Mapping| self.view_mappings().contains(m) ==> #[trigger] m.inv(),
836 {
837 self.as_page_table_owner_preserves_view_mappings();
838 let pto = self.as_page_table_owner();
839 let root_path = self.continuations[3].path();
840 self.inv_continuation(NR_LEVELS as int - 1);
841 pto.view_rec_mapping_inv(root_path);
842 }
843
844 pub proof fn view_mapping_page_size_valid(self)
851 requires
852 self.inv(),
853 ensures
854 forall|m: Mapping| #[trigger]
855 self.view_mappings().contains(m)
856 ==> set![4096usize, 2097152usize, 1073741824usize].contains(m.page_size),
857 {
858 self.as_page_table_owner_preserves_view_mappings();
859 let pto = self.as_page_table_owner();
860 let root_path = self.continuations[3].path();
861 self.inv_continuation(NR_LEVELS - 1);
862 pto.view_rec_mapping_page_size(root_path);
866 }
867
868 pub proof fn as_page_table_owner_view_non_overlapping(self)
875 requires
876 self.inv(),
877 ensures
878 self@.non_overlapping(),
879 {
880 self.as_page_table_owner_preserves_view_mappings();
881 let pto = self.as_page_table_owner();
882 let root_path = self.continuations[3].path();
883
884 assert(root_path.len() == self.continuations[3].tree_level);
885 assert(self.continuations[3].tree_level == 0) by {
886 self.inv_continuation(NR_LEVELS - 1);
887 };
890
891 assert forall|m: Mapping, n: Mapping| #[trigger]
892 self@.mappings.contains(m) && #[trigger] self@.mappings.contains(n) && m
893 != n implies m.va_range.end <= n.va_range.start || n.va_range.end
894 <= m.va_range.start by {
895 assert(self@.mappings == self.view_mappings());
896 assert(pto.view_rec(root_path).contains(m));
897 assert(pto.view_rec(root_path).contains(n));
898 pto.view_rec_disjoint_vaddrs(root_path, m, n);
899 };
900 }
901}
902
903}