1use 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 INC_LEVELS, OwnerSubtree, PageTableOwner, lemma_vaddr_of_eq_int, page_size_monotonic,
17 sibling_paths_disjoint, vaddr, vaddr_of,
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> {
27 pub proof fn as_page_table_owner_preserves_view_mappings(self)
28 requires
29 self.inv(),
30 self.all_some(),
31 ensures
32 self.as_page_table_owner().view_rec(self.path()) == self.view_mappings(),
33 self.as_subtree().inv(),
34 PageTableOwner(self.as_subtree()).pt_inv(),
35 {
36 self.inv_children_unroll_all();
37 self.as_subtree_inv();
38 self.as_page_table_owner_pt_inv();
39 }
40
41 pub proof fn view_mappings_take_child(self)
42 requires
43 self.inv(),
44 self.all_some(),
45 ensures
46 self.take_child().1.view_mappings() == self.view_mappings()
47 - self.view_mappings_take_child_spec(),
48 {
49 self.inv_children_unroll_all();
50 let def = self.take_child().1.view_mappings();
51 let diff = self.view_mappings() - self.view_mappings_take_child_spec();
52 assert forall|m: Mapping| diff.contains(m) implies def.contains(m) by {
53 let i = choose|i: int|
54 0 <= i < self.children.len() && #[trigger] self.children[i] is Some
55 && PageTableOwner(self.children[i].unwrap()).view_rec(
56 self.path().push_tail(i as usize),
57 ).contains(m);
58 assert(i != self.idx);
59 assert(self.take_child().1.children[i] is Some);
60 };
61 assert forall|m: Mapping| #![trigger def.contains(m)] def.contains(m) implies diff.contains(
62 m,
63 ) by {
64 let left = self.take_child().1;
65 assert(left.view_mappings().contains(m));
66 if self.view_mappings_take_child_spec().contains(m) {
67 assert(PageTableOwner(self.children[self.idx as int].unwrap()).view_rec(
68 self.path().push_tail(self.idx as usize),
69 ).contains(m));
70 let i = choose|i: int|
71 0 <= i < left.children.len() && #[trigger] left.children[i] is Some
72 && PageTableOwner(left.children[i].unwrap()).view_rec(
73 left.path().push_tail(i as usize),
74 ).contains(m);
75 assert(i != self.idx);
76 assert(PageTableOwner(left.children[i as int].unwrap()).view_rec(
77 left.path().push_tail(i as usize),
78 ).contains(m));
79
80 PageTableOwner(self.children[self.idx as int].unwrap()).view_rec_vaddr_range(
81 self.path().push_tail(self.idx as usize),
82 m,
83 );
84 PageTableOwner(left.children[i as int].unwrap()).view_rec_vaddr_range(
85 left.path().push_tail(i as usize),
86 m,
87 );
88
89 let size = page_size((INC_LEVELS - self.path().len() - 1) as PagingLevel);
90 sibling_paths_disjoint::<C>(self.path(), self.idx, i as usize, size);
92 lemma_vaddr_of_eq_int::<C>(self.path().push_tail(self.idx as usize));
93 lemma_vaddr_of_eq_int::<C>(self.path().push_tail(i as usize));
94 }
95 };
96 }
97
98 pub proof fn view_mappings_put_child(self, child: OwnerSubtree<C>)
99 requires
100 self.inv(),
101 child.inv(),
102 self.all_but_index_some(),
103 ensures
104 self.put_child(child).view_mappings() == self.view_mappings() + PageTableOwner(
105 child,
106 ).view_rec(self.path().push_tail(self.idx as usize)),
107 {
108 let def = self.put_child(child).view_mappings();
109 let sum = self.view_mappings() + PageTableOwner(child).view_rec(
110 self.path().push_tail(self.idx as usize),
111 );
112 assert forall|m: Mapping| sum.contains(m) implies def.contains(m) by {
113 if self.view_mappings().contains(m) {
114 let i = choose|i: int|
115 0 <= i < self.children.len() && #[trigger] self.children[i] is Some
116 && PageTableOwner(self.children[i].unwrap()).view_rec(
117 self.path().push_tail(i as usize),
118 ).contains(m);
119 assert(i != self.idx);
120 assert(self.put_child(child).children[i] == self.children[i]);
121 } else {
122 assert(PageTableOwner(child).view_rec(
123 self.path().push_tail(self.idx as usize),
124 ).contains(m));
125 assert(self.put_child(child).children[self.idx as int] == Some(child));
126 }
127 };
128 }
129}
130
131impl<'rcu, C: PageTableConfig> CursorContinuation<'rcu, C> {
132 proof fn as_subtree_inv(self)
134 requires
135 self.inv(),
136 self.all_some(),
137 ensures
138 self.as_subtree().inv(),
139 {
140 self.inv_children_unroll_all();
141 }
142
143 proof fn as_page_table_owner_pt_inv(self)
144 requires
145 self.inv(),
146 self.all_some(),
147 ensures
148 PageTableOwner(self.as_subtree()).pt_inv(),
149 {
150 self.as_subtree_inv();
151 let st = self.as_subtree();
152 let depth = (INC_LEVELS - st.level) as nat;
153 assert forall|i: int|
154 #![trigger st.children[i]]
155 0 <= i < NR_ENTRIES implies PageTableOwner::<C>::pt_edge_at(st, i) && PageTableOwner(
156 st.children[i].unwrap(),
157 ).pt_inv_at_depth((depth - 1) as nat) by {
158 self.inv_children_rel_unroll(i);
159 self.pt_inv_children_unroll(i);
160 };
161 }
162}
163
164impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
166 pub proof fn cur_subtree_eq_filtered_mappings_path(self)
169 requires
170 self.inv(),
171 self.in_locked_range(),
172 ensures
173 ({
174 let subtree_va = vaddr_of::<C>(self.cur_subtree().value.path) as int;
175 let size = page_size(self.level) as int;
176 PageTableOwner(self.cur_subtree())@.mappings == self@.mappings.filter(
177 |m: Mapping| subtree_va <= m.va_range.start < subtree_va + size,
178 )
179 }),
180 {
181 let cur_subtree = self.cur_subtree();
182 let cur_path = cur_subtree.value.path;
183 let subtree_va = vaddr_of::<C>(cur_path) as int;
184 let size = page_size(self.level) as int;
185
186 let subtree_mappings = PageTableOwner(cur_subtree)@.mappings;
187 let filtered = self@.mappings.filter(
188 |m: Mapping| subtree_va <= m.va_range.start < subtree_va + size,
189 );
190
191 self.cur_subtree_inv();
192
193 let cont = self.continuations[self.level - 1];
194 self.inv_continuation(self.level - 1);
195 cont.inv_children_rel_unroll(self.index() as int);
196 assert forall|m: Mapping| subtree_mappings.contains(m) implies filtered.contains(m) by {
200 assert(cont.children[self.index() as int] is Some);
202 assert(cont.children[self.index() as int].unwrap() == cur_subtree);
203 assert(cont.view_mappings().contains(m));
204 assert(self.view_mappings().contains(m));
205
206 PageTableOwner(cur_subtree).view_rec_vaddr_range(cur_path, m);
210 };
211
212 assert forall|m: Mapping| filtered.contains(m) implies subtree_mappings.contains(m) by {
214 let i = choose|i: int|
216 self.level - 1 <= i < NR_LEVELS
217 && #[trigger] self.continuations[i].view_mappings().contains(m);
218 self.inv_continuation(i);
219
220 let cont_i = self.continuations[i];
221 let j = choose|j: int|
222 #![auto]
223 0 <= j < NR_ENTRIES && cont_i.children[j] is Some && PageTableOwner(
224 cont_i.children[j].unwrap(),
225 ).view_rec(cont_i.path().push_tail(j as usize)).contains(m);
226
227 cont_i.inv_children_unroll(j);
228 PageTableOwner(cont_i.children[j].unwrap()).view_rec_vaddr_range(
229 cont_i.path().push_tail(j as usize),
230 m,
231 );
232
233 if i == self.level - 1 {
234 if j as usize == self.index() {
235 assert(cont_i.children[j] == Some(cur_subtree));
238 assert(cont_i.path().push_tail(j as usize) == cur_path);
239 assert(subtree_mappings == PageTableOwner(cur_subtree).view_rec(cur_path));
240 assert(PageTableOwner(cur_subtree).view_rec(cur_path).contains(m));
241 assert(subtree_mappings.contains(m));
242 } else {
243 assert(cont.level() == self.level) by {
245 if self.level == 1 {
246 } else if self.level == 2 {
247 } else if self.level == 3 {
248 } else {
249 }
250 };
251 let sib_size = page_size((INC_LEVELS - cont.path().len() - 1) as PagingLevel);
252 sibling_paths_disjoint::<C>(cont.path(), self.index(), j as usize, sib_size);
253 lemma_vaddr_of_eq_int::<C>(cont.path().push_tail(self.index() as usize));
256 lemma_vaddr_of_eq_int::<C>(cont.path().push_tail(j as usize));
257 assert(false); }
259 } else {
260 if j as usize != cont_i.idx as usize {
261 self.subtree_va_in_ancestor_range(i);
263
264 assert(cont_i.level() == (i + 1) as PagingLevel) by {
266 if i == 0 {
267 } else if i == 1 {
268 } else if i == 2 {
269 } else {
270 }
271 };
272 let sib_size = page_size((INC_LEVELS - cont_i.path().len() - 1) as PagingLevel);
273 sibling_paths_disjoint::<C>(cont_i.path(), cont_i.idx, j as usize, sib_size);
274 lemma_vaddr_of_eq_int::<C>(cont_i.path().push_tail(cont_i.idx as usize));
275 lemma_vaddr_of_eq_int::<C>(cont_i.path().push_tail(j as usize));
276 lemma_vaddr_of_eq_int::<C>(cur_path);
277 assert(false); } else {
279 assert(cont_i.children[cont_i.idx as int] is None);
280 assert(false); }
282 }
283 };
284
285 assert(subtree_mappings =~= filtered);
286 }
287
288 pub proof fn cur_subtree_eq_filtered_mappings(self)
291 requires
292 self.inv(),
293 self.in_locked_range(),
294 ensures
295 ({
296 let start = nat_align_down(
297 self@.cur_va as nat,
298 page_size(self.level) as nat,
299 ) as Vaddr;
300 let size = page_size(self.level);
301 PageTableOwner(self.cur_subtree())@.mappings == self@.mappings.filter(
302 |m: Mapping| start <= m.va_range.start < start + size,
303 )
304 }),
305 {
306 self.cur_subtree_eq_filtered_mappings_path();
311 self.cur_va_in_cont_child_range(self.level - 1);
312 self.va.to_path_vaddr_concrete(self.level as int - 1);
313 let cur_path = self.cur_subtree().value.path;
314 let ps = page_size(self.level);
315 lemma_vaddr_of_eq_int::<C>(cur_path);
316 vstd_extra::arithmetic::lemma_nat_align_down_sound(self@.cur_va as nat, ps as nat);
319 let nad = nat_align_down(self@.cur_va as nat, ps as nat);
320 assert(nad <= self@.cur_va as nat);
321 assert(nad <= usize::MAX);
322 assert((nad as Vaddr) as int == nad as int);
323 assert((nad as Vaddr) as int == vaddr_of::<C>(cur_path) as int);
324 }
325
326 proof fn cur_va_in_cont_child_range(self, lvl: int)
330 requires
331 self.inv(),
332 self.in_locked_range(),
333 self.level - 1 <= lvl < NR_LEVELS,
334 ensures
335 vaddr(
336 self.continuations[lvl].path().push_tail(self.continuations[lvl].idx as usize),
337 ) as int + self.va.leading_bits * 0x1_0000_0000_0000int <= self.cur_va() as int,
338 (self.cur_va() as int) < vaddr(
339 self.continuations[lvl].path().push_tail(self.continuations[lvl].idx as usize),
340 ) as int + self.va.leading_bits * 0x1_0000_0000_0000int + page_size(
341 (lvl + 1) as PagingLevel,
342 ) as int,
343 vaddr(self.continuations[lvl].path().push_tail(self.continuations[lvl].idx as usize))
344 == vaddr(self.va.to_path(lvl)),
345 {
346 let cont = self.continuations[lvl];
347 let child_path = cont.path().push_tail(cont.idx as usize);
348 let va_path = self.va.to_path(lvl);
349
350 self.va.to_path_len(lvl);
351 cont.path().push_tail_property_len(cont.idx as usize);
352 assert(cont.level() == (lvl + 1) as PagingLevel) by {
353 if lvl == 0 {
354 } else if lvl == 1 {
355 } else if lvl == 2 {
356 } else {
357 }
358 };
359
360 assert forall|k: int| 0 <= k < child_path.len() implies child_path.index(k)
361 == va_path.index(k) by {
362 self.va.to_path_index(lvl, k);
363 if lvl == 3 {
364 cont.path().push_tail_property_index(cont.idx as usize);
365 } else if lvl == 2 {
366 cont.path().push_tail_property_index(cont.idx as usize);
367 self.continuations[3].path().push_tail_property_index(
368 self.continuations[3].idx as usize,
369 );
370 } else if lvl == 1 {
371 cont.path().push_tail_property_index(cont.idx as usize);
372 self.continuations[2].path().push_tail_property_index(
373 self.continuations[2].idx as usize,
374 );
375 self.continuations[3].path().push_tail_property_index(
376 self.continuations[3].idx as usize,
377 );
378 } else {
379 cont.path().push_tail_property_index(cont.idx as usize);
380 self.continuations[1].path().push_tail_property_index(
381 self.continuations[1].idx as usize,
382 );
383 self.continuations[2].path().push_tail_property_index(
384 self.continuations[2].idx as usize,
385 );
386 self.continuations[3].path().push_tail_property_index(
387 self.continuations[3].idx as usize,
388 );
389 }
390 };
391
392 self.va.to_path_inv(lvl);
393 cont.path().push_tail_preserves_inv(cont.idx as usize);
394 AbstractVaddr::rec_vaddr_eq_if_indices_eq(child_path, va_path, 0);
395 self.va.vaddr_range_from_path(lvl);
396 }
397
398 proof fn subtree_va_in_ancestor_range(self, lvl: int)
401 requires
402 self.inv(),
403 self.in_locked_range(),
404 self.level - 1 < lvl < NR_LEVELS,
405 ensures
406 ({
407 let subtree_va = vaddr(self.cur_subtree().value.path);
408 let idx_path_va = vaddr(
409 self.continuations[lvl].path().push_tail(self.continuations[lvl].idx as usize),
410 );
411 &&& idx_path_va <= subtree_va
412 &&& subtree_va + page_size(self.level) <= idx_path_va + page_size(
413 (lvl + 1) as PagingLevel,
414 )
415 }),
416 {
417 let cont = self.continuations[self.level - 1];
418 self.inv_continuation(self.level - 1);
419 cont.inv_children_rel_unroll(self.index() as int);
420 self.cur_va_in_cont_child_range(self.level - 1);
423 self.cur_va_in_cont_child_range(lvl);
424 self.va.to_path_vaddr_concrete(self.level as int - 1);
425 self.va.to_path_vaddr_concrete(lvl);
426
427 let x = self.cur_va() as nat;
428 let fine = page_size(self.level as PagingLevel) as nat;
429 let coarse = page_size((lvl + 1) as PagingLevel) as nat;
430 let shift = self.va.leading_bits * 0x1_0000_0000_0000int;
431
432 let subtree_va = vaddr(self.cur_subtree().value.path);
434 assert(subtree_va == vaddr(self.va.to_path(self.level as int - 1)));
435 assert(subtree_va as int + shift == nat_align_down(x, fine) as int);
436
437 let idx_path_va = vaddr(
439 self.continuations[lvl].path().push_tail(self.continuations[lvl].idx as usize),
440 );
441 assert(idx_path_va == vaddr(self.va.to_path(lvl)));
442 assert(idx_path_va as int + shift == nat_align_down(x, coarse) as int);
443
444 lemma_page_size_divides(self.level as PagingLevel, (lvl + 1) as PagingLevel);
445 lemma_nat_align_down_monotone(x, fine, coarse);
446 lemma_nat_align_down_within_block(x, fine, coarse);
447
448 vstd_extra::arithmetic::lemma_nat_align_down_sound(x, fine);
450 vstd_extra::arithmetic::lemma_nat_align_down_sound(x, coarse);
451 }
452
453 pub proof fn subtree_va_ranges_disjoint(self, j: int)
455 requires
456 self.inv(),
457 self.in_locked_range(),
458 0 <= j < NR_ENTRIES,
459 j != self.index(),
460 self.continuations[self.level - 1].children[j] is Some,
461 ensures
462 vaddr(self.continuations[self.level - 1].path().push_tail(j as usize)) as int
463 + self.va.leading_bits * 0x1_0000_0000_0000int + page_size(
464 self.level as PagingLevel,
465 ) as int <= self.cur_va() as int || (self.cur_va() as int) < vaddr(
466 self.continuations[self.level - 1].path().push_tail(j as usize),
467 ) as int + self.va.leading_bits * 0x1_0000_0000_0000int,
468 {
469 let cont = self.continuations[self.level - 1];
470 let idx = self.index();
471
472 assert(cont.level() == self.level) by {
474 if self.level == 1 {
475 } else if self.level == 2 {
476 } else if self.level == 3 {
477 } else {
478 }
479 };
480
481 self.cur_va_in_cont_child_range(self.level - 1);
483
484 let size = page_size((INC_LEVELS - cont.path().len() - 1) as PagingLevel);
486 sibling_paths_disjoint::<C>(cont.path(), idx, j as usize, size);
487 }
488
489 pub proof fn higher_level_children_disjoint(self, i: int, j: int)
492 requires
493 self.inv(),
494 self.in_locked_range(),
495 self.level - 1 < i < NR_LEVELS,
496 0 <= j < NR_ENTRIES,
497 j != self.continuations[i].idx,
498 self.continuations[i].children[j] is Some,
499 ensures
500 vaddr(self.continuations[i].path().push_tail(j as usize)) as int + self.va.leading_bits
501 * 0x1_0000_0000_0000int + page_size((i + 1) as PagingLevel) as int
502 <= self.cur_va() as int || (self.cur_va() as int) < vaddr(
503 self.continuations[i].path().push_tail(j as usize),
504 ) as int + self.va.leading_bits * 0x1_0000_0000_0000int,
505 {
506 let cont = self.continuations[i];
507
508 assert(cont.level() == (i + 1) as PagingLevel) by {
510 if i == 0 {
511 } else if i == 1 {
512 } else if i == 2 {
513 } else {
514 }
515 };
516
517 self.cur_va_in_cont_child_range(i);
519
520 let size = page_size((INC_LEVELS - cont.path().len() - 1) as PagingLevel);
522 sibling_paths_disjoint::<C>(cont.path(), cont.idx, j as usize, size);
523 }
524
525 pub proof fn mapping_covering_cur_va_from_cur_subtree(self, m: Mapping)
529 requires
530 self.inv(),
531 self.in_locked_range(),
532 self.view_mappings().contains(m),
533 m.va_range.start <= self.cur_va() < m.va_range.end,
534 ensures
535 PageTableOwner(self.cur_subtree()).view_rec(self.cur_subtree().value.path).contains(m),
536 {
537 let cur_va = self.cur_va();
538
539 let i = choose|i: int|
541 self.level - 1 <= i < NR_LEVELS
542 && #[trigger] self.continuations[i].view_mappings().contains(m);
543 self.inv_continuation(i);
544
545 let cont_i = self.continuations[i];
546 let j = choose|j: int|
547 #![auto]
548 0 <= j < NR_ENTRIES && cont_i.children[j] is Some && PageTableOwner(
549 cont_i.children[j].unwrap(),
550 ).view_rec(cont_i.path().push_tail(j as usize)).contains(m);
551
552 cont_i.inv_children_unroll(j);
553 let child_j = cont_i.children[j].unwrap();
554 let path_j = cont_i.path().push_tail(j as usize);
555 PageTableOwner(child_j).view_rec_vaddr_range(path_j, m);
556 lemma_vaddr_of_eq_int::<C>(path_j);
559
560 if i == self.level - 1 {
561 if j as usize != self.index() {
562 self.subtree_va_ranges_disjoint(j);
563 }
564 } else {
565 if j as usize != cont_i.idx as usize {
566 self.higher_level_children_disjoint(i, j);
567 } else {
568 assert(cont_i.children[cont_i.idx as int] is None);
569 assert(false);
570 }
571 }
572 }
573
574 #[verifier::rlimit(60)]
577 pub proof fn view_mappings_replace_lowest(
578 old_self: Self,
579 new_self: Self,
580 old_cont: CursorContinuation<'rcu, C>,
581 new_cont: CursorContinuation<'rcu, C>,
582 )
583 requires
584 old_self.inv(),
585 old_self.in_locked_range(),
586 new_self.inv(),
587 old_self.level == new_self.level,
588 old_self.continuations[old_self.level - 1] == old_cont,
589 new_self.continuations[new_self.level - 1] == new_cont,
590 forall|i: int|
591 old_self.level <= i < NR_LEVELS ==> old_self.continuations[i]
592 == new_self.continuations[i],
593 ensures
594 new_self.view_mappings() == (old_self.view_mappings() - old_cont.view_mappings()).union(
595 new_cont.view_mappings(),
596 ),
597 {
598 let level = old_self.level;
599
600 assert forall|m: Mapping| new_self.view_mappings().contains(m) implies ((
601 old_self.view_mappings().contains(m) && !old_cont.view_mappings().contains(m))
602 || new_cont.view_mappings().contains(m)) by {
603 let i = choose|i: int|
604 level - 1 <= i < NR_LEVELS
605 && #[trigger] new_self.continuations[i].view_mappings().contains(m);
606 if i == level - 1 {
607 assert(new_cont.view_mappings().contains(m));
608 } else {
609 assert(old_self.continuations[i] == new_self.continuations[i]);
610 assert(old_self.continuations[i].view_mappings().contains(m));
611 assert(old_self.view_mappings().contains(m));
612
613 if old_cont.view_mappings().contains(m) {
614 old_self.inv_continuation(i);
615 old_self.inv_continuation(level - 1);
616 let cont_i = old_self.continuations[i];
617 let j = choose|j: int|
618 #![auto]
619 0 <= j < NR_ENTRIES && cont_i.children[j] is Some && PageTableOwner(
620 cont_i.children[j].unwrap(),
621 ).view_rec(cont_i.path().push_tail(j as usize)).contains(m);
622 cont_i.inv_children_unroll(j);
623 PageTableOwner(cont_i.children[j].unwrap()).view_rec_vaddr_range(
624 cont_i.path().push_tail(j as usize),
625 m,
626 );
627
628 let k = choose|k: int|
629 #![auto]
630 0 <= k < NR_ENTRIES && old_cont.children[k] is Some && PageTableOwner(
631 old_cont.children[k].unwrap(),
632 ).view_rec(old_cont.path().push_tail(k as usize)).contains(m);
633 old_cont.inv_children_unroll(k);
634 PageTableOwner(old_cont.children[k].unwrap()).view_rec_vaddr_range(
635 old_cont.path().push_tail(k as usize),
636 m,
637 );
638
639 if j as usize != cont_i.idx as usize {
640 assert(cont_i.level() == (i + 1) as PagingLevel) by {
641 if i == 0 {
642 } else if i == 1 {
643 } else if i == 2 {
644 } else {
645 }
646 };
647
648 old_self.cur_va_in_cont_child_range(level as int);
649 old_self.va.to_path_vaddr_concrete(level as int);
650 old_self.cur_va_in_cont_child_range(i);
651 old_self.va.to_path_vaddr_concrete(i);
652
653 let x = old_self.cur_va() as nat;
654 let ps_node = page_size((level + 1) as PagingLevel) as nat;
655 let ps_anc = page_size((i + 1) as PagingLevel) as nat;
656
657 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_ge_page_size(
658 (level + 1) as PagingLevel);
659 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_ge_page_size(
660 (i + 1) as PagingLevel);
661 lemma_page_size_divides((level + 1) as PagingLevel, (i + 1) as PagingLevel);
662
663 lemma_nat_align_down_monotone(x, ps_node, ps_anc);
664 lemma_nat_align_down_within_block(x, ps_node, ps_anc);
665 vstd_extra::arithmetic::lemma_nat_align_down_sound(x, ps_node);
666 vstd_extra::arithmetic::lemma_nat_align_down_sound(x, ps_anc);
667
668 let sib_size = page_size(
669 (INC_LEVELS - cont_i.path().len() - 1) as PagingLevel,
670 );
671 sibling_paths_disjoint::<C>(
672 cont_i.path(),
673 cont_i.idx,
674 j as usize,
675 sib_size,
676 );
677 lemma_vaddr_of_eq_int::<C>(cont_i.path().push_tail(cont_i.idx as usize));
679 lemma_vaddr_of_eq_int::<C>(cont_i.path().push_tail(j as usize));
680
681 old_cont.as_subtree_inv();
682 PageTableOwner(old_cont.as_subtree()).view_rec_vaddr_range(
683 old_cont.path(),
684 m,
685 );
686 } else {
687 assert(cont_i.children[cont_i.idx as int] is None);
688 }
689 }
690 }
691 };
692
693 assert forall|m: Mapping|
694 ((old_self.view_mappings().contains(m) && !old_cont.view_mappings().contains(m))
695 || new_cont.view_mappings().contains(m)) implies new_self.view_mappings().contains(
696 m,
697 ) by {
698 if new_cont.view_mappings().contains(m) {
699 assert(new_self.continuations[level - 1].view_mappings().contains(m));
700 } else {
701 let i = choose|i: int|
703 level - 1 <= i < NR_LEVELS
704 && #[trigger] old_self.continuations[i].view_mappings().contains(m);
705 if i == level - 1 {
706 assert(false);
708 } else {
709 assert(new_self.continuations[i] == old_self.continuations[i]);
710 assert(new_self.continuations[i].view_mappings().contains(m));
711 }
712 }
713 };
714
715 assert(new_self.view_mappings() =~= (old_self.view_mappings()
716 - old_cont.view_mappings()).union(new_cont.view_mappings()));
717 }
718
719 pub proof fn as_page_table_owner_preserves_view_mappings(self)
720 requires
721 self.inv(),
722 ensures
723 self.as_page_table_owner().view_rec(self.continuations[3].path())
724 == self.view_mappings(),
725 self.as_page_table_owner().0.inv(),
726 self.as_page_table_owner().0.level == self.continuations[3].tree_level,
727 self.as_page_table_owner().pt_inv(),
728 {
729 if self.level == 4 {
730 self.continuations[3].as_page_table_owner_preserves_view_mappings();
731 assert(self.view_mappings() =~= self.continuations[3].view_mappings());
732 } else if self.level == 3 {
733 let c2 = self.continuations[2];
734 let c3 = self.continuations[3];
735
736 c2.as_page_table_owner_preserves_view_mappings();
737 c2.as_subtree_inv();
738 c3.view_mappings_put_child(c2.as_subtree());
739 c3.as_subtree_restore(c2);
740
741 let l4 = c3.restore(c2).0;
742 assert(l4.all_some()) by {
743 assert forall|i: int| 0 <= i < NR_ENTRIES implies l4.children[i] is Some by {
744 if i == c3.idx as int {
745 } else {
746 assert(l4.children[i] == c3.children[i]);
747 }
748 };
749 };
750
751 c2.as_page_table_owner_pt_inv();
752 assert(l4.pt_inv_children()) by {
753 assert forall|i: int|
754 #![trigger l4.children[i]]
755 !(0 <= i < l4.children.len()) || (l4.children[i] is Some ==> PageTableOwner(
756 l4.children[i].unwrap(),
757 ).pt_inv()) by {
758 if 0 <= i < l4.children.len() {
759 if i == c3.idx as int {
760 assert(l4.children[i] == Some(c2.as_subtree()));
761 } else {
762 assert(l4.children[i] == c3.children[i]);
763 c3.pt_inv_children_unroll(i);
764 }
765 } else {
766 assert(!(0 <= i < l4.children.len()));
767 }
768 };
769 };
770
771 c2.inv_children_unroll_all();
772 c3.inv_children_unroll_all();
773 l4.as_page_table_owner_preserves_view_mappings();
774
775 assert(self.view_mappings() =~= self.continuations[2].view_mappings().union(
776 self.continuations[3].view_mappings(),
777 )) by {
778 assert forall|m: Mapping| #[trigger]
779 self.view_mappings().contains(
780 m,
781 ) implies self.continuations[2].view_mappings().contains(m)
782 || self.continuations[3].view_mappings().contains(m) by {
783 let i = choose|i: int|
784 2 <= i < NR_LEVELS
785 && #[trigger] self.continuations[i].view_mappings().contains(m);
786 };
787 };
788 } else if self.level == 2 {
789 let c1 = self.continuations[1];
790 let c2 = self.continuations[2];
791 let c3 = self.continuations[3];
792
793 c1.as_page_table_owner_preserves_view_mappings();
794 c1.as_subtree_inv();
795 c2.view_mappings_put_child(c1.as_subtree());
796 c2.as_subtree_restore(c1);
797
798 let l3 = c2.restore(c1).0;
799 assert(l3.all_some()) by {
800 assert forall|i: int| 0 <= i < NR_ENTRIES implies l3.children[i] is Some by {
801 if i == c2.idx as int {
802 } else {
803 assert(l3.children[i] == c2.children[i]);
804 }
805 };
806 };
807 c1.as_page_table_owner_pt_inv();
808 assert(l3.pt_inv_children()) by {
809 assert forall|i: int|
810 #![trigger l3.children[i]]
811 !(0 <= i < l3.children.len()) || (l3.children[i] is Some ==> PageTableOwner(
812 l3.children[i].unwrap(),
813 ).pt_inv()) by {
814 if 0 <= i < l3.children.len() {
815 if i == c2.idx as int {
816 assert(l3.children[i] == Some(c1.as_subtree()));
817 } else {
818 assert(l3.children[i] == c2.children[i]);
819 c2.pt_inv_children_unroll(i);
820 }
821 } else {
822 assert(!(0 <= i < l3.children.len()));
823 }
824 };
825 };
826
827 c1.inv_children_unroll_all();
828 c2.inv_children_unroll_all();
829 l3.as_page_table_owner_preserves_view_mappings();
830 l3.as_subtree_inv();
831 c3.as_subtree_restore(l3);
832 c3.view_mappings_put_child(l3.as_subtree());
833
834 let l4 = c3.restore(l3).0;
835 assert(l4.all_some()) by {
836 assert forall|i: int| 0 <= i < NR_ENTRIES implies l4.children[i] is Some by {
837 if i == c3.idx as int {
838 assert(l4.children[i] == Some(l3.as_subtree()));
839 } else {
840 assert(l4.children[i] == c3.children[i]);
841 }
842 };
843 };
844 l3.as_page_table_owner_pt_inv();
845 assert(l4.pt_inv_children()) by {
846 assert forall|i: int|
847 #![trigger l4.children[i]]
848 !(0 <= i < l4.children.len()) || (l4.children[i] is Some ==> PageTableOwner(
849 l4.children[i].unwrap(),
850 ).pt_inv()) by {
851 if 0 <= i < l4.children.len() {
852 if i == c3.idx as int {
853 assert(l4.children[i] == Some(l3.as_subtree()));
854 } else {
855 assert(l4.children[i] == c3.children[i]);
856 c3.pt_inv_children_unroll(i);
857 }
858 } else {
859 assert(!(0 <= i < l4.children.len()));
860 }
861 };
862 };
863
864 c3.inv_children_unroll_all();
865 l4.as_page_table_owner_preserves_view_mappings();
866
867 assert(self.view_mappings() =~= c1.view_mappings().union(c2.view_mappings()).union(
868 c3.view_mappings(),
869 )) by {
870 assert forall|m: Mapping| self.view_mappings().contains(m) implies (
871 c1.view_mappings().contains(m) || c2.view_mappings().contains(m)
872 || c3.view_mappings().contains(m)) by {
873 let i = choose|i: int|
874 1 <= i < NR_LEVELS
875 && #[trigger] self.continuations[i].view_mappings().contains(m);
876 };
877 };
878 } else {
879 let c0 = self.continuations[0];
881 let c1 = self.continuations[1];
882 let c2 = self.continuations[2];
883 let c3 = self.continuations[3];
884
885 c0.as_page_table_owner_preserves_view_mappings();
886 c0.as_subtree_inv();
887 c1.view_mappings_put_child(c0.as_subtree());
888 c1.as_subtree_restore(c0);
889 let l2 = c1.restore(c0).0;
890 assert(l2.all_some()) by {
891 assert forall|i: int| 0 <= i < NR_ENTRIES implies l2.children[i] is Some by {
892 if i == c1.idx as int {
893 } else {
894 assert(l2.children[i] == c1.children[i]);
895 }
896 };
897 };
898 c0.as_page_table_owner_pt_inv();
899 assert(l2.pt_inv_children()) by {
900 assert forall|i: int|
901 #![trigger l2.children[i]]
902 !(0 <= i < l2.children.len()) || (l2.children[i] is Some ==> PageTableOwner(
903 l2.children[i].unwrap(),
904 ).pt_inv()) by {
905 if 0 <= i < l2.children.len() {
906 if i == c1.idx as int {
907 assert(l2.children[i] == Some(c0.as_subtree()));
908 } else {
909 assert(l2.children[i] == c1.children[i]);
910 c1.pt_inv_children_unroll(i);
911 }
912 } else {
913 assert(!(0 <= i < l2.children.len()));
914 }
915 };
916 };
917
918 c0.inv_children_unroll_all();
919 c1.inv_children_unroll_all();
920 l2.as_page_table_owner_preserves_view_mappings();
921 l2.as_subtree_inv();
922 c2.view_mappings_put_child(l2.as_subtree());
923 c2.as_subtree_restore(l2);
924 let l3 = c2.restore(l2).0;
925 assert(l3.all_some()) by {
926 assert forall|i: int| 0 <= i < NR_ENTRIES implies l3.children[i] is Some by {
927 if i == c2.idx as int {
928 } else {
929 assert(l3.children[i] == c2.children[i]);
930 }
931 };
932 };
933 l2.as_page_table_owner_pt_inv();
934 assert(l3.pt_inv_children()) by {
935 assert forall|i: int|
936 #![trigger l3.children[i]]
937 !(0 <= i < l3.children.len()) || (l3.children[i] is Some ==> PageTableOwner(
938 l3.children[i].unwrap(),
939 ).pt_inv()) by {
940 if 0 <= i < l3.children.len() {
941 if i == c2.idx as int {
942 assert(l3.children[i] == Some(l2.as_subtree()));
943 } else {
944 assert(l3.children[i] == c2.children[i]);
945 c2.pt_inv_children_unroll(i);
946 }
947 } else {
948 assert(!(0 <= i < l3.children.len()));
949 }
950 };
951 };
952
953 c2.inv_children_unroll_all();
954 l3.as_page_table_owner_preserves_view_mappings();
955 l3.as_subtree_inv();
956 c3.view_mappings_put_child(l3.as_subtree());
957 c3.as_subtree_restore(l3);
958 let l4 = c3.restore(l3).0;
959 assert(l4.all_some()) by {
960 assert forall|i: int| 0 <= i < NR_ENTRIES implies l4.children[i] is Some by {
961 if i == c3.idx as int {
962 } else {
963 assert(l4.children[i] == c3.children[i]);
964 }
965 };
966 };
967 l3.as_page_table_owner_pt_inv();
968 assert(l4.pt_inv_children()) by {
969 assert forall|i: int|
970 #![trigger l4.children[i]]
971 !(0 <= i < l4.children.len()) || (l4.children[i] is Some ==> PageTableOwner(
972 l4.children[i].unwrap(),
973 ).pt_inv()) by {
974 if 0 <= i < l4.children.len() {
975 if i == c3.idx as int {
976 assert(l4.children[i] == Some(l3.as_subtree()));
977 } else {
978 assert(l4.children[i] == c3.children[i]);
979 c3.pt_inv_children_unroll(i);
980 }
981 } else {
982 assert(!(0 <= i < l4.children.len()));
983 }
984 };
985 };
986
987 c3.inv_children_unroll_all();
988 l4.as_page_table_owner_preserves_view_mappings();
989
990 assert(self.view_mappings() =~= c0.view_mappings().union(c1.view_mappings()).union(
991 c2.view_mappings(),
992 ).union(c3.view_mappings())) by {
993 assert forall|m: Mapping| self.view_mappings().contains(m) implies (
994 c0.view_mappings().contains(m) || c1.view_mappings().contains(m)
995 || c2.view_mappings().contains(m) || c3.view_mappings().contains(m)) by {
996 let i = choose|i: int|
997 0 <= i < NR_LEVELS
998 && #[trigger] self.continuations[i].view_mappings().contains(m);
999 };
1000 };
1001 }
1002 }
1003
1004 pub proof fn view_mapping_inv(self)
1010 requires
1011 self.inv(),
1012 ensures
1013 forall|m: Mapping| self.view_mappings().contains(m) ==> #[trigger] m.inv(),
1014 {
1015 self.as_page_table_owner_preserves_view_mappings();
1016 let pto = self.as_page_table_owner();
1017 let root_path = self.continuations[3].path();
1018 self.inv_continuation(NR_LEVELS as int - 1);
1019 pto.view_rec_mapping_inv(root_path);
1020 }
1021
1022 pub proof fn view_mapping_page_size_valid(self)
1029 requires
1030 self.inv(),
1031 ensures
1032 forall|m: Mapping| #[trigger]
1033 self.view_mappings().contains(m)
1034 ==> set![4096usize, 2097152usize, 1073741824usize].contains(m.page_size),
1035 {
1036 self.as_page_table_owner_preserves_view_mappings();
1037 let pto = self.as_page_table_owner();
1038 let root_path = self.continuations[3].path();
1039 self.inv_continuation(NR_LEVELS as int - 1);
1040 pto.view_rec_mapping_page_size(root_path);
1044 }
1045
1046 pub proof fn view_mappings_finite(self)
1052 requires
1053 self.inv(),
1054 ensures
1055 self.view_mappings().finite(),
1056 {
1057 self.as_page_table_owner_preserves_view_mappings();
1058 let pto = self.as_page_table_owner();
1059 let root_path = self.continuations[3].path();
1060 self.inv_continuation(NR_LEVELS as int - 1);
1061 pto.view_rec_finite(root_path);
1062 }
1063
1064 pub proof fn as_page_table_owner_view_non_overlapping(self)
1071 requires
1072 self.inv(),
1073 ensures
1074 self@.non_overlapping(),
1075 {
1076 self.as_page_table_owner_preserves_view_mappings();
1077 let pto = self.as_page_table_owner();
1078 let root_path = self.continuations[3].path();
1079
1080 assert(root_path.len() == self.continuations[3].tree_level);
1081 assert(self.continuations[3].tree_level == 0) by {
1082 self.inv_continuation(NR_LEVELS as int - 1);
1083 };
1086 assert(root_path.len() == 0);
1087 assert(pto.0.level == 0);
1088
1089 assert forall|m: Mapping, n: Mapping| #[trigger]
1090 self@.mappings.contains(m) && #[trigger] self@.mappings.contains(n) && m
1091 != n implies m.va_range.end <= n.va_range.start || n.va_range.end
1092 <= m.va_range.start by {
1093 assert(self@.mappings == self.view_mappings());
1094 assert(pto.view_rec(root_path).contains(m));
1095 assert(pto.view_rec(root_path).contains(n));
1096 pto.view_rec_disjoint_vaddrs(root_path, m, n);
1097 };
1098 }
1099}
1100
1101}