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