1use vstd::prelude::*;
2
3use vstd_extra::ghost_tree::*;
4use vstd_extra::ownership::*;
5
6use crate::mm::page_table::*;
7use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr};
8use crate::specs::arch::mm::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
9use crate::specs::arch::paging_consts::PagingConsts;
10use crate::specs::mm::Guards;
11use crate::specs::mm::Mapping;
12use crate::specs::mm::MetaRegionOwners;
13use crate::specs::mm::page_table::AbstractVaddr;
14use crate::specs::mm::page_table::cursor::owners::*;
15use crate::specs::mm::page_table::node::EntryOwner;
16use crate::specs::mm::page_table::owners::{INC_LEVELS, OwnerSubtree, PageTableOwner};
17
18use crate::mm::page_table::page_size_spec as page_size;
19use crate::specs::mm::frame::mapping::{frame_to_index, meta_to_frame};
20use crate::specs::mm::page_table::cursor::page_size_lemmas::{
21 lemma_page_size_divides, lemma_page_size_ge_page_size,
22};
23use vstd_extra::arithmetic::{
24 lemma_nat_align_down_sound, lemma_nat_align_down_within_block, nat_align_down, nat_align_up,
25};
26
27use core::ops::Range;
28
29verus! {
30
31pub proof fn push_tail_different_indices_different_paths(
33 path: TreePath<NR_ENTRIES>,
34 i: usize,
35 j: usize,
36)
37 requires
38 path.inv(),
39 0 <= i < NR_ENTRIES,
40 0 <= j < NR_ENTRIES,
41 i != j,
42 ensures
43 path.push_tail(i) != path.push_tail(j),
44{
45 path.push_tail_property(i);
46 path.push_tail_property(j);
47 assert(path.push_tail(i).index(path.len() as int) == i as usize);
48 assert(path.push_tail(j).index(path.len() as int) == j as usize);
49 if path.push_tail(i) == path.push_tail(j) {
50 assert(i == j); }
52}
53
54pub proof fn different_length_different_paths(
56 path1: TreePath<NR_ENTRIES>,
57 path2: TreePath<NR_ENTRIES>,
58)
59 requires
60 path1.len() != path2.len(),
61 ensures
62 path1 != path2,
63{
64 if path1 == path2 {
66 assert(path1.len() == path2.len());
67 }
68}
69
70pub proof fn push_tail_increases_length(path: TreePath<NR_ENTRIES>, i: usize)
72 requires
73 path.inv(),
74 0 <= i < NR_ENTRIES,
75 ensures
76 path.push_tail(i).len() > path.len(),
77{
78 path.push_tail_property(i);
79}
80
81pub proof fn subtree_unlock_upgrade<'rcu, C: PageTableConfig>(
87 subtree: OwnerSubtree<C>,
88 path: TreePath<NR_ENTRIES>,
89 guards: Guards<'rcu>,
90 regions: MetaRegionOwners,
91 excepted_addr: usize,
92 excepted_path: TreePath<NR_ENTRIES>,
93)
94 requires
95 subtree.inv(),
96 PageTableOwner::<C>(subtree).pt_inv(),
97 subtree.tree_predicate_map(path, PageTableOwner::<C>::metaregion_sound_pred(regions)),
98 subtree.tree_predicate_map(
99 path,
100 CursorOwner::<'rcu, C>::node_unlocked_except(guards, excepted_addr),
101 ),
102 regions.slot_owners[frame_to_index(meta_to_frame(excepted_addr))].paths_in_pt
103 == set![excepted_path],
104 path == subtree.value.path,
106 path.inv(),
107 path != excepted_path,
109 excepted_path.len() <= path.len() || (exists|k: int|
113 0 <= k < path.len() && #[trigger] excepted_path.index(k) != path.index(k)),
114 ensures
115 subtree.tree_predicate_map(path, CursorOwner::<'rcu, C>::node_unlocked(guards)),
116 decreases INC_LEVELS - subtree.level,
117{
118 let f = PageTableOwner::<C>::metaregion_sound_pred(regions);
119 let g = CursorOwner::<'rcu, C>::node_unlocked_except(guards, excepted_addr);
120 let h = CursorOwner::<'rcu, C>::node_unlocked(guards);
121
122 assert(f(subtree.value, path));
123 assert(g(subtree.value, path));
124 if subtree.value.is_node() {
125 if subtree.value.node.unwrap().meta_addr_self() == excepted_addr {
126 let idx = frame_to_index(meta_to_frame(excepted_addr));
129 assert(subtree.value.metaregion_sound(regions));
130 assert(regions.slot_owners[idx].paths_in_pt == set![subtree.value.path]);
131 assert(set![subtree.value.path].contains(excepted_path));
132 assert(false);
133 }
134 }
135 assert(h(subtree.value, path));
136
137 if subtree.level < INC_LEVELS - 1 && subtree.value.is_node() {
138 assert forall|i: int|
139 #![trigger subtree.children[i]]
140 0 <= i < subtree.children.len()
141 && subtree.children[i] is Some implies subtree.children[i].unwrap().tree_predicate_map(
142 path.push_tail(i as usize), h) by {
143 let child = subtree.children[i].unwrap();
144 subtree.map_unroll_once(path, f, i);
145 subtree.map_unroll_once(path, g, i);
146
147 PageTableOwner::<C>(subtree).pt_inv_unroll(i);
148 let child_path = path.push_tail(i as usize);
149 path.push_tail_property(i as usize);
150
151 assert(child_path != excepted_path) by {
152 if excepted_path.len() <= path.len() {
153 } else {
154 let k = choose|k: int|
155 0 <= k < path.len() && #[trigger] excepted_path.index(k) != path.index(k);
156 assert(child_path.index(k) == path.index(k));
157 }
158 };
159
160 assert(excepted_path.len() <= child_path.len() || (exists|k: int|
161 0 <= k < child_path.len() && #[trigger] excepted_path.index(k) != child_path.index(
162 k,
163 ))) by {
164 if excepted_path.len() <= path.len() {
165 } else {
166 let k = choose|k: int|
167 0 <= k < path.len() && #[trigger] excepted_path.index(k) != path.index(k);
168 assert(child_path.index(k) == path.index(k));
169 }
170 };
171
172 subtree_unlock_upgrade(
173 child,
174 child_path,
175 guards,
176 regions,
177 excepted_addr,
178 excepted_path,
179 );
180 };
181 } else if subtree.level < INC_LEVELS - 1 && !subtree.value.is_node() {
182 assert forall|i: int|
185 #![trigger subtree.children[i]]
186 0 <= i < subtree.children.len()
187 && subtree.children[i] is Some implies subtree.children[i].unwrap().tree_predicate_map(
188 path.push_tail(i as usize), h) by {
189 PageTableOwner::<C>(subtree).pt_inv_non_node(i);
190 };
191 }
192}
193
194impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
195 pub open spec fn max_steps_subtree(level: usize) -> nat
198 decreases level,
199 {
200 if level <= 1 {
201 NR_ENTRIES as nat
202 } else {
203 (NR_ENTRIES as nat) * (Self::max_steps_subtree((level - 1) as usize) + 1)
204 }
205 }
206
207 pub open spec fn max_steps_partial(self, level: usize) -> nat
219 decreases NR_LEVELS + 1 - level,
220 when level <= NR_LEVELS + 1
221 {
222 if level > NR_LEVELS {
223 0
224 } else {
225 let cont = self.continuations[(level - 1) as int];
226 let count: nat = (NR_ENTRIES - cont.idx - 1) as nat;
227 let steps = Self::max_steps_subtree(level) * count;
228 let remaining_steps = self.max_steps_partial((level + 1) as usize);
229 steps + remaining_steps
230 }
231 }
232
233 pub open spec fn max_steps(self) -> nat {
234 (self.max_steps_partial(self.level as usize) + Self::max_steps_subtree(
235 self.level as usize,
236 )) as nat
237 }
238
239 pub proof fn max_steps_subtree_positive(level: usize)
240 ensures
241 Self::max_steps_subtree(level) > 0,
242 decreases level,
243 {
244 if level > 1 {
245 Self::max_steps_subtree_positive((level - 1) as usize);
246 }
247 }
248
249 pub proof fn max_steps_partial_eq(self, other: Self, start: usize)
251 requires
252 1 <= start <= NR_LEVELS + 1,
253 forall|k: int|
254 start - 1 <= k < NR_LEVELS ==> #[trigger] self.continuations[k].idx
255 == other.continuations[k].idx,
256 ensures
257 self.max_steps_partial(start) == other.max_steps_partial(start),
258 decreases NR_LEVELS + 1 - start,
259 {
260 if start <= NR_LEVELS {
261 self.max_steps_partial_eq(other, (start + 1) as usize);
262 }
263 }
264
265 pub proof fn max_steps_partial_inv(self, other: Self, level: usize)
266 requires
267 self.inv(),
268 other.inv(),
269 self.level == other.level,
270 self.level <= level <= NR_LEVELS + 1,
271 forall|i: int|
272 #![trigger self.continuations[i].idx]
273 #![trigger other.continuations[i].idx]
274 self.level - 1 <= i < NR_LEVELS ==> self.continuations[i].idx
275 == other.continuations[i].idx,
276 ensures
277 self.max_steps_partial(level) == other.max_steps_partial(level),
278 decreases NR_LEVELS + 1 - level,
279 {
280 if level <= NR_LEVELS {
281 self.max_steps_partial_inv(other, (level + 1) as usize);
282 }
283 }
284
285 pub open spec fn push_level_owner(self, guard: PageTableGuard<'rcu, C>) -> Self {
286 let cont = self.continuations[self.level - 1];
287 let (child, cont) = cont.make_cont(self.va.index[self.level - 2] as usize, guard);
288 let new_continuations = self.continuations.insert(self.level - 1, cont);
289 let new_continuations = new_continuations.insert(self.level - 2, child);
290
291 let new_level = (self.level - 1) as u8;
292 Self { continuations: new_continuations, level: new_level, popped_too_high: false, ..self }
293 }
294
295 pub proof fn push_level_owner_decreases_steps(self, guard: PageTableGuard<'rcu, C>)
296 requires
297 self.inv(),
298 self.level > 1,
299 ensures
300 self.push_level_owner(guard).max_steps() < self.max_steps(),
301 {
302 let new_self = self.push_level_owner(guard);
303 let l = self.level as usize;
304 let lm1 = (self.level - 1) as usize;
305 new_self.max_steps_partial_eq(self, l);
307 assert(self.va.index.contains_key(self.level - 2));
309 let new_child = new_self.continuations[lm1 - 1];
310 assert(new_child.idx < NR_ENTRIES);
311 Self::max_steps_subtree_positive(lm1);
312 Self::max_steps_subtree_positive(l);
313 assert(Self::max_steps_subtree(l) == (NR_ENTRIES as nat) * (Self::max_steps_subtree(lm1)
315 + 1));
316 vstd::arithmetic::mul::lemma_mul_inequality(
318 (NR_ENTRIES - new_child.idx) as int,
319 NR_ENTRIES as int,
320 Self::max_steps_subtree(lm1) as int,
321 );
322 vstd::arithmetic::mul::lemma_mul_is_distributive_add(
323 Self::max_steps_subtree(lm1) as int,
324 (NR_ENTRIES - new_child.idx - 1) as int,
325 1,
326 );
327 vstd::arithmetic::mul::lemma_mul_is_commutative(
328 (NR_ENTRIES - new_child.idx) as int,
329 Self::max_steps_subtree(lm1) as int,
330 );
331 vstd::arithmetic::mul::lemma_mul_is_commutative(
332 NR_ENTRIES as int,
333 Self::max_steps_subtree(lm1) as int,
334 );
335 vstd::arithmetic::mul::lemma_mul_is_distributive_add(
336 NR_ENTRIES as int,
337 Self::max_steps_subtree(lm1) as int,
338 1,
339 );
340 }
341
342 pub proof fn push_level_owner_preserves_va(self, guard: PageTableGuard<'rcu, C>)
343 requires
344 self.inv(),
345 self.level > 1,
346 ensures
347 self.push_level_owner(guard).va == self.va,
348 self.push_level_owner(guard).continuations[self.level - 2].idx
349 == self.va.index[self.level - 2],
350 {
351 assert(self.va.index.contains_key(self.level - 2));
352 }
353
354 pub proof fn push_level_owner_preserves_mappings(self, guard: PageTableGuard<'rcu, C>)
355 requires
356 self.inv(),
357 self.level > 1,
358 self.cur_entry_owner().is_node(),
359 ensures
360 self.push_level_owner(guard)@.mappings == self@.mappings,
361 {
362 let new_owner = self.push_level_owner(guard);
363 let old_cont = self.continuations[self.level - 1];
364 let (child_cont, modified_cont) = old_cont.make_cont(
365 self.va.index[self.level - 2] as usize,
366 guard,
367 );
368
369 assert(old_cont.all_some());
370 old_cont.view_mappings_take_child();
371
372 let taken = old_cont.take_child().1;
373
374 assert(modified_cont.children =~= taken.children) by {
375 assert forall|j: int|
376 0 <= j < modified_cont.children.len() implies modified_cont.children[j]
377 == taken.children[j] by {
378 if j == old_cont.idx as int {
379 assert(modified_cont.children[j] is None);
380 assert(taken.children[j] is None);
381 } else {
382 assert(modified_cont.children[j] == old_cont.children[j]);
383 }
384 };
385 };
386 assert(modified_cont.view_mappings() =~= taken.view_mappings()) by {
387 assert(modified_cont.path() == taken.path());
388 };
389
390 old_cont.inv_children_rel_unroll(old_cont.idx as int);
391 let child_subtree = old_cont.children[old_cont.idx as int].unwrap();
392 let child_path = old_cont.path().push_tail(old_cont.idx as usize);
393 assert(child_cont.children == child_subtree.children);
394 assert(child_cont.path() == child_path);
395 assert(child_subtree.value.is_node());
396 assert(child_path.len() < INC_LEVELS - 1) by {
397 assert(old_cont.tree_level < INC_LEVELS - 1);
398 assert(old_cont.entry_own.inv_base());
399 old_cont.path().push_tail_property(old_cont.idx as usize);
400 };
401 old_cont.inv_children_unroll(old_cont.idx as int);
402 assert(child_subtree.inv());
403 let pto = PageTableOwner(child_subtree);
404 assert(pto.view_rec(child_path) =~= child_cont.view_mappings()) by {
405 assert forall|m: Mapping| #[trigger]
406 child_cont.view_mappings().contains(m) implies pto.view_rec(child_path).contains(
407 m,
408 ) by {
409 let j = choose|j: int|
410 #![auto]
411 0 <= j < child_cont.children.len() && child_cont.children[j] is Some
412 && PageTableOwner(child_cont.children[j].unwrap()).view_rec(
413 child_cont.path().push_tail(j as usize),
414 ).contains(m);
415 assert(pto.0.children[j] is Some);
416 assert(pto.0.children[j] == child_cont.children[j]);
417 };
418 assert forall|m: Mapping|
419 pto.view_rec(child_path).contains(
420 m,
421 ) implies #[trigger] child_cont.view_mappings().contains(m) by {
422 let j = choose|j: int|
423 #![trigger pto.0.children[j]]
424 0 <= j < pto.0.children.len() && pto.0.children[j] is Some && PageTableOwner(
425 pto.0.children[j].unwrap(),
426 ).view_rec(child_path.push_tail(j as usize)).contains(m);
427 assert(child_cont.children[j] == pto.0.children[j]);
428 assert(child_cont.children[j] is Some);
429 };
430 };
431 assert(child_cont.view_mappings() =~= old_cont.view_mappings_take_child_spec());
432
433 assert forall|m: Mapping|
434 self.view_mappings().contains(m) implies new_owner.view_mappings().contains(m) by {
435 let i = choose|i: int|
436 self.level - 1 <= i < NR_LEVELS && (
437 #[trigger] self.continuations[i]).view_mappings().contains(m);
438 if i == self.level - 1 {
439 if old_cont.view_mappings_take_child_spec().contains(m) {
440 assert(new_owner.continuations[self.level - 2].view_mappings().contains(m));
441 } else {
442 assert(taken.view_mappings().contains(m));
443 assert(modified_cont.view_mappings().contains(m));
444 assert(new_owner.continuations[self.level - 1].view_mappings().contains(m));
445 }
446 } else {
447 assert(new_owner.continuations[i] == self.continuations[i]);
448 }
449 };
450 assert forall|m: Mapping|
451 new_owner.view_mappings().contains(m) implies self.view_mappings().contains(m) by {
452 let i = choose|i: int|
453 new_owner.level - 1 <= i < NR_LEVELS && (
454 #[trigger] new_owner.continuations[i]).view_mappings().contains(m);
455 if i == self.level - 2 {
456 assert(child_cont.view_mappings().contains(m));
457 assert(old_cont.view_mappings_take_child_spec().contains(m));
458 let child_subtree = old_cont.children[old_cont.idx as int].unwrap();
461 assert(PageTableOwner(child_subtree).view_rec(
462 old_cont.path().push_tail(old_cont.idx as usize),
463 ).contains(m));
464 assert(old_cont.view_mappings().contains(m));
465 assert(self.continuations[self.level - 1].view_mappings().contains(m));
466 } else if i == self.level - 1 {
467 assert(modified_cont.view_mappings().contains(m));
468 assert(taken.view_mappings().contains(m));
469 assert(old_cont.view_mappings().contains(m));
471 assert(self.continuations[self.level - 1].view_mappings().contains(m));
472 } else {
473 assert(self.continuations[i] == new_owner.continuations[i]);
474 }
475 };
476 assert(new_owner.view_mappings() =~= self.view_mappings());
477 }
478
479 pub proof fn push_level_owner_preserves_inv(self, guard: PageTableGuard<'rcu, C>)
480 requires
481 self.inv(),
482 self.level > 1,
483 !self.popped_too_high,
484 self.level <= self.guard_level,
485 self.in_locked_range(),
486 self.cur_entry_owner().is_node(),
488 self.cur_entry_owner().node.unwrap().relate_guard(guard),
490 forall|i: int|
492 #![trigger self.continuations[i]]
493 self.level - 1 <= i < NR_LEVELS
494 ==> self.continuations[i].guard.inner.inner@.ptr.addr()
495 != guard.inner.inner@.ptr.addr(),
496 ensures
497 self.push_level_owner(guard).inv(),
498 {
499 self.in_locked_range_guard_index_eq_prefix();
505
506 let new_owner = self.push_level_owner(guard);
507 let new_level = (self.level - 1) as u8;
508
509 let old_cont = self.continuations[self.level - 1];
510 old_cont.inv_children_unroll(old_cont.idx as int);
511 let child_node = old_cont.children[old_cont.idx as int].unwrap();
512 let (child, modified_cont) = old_cont.make_cont(
513 self.va.index[self.level - 2] as usize,
514 guard,
515 );
516
517 old_cont.inv_children_rel_unroll(old_cont.idx as int);
518 assert(child.entry_own == child_node.value);
519 assert(child.entry_own == self.cur_entry_owner());
520 assert(child.children == child_node.children);
521 assert(child.tree_level == old_cont.tree_level + 1);
522
523 assert(self.va.inv());
524 assert(self.va.index.contains_key(self.level - 2));
525 assert(0 <= self.va.index[self.level - 2] < NR_ENTRIES);
526 assert(child.idx == self.va.index[self.level - 2] as usize);
527
528 assert(child.entry_own.inv()) by {
529 old_cont.inv_children_unroll(old_cont.idx as int);
530 };
531
532 assert(child.entry_own.path.len() == old_cont.entry_own.node.unwrap().tree_level + 1);
533 assert(old_cont.entry_own.node.unwrap().tree_level == old_cont.tree_level) by {
534 assert(old_cont.tree_level == INC_LEVELS - old_cont.level() - 1);
535 };
536 assert(child.entry_own.path.len() == child.tree_level) by {
537 assert(child.tree_level == old_cont.tree_level + 1);
538 };
539
540 assert(child.entry_own.node.unwrap().tree_level == child.entry_own.path.len()) by {
541 assert(child.children[0] is Some);
542 let gc = child.children[0].unwrap();
543 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
544 child.entry_own,
545 0,
546 Some(gc.value),
547 ));
548 assert(gc.value.path.len() == child.entry_own.node.unwrap().tree_level + 1);
549 assert(gc.value.path == child.entry_own.path.push_tail(0usize));
550 assert(child.entry_own.inv_base());
551 assert(child.entry_own.path.inv());
552 child.entry_own.path.push_tail_property(0usize);
553 assert(child.entry_own.path.push_tail(0usize).len() == child.entry_own.path.len() + 1);
554 };
555
556 assert(child.tree_level == child.entry_own.node.unwrap().tree_level);
557 assert(child.tree_level == INC_LEVELS - child.level() - 1);
558
559 assert(child.inv_children()) by {
560 assert forall|j: int|
561 0 <= j < child.children.len()
562 && #[trigger] child.children[j] is Some implies child.children[j].unwrap().inv() by {
563 assert(child.children[j] == child_node.children[j]);
564 old_cont.inv_children_unroll(old_cont.idx as int);
565 };
566 };
567 assert(child.inv_children_rel()) by {
568 assert forall|j: int|
569 0 <= j < NR_ENTRIES && #[trigger] child.children[j] is Some implies {
570 &&& child.children[j].unwrap().value.parent_level == child.level()
571 &&& child.children[j].unwrap().level == child.tree_level + 1
572 &&& !child.children[j].unwrap().value.in_scope
573 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
574 child.entry_own,
575 j,
576 Some(child.children[j].unwrap().value),
577 )
578 &&& child.children[j].unwrap().value.path == child.path().push_tail(j as usize)
579 } by {
580 let gc = child.children[j].unwrap();
581 assert(child.children[j] == child_node.children[j]);
582 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
583 child.entry_own,
584 j,
585 Some(gc.value),
586 ));
587 child.inv_children_unroll(j);
588 assert(gc.inv());
589 };
590 };
591 assert(child.inv());
592
593 assert(new_owner.continuations[new_owner.level - 1].all_some()) by {
594 assert(new_owner.continuations[new_owner.level - 1] == child);
595 assert forall|j: int| 0 <= j < NR_ENTRIES implies child.children[j] is Some by {
596 if child.children[j] is None {
597 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
598 child.entry_own,
599 j,
600 None,
601 ));
602 }
603 };
604 };
605
606 assert(modified_cont.all_but_index_some()) by {
607 assert(modified_cont.children[modified_cont.idx as int] is None);
608 assert forall|i: int|
609 0 <= i < modified_cont.idx implies modified_cont.children[i] is Some by {
610 assert(modified_cont.children[i] == old_cont.children[i]);
611 };
612 assert forall|i: int|
613 modified_cont.idx < i < NR_ENTRIES implies modified_cont.children[i] is Some by {
614 assert(modified_cont.children[i] == old_cont.children[i]);
615 };
616 };
617
618 assert(forall|i: int|
619 new_owner.level <= i < NR_LEVELS ==> {
620 (#[trigger] new_owner.continuations[i]).all_but_index_some()
621 }) by {
622 assert forall|i: int| new_owner.level <= i < NR_LEVELS implies (
623 #[trigger] new_owner.continuations[i]).all_but_index_some() by {
624 if i == self.level - 1 {
625 assert(new_owner.continuations[i] == modified_cont);
626 } else {
627 assert(new_owner.continuations[i] == self.continuations[i]);
629 }
630 };
631 };
632
633 assert(modified_cont.children.len() == NR_ENTRIES);
636 assert(0 <= modified_cont.idx < NR_ENTRIES);
637 assert(modified_cont.inv_children()) by {
638 assert forall|i: int|
639 0 <= i < modified_cont.children.len()
640 && #[trigger] modified_cont.children[i] is Some implies modified_cont.children[i].unwrap().inv() by {
641 assert(i != modified_cont.idx);
642 assert(modified_cont.children[i] == old_cont.children[i]);
643 old_cont.inv_children_unroll(i);
644 };
645 };
646 assert(modified_cont.inv_children_rel()) by {
647 assert forall|i: int|
648 0 <= i < NR_ENTRIES && #[trigger] modified_cont.children[i] is Some implies {
649 &&& modified_cont.children[i].unwrap().value.parent_level == modified_cont.level()
650 &&& modified_cont.children[i].unwrap().level == modified_cont.tree_level + 1
651 &&& !modified_cont.children[i].unwrap().value.in_scope
652 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
653 modified_cont.entry_own,
654 i,
655 Some(modified_cont.children[i].unwrap().value),
656 )
657 &&& modified_cont.children[i].unwrap().value.path == modified_cont.path().push_tail(
658 i as usize,
659 )
660 } by {
661 assert(i != modified_cont.idx);
662 assert(modified_cont.children[i] == old_cont.children[i]);
663 assert(old_cont.inv_children_rel());
664 };
665 };
666 assert(modified_cont.entry_own.is_node());
667 assert(modified_cont.entry_own.inv());
668 assert(modified_cont.entry_own.node.unwrap().relate_guard(modified_cont.guard));
669 assert(modified_cont.tree_level == INC_LEVELS - modified_cont.level() - 1);
670 assert(modified_cont.tree_level < INC_LEVELS - 1);
671 assert(modified_cont.path().len() == modified_cont.tree_level);
672 assert(modified_cont.inv());
673
674 assert(new_owner.level <= 4 ==> {
675 &&& new_owner.continuations.contains_key(3)
676 &&& new_owner.continuations[3].inv()
677 &&& new_owner.continuations[3].level() == 4
678 &&& new_owner.continuations[3].entry_own.parent_level == 5
679 &&& new_owner.va.index[3] == new_owner.continuations[3].idx
680 }) by {
681 if new_owner.level <= 4 {
682 if self.level == 4 {
683 assert(new_owner.continuations[3] == modified_cont);
684 } else {
685 assert(new_owner.continuations[3] == self.continuations[3]);
686 }
687 }
688 };
689
690 assert(new_owner.level <= 3 ==> {
692 &&& new_owner.continuations.contains_key(2)
693 &&& new_owner.continuations[2].inv()
694 &&& new_owner.continuations[2].level() == 3
695 &&& new_owner.continuations[2].entry_own.parent_level == 4
696 &&& new_owner.va.index[2] == new_owner.continuations[2].idx
697 &&& new_owner.continuations[2].guard.inner.inner@.ptr.addr()
698 != new_owner.continuations[3].guard.inner.inner@.ptr.addr()
699 &&& new_owner.continuations[2].path() == new_owner.continuations[3].path().push_tail(
700 new_owner.continuations[3].idx as usize,
701 )
702 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
703 new_owner.continuations[3].entry_own,
704 new_owner.continuations[3].idx as int,
705 Some(new_owner.continuations[2].entry_own),
706 )
707 }) by {
708 if new_owner.level <= 3 {
709 if self.level == 4 {
710 assert(self.va.index.contains_key(2));
711 assert(new_owner.continuations[2].guard == guard);
712 assert(new_owner.continuations[3] == modified_cont);
713 assert(modified_cont.guard == old_cont.guard);
714 assert(new_owner.continuations[2].guard.inner.inner@.ptr.addr()
716 != new_owner.continuations[3].guard.inner.inner@.ptr.addr()) by {
717 assert(self.continuations[self.level - 1].guard.inner.inner@.ptr.addr()
718 != guard.inner.inner@.ptr.addr());
719 };
720 assert(new_owner.continuations[2].path()
722 == new_owner.continuations[3].path().push_tail(
723 new_owner.continuations[3].idx as usize,
724 )) by {
725 assert(modified_cont.path() == old_cont.path());
726 assert(modified_cont.idx == old_cont.idx);
727 old_cont.inv_children_rel_unroll(old_cont.idx as int);
728 };
729 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
731 new_owner.continuations[3].entry_own,
732 new_owner.continuations[3].idx as int,
733 Some(new_owner.continuations[2].entry_own),
734 )) by {
735 old_cont.inv_children_rel_unroll(old_cont.idx as int);
736 };
737 } else {
738 }
740 }
741 };
742
743 assert(new_owner.level <= 2 ==> {
745 &&& new_owner.continuations.contains_key(1)
746 &&& new_owner.continuations[1].inv()
747 &&& new_owner.continuations[1].level() == 2
748 &&& new_owner.continuations[1].entry_own.parent_level == 3
749 &&& new_owner.va.index[1] == new_owner.continuations[1].idx
750 &&& new_owner.continuations[1].guard.inner.inner@.ptr.addr()
751 != new_owner.continuations[2].guard.inner.inner@.ptr.addr()
752 &&& new_owner.continuations[1].guard.inner.inner@.ptr.addr()
753 != new_owner.continuations[3].guard.inner.inner@.ptr.addr()
754 &&& new_owner.continuations[1].path() == new_owner.continuations[2].path().push_tail(
755 new_owner.continuations[2].idx as usize,
756 )
757 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
758 new_owner.continuations[2].entry_own,
759 new_owner.continuations[2].idx as int,
760 Some(new_owner.continuations[1].entry_own),
761 )
762 }) by {
763 if new_owner.level <= 2 {
764 if self.level == 3 {
765 assert(self.va.index.contains_key(1));
766 assert(new_owner.continuations[1].guard == guard);
767 assert(new_owner.continuations[2] == modified_cont);
768 assert(modified_cont.guard == old_cont.guard);
769
770 assert(new_owner.continuations[1].guard.inner.inner@.ptr.addr()
771 != new_owner.continuations[2].guard.inner.inner@.ptr.addr()) by {
772 assert(self.continuations[2].guard.inner.inner@.ptr.addr()
773 != guard.inner.inner@.ptr.addr());
774 };
775 assert(new_owner.continuations[1].guard.inner.inner@.ptr.addr()
776 != new_owner.continuations[3].guard.inner.inner@.ptr.addr()) by {
777 assert(self.continuations[3].guard.inner.inner@.ptr.addr()
778 != guard.inner.inner@.ptr.addr());
779 };
780 assert(new_owner.continuations[1].path()
782 == new_owner.continuations[2].path().push_tail(
783 new_owner.continuations[2].idx as usize,
784 )) by {
785 assert(modified_cont.path() == old_cont.path());
786 assert(modified_cont.idx == old_cont.idx);
787 old_cont.inv_children_rel_unroll(old_cont.idx as int);
788 };
789 assert(old_cont.level() == 3);
791 assert(child.entry_own.parent_level == 3) by {
792 old_cont.inv_children_rel_unroll(old_cont.idx as int);
793 };
794 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
796 new_owner.continuations[2].entry_own,
797 new_owner.continuations[2].idx as int,
798 Some(new_owner.continuations[1].entry_own),
799 )) by {
800 old_cont.inv_children_rel_unroll(old_cont.idx as int);
801 };
802 } else {
803 }
805 }
806 };
807
808 assert(new_owner.level == 1 ==> {
810 &&& new_owner.continuations.contains_key(0)
811 &&& new_owner.continuations[0].inv()
812 &&& new_owner.continuations[0].level() == 1
813 &&& new_owner.continuations[0].entry_own.parent_level == 2
814 &&& new_owner.va.index[0] == new_owner.continuations[0].idx
815 &&& new_owner.continuations[0].guard.inner.inner@.ptr.addr()
816 != new_owner.continuations[1].guard.inner.inner@.ptr.addr()
817 &&& new_owner.continuations[0].guard.inner.inner@.ptr.addr()
818 != new_owner.continuations[2].guard.inner.inner@.ptr.addr()
819 &&& new_owner.continuations[0].guard.inner.inner@.ptr.addr()
820 != new_owner.continuations[3].guard.inner.inner@.ptr.addr()
821 &&& new_owner.continuations[0].path() == new_owner.continuations[1].path().push_tail(
822 new_owner.continuations[1].idx as usize,
823 )
824 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
825 new_owner.continuations[1].entry_own,
826 new_owner.continuations[1].idx as int,
827 Some(new_owner.continuations[0].entry_own),
828 )
829 }) by {
830 if new_owner.level == 1 {
831 assert(new_owner.continuations[0].guard == guard);
833 assert(new_owner.continuations[1] == modified_cont);
834 assert(modified_cont.guard == old_cont.guard);
835
836 assert(self.continuations[1].guard.inner.inner@.ptr.addr()
838 != guard.inner.inner@.ptr.addr());
839 assert(self.continuations[2].guard.inner.inner@.ptr.addr()
840 != guard.inner.inner@.ptr.addr());
841 assert(self.continuations[3].guard.inner.inner@.ptr.addr()
842 != guard.inner.inner@.ptr.addr());
843
844 assert(old_cont.level() == 2);
847 assert(child.tree_level == INC_LEVELS - child.level() - 1);
852
853 assert(child.entry_own.parent_level == 2) by {
855 old_cont.inv_children_rel_unroll(old_cont.idx as int);
856 assert(child.entry_own.parent_level == old_cont.level());
857 };
858
859 assert(new_owner.va.index[0] == child.idx);
861
862 assert(child.path() == modified_cont.path().push_tail(modified_cont.idx as usize))
864 by {
865 assert(modified_cont.path() == old_cont.path());
866 assert(modified_cont.idx == old_cont.idx);
867 old_cont.inv_children_rel_unroll(old_cont.idx as int);
868 assert(child.entry_own.path == old_cont.path().push_tail(
869 old_cont.idx as usize,
870 ));
871 };
872
873 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
875 new_owner.continuations[1].entry_own,
876 new_owner.continuations[1].idx as int,
877 Some(new_owner.continuations[0].entry_own),
878 )) by {
879 old_cont.inv_children_rel_unroll(old_cont.idx as int);
880 };
881 }
882 };
883
884 }
885
886 pub proof fn push_level_owner_preserves_invs(
887 self,
888 guard: PageTableGuard<'rcu, C>,
889 regions: MetaRegionOwners,
890 guards: Guards<'rcu>,
891 )
892 requires
893 self.inv(),
894 self.level > 1,
895 !self.popped_too_high,
896 self.level <= self.guard_level,
897 self.in_locked_range(),
898 self.only_current_locked(guards),
899 self.nodes_locked(guards),
900 self.metaregion_sound(regions),
901 self.cur_entry_owner().is_node(),
903 self.cur_entry_owner().node.unwrap().relate_guard(guard),
905 guards.lock_held(guard.inner.inner@.ptr.addr()),
907 ensures
908 self.push_level_owner(guard).inv(),
909 self.push_level_owner(guard).children_not_locked(guards),
910 self.push_level_owner(guard).nodes_locked(guards),
911 self.push_level_owner(guard).metaregion_sound(regions),
912 {
913 if self.level == self.guard_level {
914 self.in_locked_range_guard_index_eq_prefix();
915 }
916 reveal(CursorContinuation::inv_children);
917 let new_owner = self.push_level_owner(guard);
918 let old_cont = self.continuations[self.level - 1];
919 old_cont.inv_children_unroll_all();
920 let (child_cont, modified_cont) = old_cont.make_cont(
921 self.va.index[self.level - 2] as usize,
922 guard,
923 );
924
925 let cur_entry = self.cur_entry_owner();
926 let cur_entry_addr = cur_entry.node.unwrap().meta_addr_self();
927 let cur_entry_path = old_cont.path().push_tail(old_cont.idx as usize);
928 self.cont_entries_metaregion(regions);
929
930 assert forall|i: int|
931 #![trigger self.continuations[i]]
932 self.level - 1 <= i
933 < NR_LEVELS implies self.continuations[i].guard.inner.inner@.ptr.addr()
934 != guard.inner.inner@.ptr.addr() by {
935 let cont_i = self.continuations[i];
936
937 if cont_i.guard.inner.inner@.ptr.addr() == guard.inner.inner@.ptr.addr() {
938 let addr = cont_i.entry_own.node.unwrap().meta_addr_self();
939 assert(addr == cur_entry.node.unwrap().meta_addr_self());
940 let idx = frame_to_index(meta_to_frame(addr));
941 assert(regions.slot_owners[idx].paths_in_pt == set![cont_i.path()]);
942 assert(regions.slot_owners[idx].paths_in_pt == set![cur_entry_path]);
943 assert(set![cont_i.path()].contains(cur_entry_path));
944
945 assert(cur_entry_path.len() == old_cont.tree_level + 1) by {
946 old_cont.inv_children_rel_unroll(old_cont.idx as int);
947 old_cont.entry_own.path.push_tail_property(old_cont.idx as usize);
948 };
949 assert(cont_i.tree_level <= old_cont.tree_level) by {
950 if self.level as int == 1 {
951 assert(old_cont.level() == 1);
952 } else if self.level as int == 2 {
953 assert(old_cont.level() == 2);
954 } else if self.level as int == 3 {
955 assert(old_cont.level() == 3);
956 } else {
957 assert(old_cont.level() == 4);
958 }
959 };
960 assert(false);
961 }
962 };
963 self.push_level_owner_preserves_inv(guard);
964
965 let excepted_idx = frame_to_index(meta_to_frame(cur_entry_addr));
966 assert(regions.slot_owners[excepted_idx].paths_in_pt == set![cur_entry_path]) by {
967 old_cont.inv_children_rel_unroll(old_cont.idx as int);
968 };
969
970 let f = PageTableOwner::<C>::metaregion_sound_pred(regions);
971 let g_except = CursorOwner::<'rcu, C>::node_unlocked_except(guards, cur_entry_addr);
972 let h = CursorOwner::<'rcu, C>::node_unlocked(guards);
973
974 assert forall|i: int|
975 #![trigger new_owner.continuations[i]]
976 new_owner.level - 1 <= i < NR_LEVELS implies new_owner.continuations[i].map_children(
977 h,
978 ) by {
979 if i == self.level - 2 {
980 assert(new_owner.continuations[i] == child_cont);
981 assert forall|j: int|
982 #![trigger child_cont.children[j]]
983 0 <= j < child_cont.children.len()
984 && child_cont.children[j] is Some implies child_cont.children[j].unwrap().tree_predicate_map(
985 child_cont.path().push_tail(j as usize), h) by {
986 let gc = child_cont.children[j].unwrap();
987 let gc_path = child_cont.path().push_tail(j as usize);
988 child_cont.inv_children_unroll(j);
989 child_cont.inv_children_rel_unroll(j);
990 child_cont.path().push_tail_property(j as usize);
991
992 let child_subtree = old_cont.children[old_cont.idx as int].unwrap();
993 child_subtree.map_unroll_once(cur_entry_path, f, j);
994 child_subtree.map_unroll_once(cur_entry_path, g_except, j);
995
996 assert(child_cont.path() == cur_entry_path);
997 assert(gc_path == cur_entry_path.push_tail(j as usize));
998 assert(cur_entry_path.len() < gc_path.len());
999 child_cont.pt_inv_children_unroll(j);
1000 subtree_unlock_upgrade(
1001 gc,
1002 gc_path,
1003 guards,
1004 regions,
1005 cur_entry_addr,
1006 cur_entry_path,
1007 );
1008 };
1009 } else if i == self.level - 1 {
1010 assert(new_owner.continuations[i] == modified_cont);
1011 assert(modified_cont.path() == old_cont.path());
1012 assert forall|j: int|
1013 #![trigger modified_cont.children[j]]
1014 0 <= j < modified_cont.children.len()
1015 && modified_cont.children[j] is Some implies modified_cont.children[j].unwrap().tree_predicate_map(
1016 modified_cont.path().push_tail(j as usize), h) by {
1017 assert(j != old_cont.idx as int);
1018 assert(modified_cont.children[j] == old_cont.children[j]);
1019 let sibling = old_cont.children[j].unwrap();
1020 let sibling_path = old_cont.path().push_tail(j as usize);
1021 old_cont.inv_children_unroll(j);
1022 old_cont.inv_children_rel_unroll(j);
1023 old_cont.path().push_tail_property(j as usize);
1024
1025 push_tail_different_indices_different_paths(
1026 old_cont.path(),
1027 j as usize,
1028 old_cont.idx,
1029 );
1030 old_cont.inv_children_rel_unroll(old_cont.idx as int);
1033 old_cont.path().push_tail_property(old_cont.idx as usize);
1034 assert(cur_entry_path.len() <= sibling_path.len());
1035 old_cont.pt_inv_children_unroll(j);
1036 subtree_unlock_upgrade(
1037 sibling,
1038 sibling_path,
1039 guards,
1040 regions,
1041 cur_entry_addr,
1042 cur_entry_path,
1043 );
1044 };
1045 } else {
1046 assert(new_owner.continuations[i] == self.continuations[i]);
1047 let cont_i = self.continuations[i];
1048
1049 old_cont.entry_own.path.push_tail_property(old_cont.idx as usize);
1050 if i == self.level as int {
1051 assert(old_cont.path() == cont_i.path().push_tail(cont_i.idx as usize));
1052 cont_i.entry_own.path.push_tail_property(cont_i.idx as usize);
1053 } else if i == self.level as int + 1 {
1054 let cont_sl = self.continuations[self.level as int];
1055 assert(old_cont.path() == cont_sl.path().push_tail(cont_sl.idx as usize));
1056 assert(cont_sl.path() == cont_i.path().push_tail(cont_i.idx as usize));
1057 cont_i.entry_own.path.push_tail_property(cont_i.idx as usize);
1058 cont_i.path().push_tail(cont_i.idx as usize).push_tail_property(
1059 cont_sl.idx as usize,
1060 );
1061 } else {
1062 let cont_sl = self.continuations[self.level as int];
1063 let cont_sl1 = self.continuations[self.level as int + 1];
1064 assert(old_cont.path() == cont_sl.path().push_tail(cont_sl.idx as usize));
1065 assert(cont_sl.path() == cont_sl1.path().push_tail(cont_sl1.idx as usize));
1066 assert(cont_sl1.path() == cont_i.path().push_tail(cont_i.idx as usize));
1067 cont_i.entry_own.path.push_tail_property(cont_i.idx as usize);
1068 cont_i.path().push_tail(cont_i.idx as usize).push_tail_property(
1069 cont_sl1.idx as usize,
1070 );
1071 cont_sl1.path().push_tail(cont_sl1.idx as usize).push_tail_property(
1072 cont_sl.idx as usize,
1073 );
1074 }
1075 assert(cur_entry_path.index(cont_i.tree_level as int) == cont_i.idx as usize);
1076
1077 assert forall|j: int|
1078 #![trigger cont_i.children[j]]
1079 0 <= j < cont_i.children.len()
1080 && cont_i.children[j] is Some implies cont_i.children[j].unwrap().tree_predicate_map(
1081 cont_i.path().push_tail(j as usize), h) by {
1082 let child_sub = cont_i.children[j].unwrap();
1083 let child_path = cont_i.path().push_tail(j as usize);
1084 cont_i.inv_children_unroll(j);
1085 cont_i.inv_children_rel_unroll(j);
1086 cont_i.path().push_tail_property(j as usize);
1087
1088 assert(child_path.index(cont_i.tree_level as int) == j as usize);
1089 assert(j != cont_i.idx as int);
1090 assert(child_path.index(cont_i.tree_level as int) != cur_entry_path.index(
1091 cont_i.tree_level as int,
1092 ));
1093 assert(cont_i.tree_level < child_path.len());
1094 cont_i.pt_inv_children_unroll(j);
1095 subtree_unlock_upgrade(
1096 child_sub,
1097 child_path,
1098 guards,
1099 regions,
1100 cur_entry_addr,
1101 cur_entry_path,
1102 );
1103 };
1104 }
1105 };
1106 assert(new_owner.children_not_locked(guards));
1107 assert forall|i: int|
1108 #![trigger new_owner.continuations[i]]
1109 new_owner.level - 1 <= i
1110 < new_owner.guard_level implies new_owner.continuations[i].node_locked(guards) by {
1111 if i == self.level - 2 {
1112 assert(new_owner.continuations[i] == child_cont);
1113 assert(child_cont.guard == guard);
1114 } else if i == self.level - 1 {
1115 assert(new_owner.continuations[i] == modified_cont);
1116 assert(modified_cont.guard == old_cont.guard);
1117 } else {
1118 assert(new_owner.continuations[i] == self.continuations[i]);
1119 }
1120 };
1121 assert(new_owner.nodes_locked(guards));
1122
1123 let f = PageTableOwner::<C>::metaregion_sound_pred(regions);
1124 let child_subtree = child_cont.as_subtree();
1125
1126 assert(child_subtree.inv_children()) by {
1127 assert forall|j: int|
1128 0 <= j < NR_ENTRIES implies match #[trigger] child_subtree.children[j] {
1129 Some(ch) => {
1130 &&& ch.level == child_subtree.level + 1
1131 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1132 child_subtree.value,
1133 j,
1134 Some(ch.value),
1135 )
1136 },
1137 None => <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1138 child_subtree.value,
1139 j,
1140 None,
1141 ),
1142 } by {
1143 assert(child_cont.children[j] is Some);
1144 let ch = child_cont.children[j].unwrap();
1145 assert(ch.level == child_cont.tree_level + 1);
1146 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1147 child_cont.entry_own,
1148 j,
1149 Some(ch.value),
1150 ));
1151 };
1152 };
1153 assert forall|j: int|
1154 0 <= j < NR_ENTRIES implies match #[trigger] child_subtree.children[j] {
1155 Some(ch) => ch.inv(),
1156 None => true,
1157 } by {
1158 child_cont.inv_children_unroll(j);
1159 };
1160 assert(child_subtree.inv()) by {
1161 assert(child_subtree.inv_node());
1162 };
1163
1164 assert(child_subtree.tree_predicate_map(child_cont.path(), f)) by {
1166 assert(f(child_subtree.value, child_cont.path()));
1167 assert forall|j: int|
1168 0 <= j
1169 < child_subtree.children.len() implies match #[trigger] child_subtree.children[j] {
1170 Some(ch) => ch.tree_predicate_map(child_cont.path().push_tail(j as usize), f),
1171 None => true,
1172 } by {
1173 child_subtree.map_unroll_once(child_cont.path(), f, j);
1174 };
1175 };
1176
1177 assert(modified_cont.map_children(f)) by {
1179 assert forall|j: int|
1180 0 <= j < modified_cont.children.len()
1181 && #[trigger] modified_cont.children[j] is Some implies modified_cont.children[j].unwrap().tree_predicate_map(
1182 modified_cont.path().push_tail(j as usize), f) by {
1183 assert(j != old_cont.idx as int);
1184 assert(modified_cont.children[j] == old_cont.children[j]);
1185 };
1186 };
1187
1188 assert(new_owner.metaregion_sound(regions)) by {
1189 assert forall|i: int| #![auto] new_owner.level - 1 <= i < NR_LEVELS implies {
1190 &&& f(new_owner.continuations[i].entry_own, new_owner.continuations[i].path())
1191 &&& new_owner.continuations[i].map_children(f)
1192 } by {
1193 if i == self.level - 2 {
1194 assert(new_owner.continuations[i] == child_cont);
1195 } else if i == self.level - 1 {
1196 assert(new_owner.continuations[i] == modified_cont);
1197 assert(modified_cont.entry_own == old_cont.entry_own);
1198 assert(modified_cont.path() == old_cont.path());
1199 } else {
1200 assert(new_owner.continuations[i] == self.continuations[i]);
1201 }
1202 };
1203 };
1204 }
1205
1206 pub proof fn tracked_push_level_owner(tracked &mut self, guard: PageTableGuard<'rcu, C>)
1207 requires
1208 old(self).inv(),
1209 old(self).level > 1,
1210 ensures
1211 *final(self) == old(self).push_level_owner(guard),
1212 {
1213 assert(self.va.index.contains_key(self.level - 2));
1214
1215 let ghost self0 = *self;
1216 let tracked mut cont = self.continuations.tracked_remove(self.level - 1);
1217 let ghost cont0 = cont;
1218 let tracked child = cont.tracked_make_cont(self.va.index[self.level - 2] as usize, guard);
1219
1220 assert((child, cont) == cont0.make_cont(self.va.index[self.level - 2] as usize, guard));
1221
1222 self.continuations.tracked_insert(self.level - 1, cont);
1223 self.continuations.tracked_insert(self.level - 2, child);
1224
1225 assert(self.continuations == self0.continuations.insert(self.level - 1, cont).insert(
1226 self.level - 2,
1227 child,
1228 ));
1229
1230 self.popped_too_high = false;
1231
1232 self.level = (self.level - 1) as u8;
1233 }
1234
1235 pub open spec fn pop_level_owner(self) -> (Self, PageTableGuard<'rcu, C>) {
1236 let child = self.continuations[self.level - 1];
1237 let cont = self.continuations[self.level as int];
1238 let (new_cont, guard) = cont.restore(child);
1239 let new_continuations = self.continuations.insert(self.level as int, new_cont);
1240 let new_continuations = new_continuations.remove(self.level - 1);
1241 let new_level = (self.level + 1) as u8;
1242 let popped_too_high = if new_level >= self.guard_level {
1243 true
1244 } else {
1245 false
1246 };
1247 (
1248 Self {
1249 continuations: new_continuations,
1250 level: new_level,
1251 popped_too_high: popped_too_high,
1252 ..self
1253 },
1254 guard,
1255 )
1256 }
1257
1258 pub proof fn pop_level_owner_preserves_inv(self)
1259 requires
1260 self.inv(),
1261 self.level < NR_LEVELS,
1262 ensures
1265 self.pop_level_owner().0.inv(),
1266 {
1267 let child = self.continuations[self.level - 1];
1268 assert(child.inv());
1269 assert(child.all_some());
1270 let cont = self.continuations[self.level as int];
1271 assert(cont.inv());
1272 let (new_cont, _) = cont.restore(child);
1273 let new_owner = self.pop_level_owner().0;
1274
1275 let child_node = OwnerSubtree {
1276 value: child.entry_own,
1277 level: child.tree_level,
1278 children: child.children,
1279 };
1280
1281 let nc = self.continuations.insert(self.level as int, new_cont).remove(self.level - 1);
1282 assert(new_owner.continuations == nc);
1283 if self.level < 3 {
1284 assert(nc[3] == self.continuations[3]);
1285 }
1286 if self.level < 2 {
1287 assert(nc[2] == self.continuations[2]);
1288 }
1289 assert(new_cont.all_some()) by {
1290 assert forall|i: int| 0 <= i < NR_ENTRIES implies new_cont.children[i] is Some by {
1291 if i == cont.idx as int {
1292 assert(new_cont.children[i] == Some(child_node));
1293 } else {
1294 assert(new_cont.children[i] == cont.children[i]);
1295 }
1296 };
1297 };
1298
1299 assert forall|i: int| new_owner.level <= i < NR_LEVELS implies (
1300 #[trigger] new_owner.continuations[i]).all_but_index_some() by {
1301 if i == self.level as int {
1302 assert(new_owner.continuations[i] == new_cont);
1303 assert(new_cont.all_some());
1304 } else {
1305 assert(new_owner.continuations[i] == self.continuations[i]);
1306 }
1307 };
1308
1309 assert(child.path() == cont.path().push_tail(cont.idx as usize));
1310 assert(child.entry_own.path == new_cont.path().push_tail(cont.idx as usize));
1311 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1312 new_cont.entry_own,
1313 cont.idx as int,
1314 Some(child.entry_own),
1315 ));
1316
1317 assert(child_node.inv_children()) by {
1318 assert forall|j: int|
1319 0 <= j < NR_ENTRIES implies match #[trigger] child_node.children[j] {
1320 Some(ch) => {
1321 &&& ch.level == child_node.level + 1
1322 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1323 child_node.value,
1324 j,
1325 Some(ch.value),
1326 )
1327 },
1328 None => <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1329 child_node.value,
1330 j,
1331 None,
1332 ),
1333 } by {
1334 assert(child.children[j] is Some);
1335 let ch = child.children[j].unwrap();
1336 assert(ch.level == child.tree_level + 1);
1337 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1338 child.entry_own,
1339 j,
1340 Some(ch.value),
1341 ));
1342 };
1343 };
1344 assert forall|j: int| 0 <= j < NR_ENTRIES implies match #[trigger] child_node.children[j] {
1345 Some(ch) => ch.inv(),
1346 None => true,
1347 } by {
1348 child.inv_children_unroll(j);
1349 };
1350 assert(child_node.inv()) by {
1351 assert(child_node.inv_node());
1352 };
1353
1354 assert(new_cont.inv_children()) by {
1355 assert forall|i: int|
1356 0 <= i < new_cont.children.len()
1357 && #[trigger] new_cont.children[i] is Some implies new_cont.children[i].unwrap().inv() by {
1358 if i == cont.idx as int {
1359 assert(new_cont.children[i].unwrap() == child_node);
1360 } else {
1361 assert(new_cont.children[i] == cont.children[i]);
1362 cont.inv_children_unroll(i);
1363 }
1364 };
1365 };
1366
1367 assert(new_cont.inv_children_rel()) by {
1368 assert forall|i: int|
1369 0 <= i < NR_ENTRIES && #[trigger] new_cont.children[i] is Some implies {
1370 &&& new_cont.children[i].unwrap().value.parent_level == new_cont.level()
1371 &&& new_cont.children[i].unwrap().level == new_cont.tree_level + 1
1372 &&& !new_cont.children[i].unwrap().value.in_scope
1373 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1374 new_cont.entry_own,
1375 i,
1376 Some(new_cont.children[i].unwrap().value),
1377 )
1378 &&& new_cont.children[i].unwrap().value.path == new_cont.path().push_tail(
1379 i as usize,
1380 )
1381 } by {
1382 if i == cont.idx as int {
1383 assert(new_cont.children[i].unwrap() == child_node);
1384 assert(!child.entry_own.in_scope);
1385 } else {
1386 assert(new_cont.children[i] == cont.children[i]);
1387 cont.inv_children_rel_unroll(i);
1388 }
1389 };
1390 };
1391
1392 assert(new_cont.inv()) by {
1393 assert(new_cont.tree_level == INC_LEVELS - new_cont.level() - 1);
1394 assert(new_cont.path().len() == new_cont.tree_level);
1395 };
1396
1397 assert(new_owner.level <= 4 ==> {
1398 &&& new_owner.continuations.contains_key(3)
1399 &&& new_owner.continuations[3].inv()
1400 &&& new_owner.continuations[3].level() == 4
1401 &&& new_owner.continuations[3].entry_own.parent_level
1402 == 5
1403 &&& new_owner.in_locked_range() ==> new_owner.va.index[3]
1406 == new_owner.continuations[3].idx
1407 }) by {
1408 if self.level as int == 3 {
1409 assert(new_owner.continuations[3] == new_cont);
1410 } else {
1411 assert(new_owner.continuations[3] == self.continuations[3]);
1412 }
1413 };
1414
1415 assert(new_owner.level <= 3 ==> {
1417 &&& new_owner.continuations.contains_key(2)
1418 &&& new_owner.continuations[2].inv()
1419 &&& new_owner.continuations[2].level() == 3
1420 &&& new_owner.continuations[2].entry_own.parent_level == 4
1421 &&& new_owner.in_locked_range() ==> new_owner.va.index[2]
1422 == new_owner.continuations[2].idx
1423 &&& new_owner.continuations[2].guard.inner.inner@.ptr.addr()
1424 != new_owner.continuations[3].guard.inner.inner@.ptr.addr()
1425 &&& new_owner.continuations[2].path() == new_owner.continuations[3].path().push_tail(
1426 new_owner.continuations[3].idx as usize,
1427 )
1428 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1429 new_owner.continuations[3].entry_own,
1430 new_owner.continuations[3].idx as int,
1431 Some(new_owner.continuations[2].entry_own),
1432 )
1433 }) by {
1434 if new_owner.level <= 3 {
1435 if self.level as int == 2 {
1436 assert(new_owner.continuations[2] == new_cont);
1437 } else {
1438 assert(new_owner.continuations[2] == self.continuations[2]);
1439 }
1440 }
1441 };
1442
1443 assert(new_owner.level <= 2 ==> {
1445 &&& new_owner.continuations.contains_key(1)
1446 &&& new_owner.continuations[1].inv()
1447 &&& new_owner.continuations[1].level() == 2
1448 &&& new_owner.continuations[1].entry_own.parent_level == 3
1449 &&& new_owner.in_locked_range() ==> new_owner.va.index[1]
1450 == new_owner.continuations[1].idx
1451 &&& new_owner.continuations[1].guard.inner.inner@.ptr.addr()
1452 != new_owner.continuations[2].guard.inner.inner@.ptr.addr()
1453 &&& new_owner.continuations[1].guard.inner.inner@.ptr.addr()
1454 != new_owner.continuations[3].guard.inner.inner@.ptr.addr()
1455 &&& new_owner.continuations[1].path() == new_owner.continuations[2].path().push_tail(
1456 new_owner.continuations[2].idx as usize,
1457 )
1458 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1459 new_owner.continuations[2].entry_own,
1460 new_owner.continuations[2].idx as int,
1461 Some(new_owner.continuations[1].entry_own),
1462 )
1463 }) by {
1464 if new_owner.level <= 2 {
1465 assert(new_owner.continuations[1] == new_cont);
1466 }
1467 };
1468 }
1469
1470 pub proof fn pop_level_owner_preserves_invs(
1471 self,
1472 guards: Guards<'rcu>,
1473 regions: MetaRegionOwners,
1474 )
1475 requires
1476 self.inv(),
1477 self.level < NR_LEVELS,
1478 self.children_not_locked(guards),
1480 self.nodes_locked(guards),
1481 self.metaregion_sound(regions),
1482 ensures
1483 self.pop_level_owner().0.inv(),
1484 self.pop_level_owner().0.only_current_locked(guards),
1485 self.pop_level_owner().0.nodes_locked(guards),
1486 self.pop_level_owner().0.metaregion_sound(regions),
1487 {
1488 let new_owner = self.pop_level_owner().0;
1489 let child = self.continuations[self.level - 1];
1490 let cont = self.continuations[self.level as int];
1491 let (new_cont, _guard) = cont.restore(child);
1492 let child_node = OwnerSubtree {
1493 value: child.entry_own,
1494 level: child.tree_level,
1495 children: child.children,
1496 };
1497
1498 self.pop_level_owner_preserves_inv();
1499
1500 assert(new_owner.va == self.va);
1501
1502 assert(new_owner.nodes_locked(guards)) by {
1503 assert forall|i: int|
1504 #![trigger new_owner.continuations[i]]
1505 new_owner.level - 1 <= i
1506 < new_owner.guard_level implies new_owner.continuations[i].node_locked(
1507 guards,
1508 ) by {
1509 if i == self.level as int {
1510 assert(new_owner.continuations[i] == new_cont);
1511 assert(new_cont.guard == cont.guard);
1512 } else {
1513 assert(new_owner.continuations[i] == self.continuations[i]);
1514 }
1515 };
1516 };
1517
1518 let child_addr = child.entry_own.node.unwrap().meta_addr_self();
1519 let child_subtree = child.as_subtree();
1520
1521 assert forall|j: int|
1522 0 <= j < NR_ENTRIES implies match #[trigger] child_subtree.children[j] {
1523 Some(ch) => ch.inv(),
1524 None => true,
1525 } by {
1526 child.inv_children_unroll(j);
1527 };
1528 assert(child_subtree.inv());
1529
1530 assert(OwnerSubtree::<C>::implies(
1531 CursorOwner::<'rcu, C>::node_unlocked(guards),
1532 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr),
1533 ));
1534 self.map_children_implies(
1535 CursorOwner::<'rcu, C>::node_unlocked(guards),
1536 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr),
1537 );
1538
1539 assert(new_owner.only_current_locked(guards)) by {
1540 assert forall|i: int|
1541 #![trigger new_owner.continuations[i]]
1542 new_owner.level - 1 <= i
1543 < NR_LEVELS implies new_owner.continuations[i].map_children(
1544 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr),
1545 ) by {
1546 if i > self.level as int {
1547 assert(new_owner.continuations[i] == self.continuations[i]);
1548 } else {
1549 assert(new_owner.continuations[i] == new_cont);
1550 new_cont.map_children_lift_skip_idx(
1551 cont,
1552 cont.idx as int,
1553 CursorOwner::<'rcu, C>::node_unlocked(guards),
1554 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr),
1555 );
1556 }
1557 };
1558 };
1559
1560 let f = PageTableOwner::<C>::metaregion_sound_pred(regions);
1561 self.cont_entries_metaregion(regions);
1562
1563 assert(new_owner.metaregion_sound(regions)) by {
1564 assert forall|i: int|
1565 #![auto]
1566 new_owner.level - 1 <= i
1567 < NR_LEVELS implies new_owner.continuations[i].map_children(f) by {
1568 if i > self.level as int {
1569 } else {
1570 new_cont.map_children_lift_skip_idx(cont, cont.idx as int, f, f);
1571 }
1572 };
1573 };
1574 }
1575
1576 pub proof fn set_va_preserves_inv(self, new_va: AbstractVaddr)
1582 requires
1583 self.inv(),
1584 self.in_locked_range(),
1585 !self.popped_too_high,
1586 self.level <= self.guard_level,
1587 new_va.inv(),
1588 new_va.offset == 0,
1589 new_va.leading_bits == self.prefix.leading_bits,
1590 forall|i: int|
1591 #![auto]
1592 self.level - 1 <= i < NR_LEVELS ==> new_va.index[i] == self.va.index[i],
1593 forall|i: int|
1594 #![auto]
1595 self.guard_level - 1 <= i < NR_LEVELS ==> new_va.index[i] == self.prefix.index[i],
1596 ensures
1597 self.set_va(new_va).inv(),
1598 {
1599 let r = self.set_va(new_va);
1600
1601 assert(r.in_locked_range()) by {
1602 let gl = self.guard_level;
1603 if gl >= 1 && gl <= NR_LEVELS {
1604 r.va.align_down_to_vaddr_eq_if_upper_indices_eq(r.prefix, gl as int);
1605 r.va.align_down_concrete(gl as int);
1606 r.prefix.align_down_concrete(gl as int);
1607 self.prefix_aligned_to_guard_level();
1609 self.prefix_plus_ps_no_overflow();
1610 r.prefix.aligned_align_up_advances(gl as int);
1611 AbstractVaddr::from_vaddr_to_vaddr_roundtrip(
1612 nat_align_down(
1613 r.va.to_vaddr() as nat,
1614 page_size(gl as PagingLevel) as nat,
1615 ) as Vaddr,
1616 );
1617 AbstractVaddr::from_vaddr_to_vaddr_roundtrip(
1618 nat_align_down(
1619 r.prefix.to_vaddr() as nat,
1620 page_size(gl as PagingLevel) as nat,
1621 ) as Vaddr,
1622 );
1623 lemma_page_size_ge_page_size(gl as PagingLevel);
1624 lemma_nat_align_down_sound(
1625 r.va.to_vaddr() as nat,
1626 page_size(gl as PagingLevel) as nat,
1627 );
1628 r.prefix.align_down_shape(gl as int);
1629 r.prefix.align_down(gl as int).reflect_prop(
1630 nat_align_down(
1631 r.prefix.to_vaddr() as nat,
1632 page_size(gl as PagingLevel) as nat,
1633 ) as Vaddr,
1634 );
1635 }
1636 };
1637
1638 assert(r.continuations[r.level - 1].all_some());
1639 assert(r.level <= 4 ==> {
1640 &&& r.continuations.contains_key(3)
1641 &&& r.continuations[3].inv()
1642 &&& r.continuations[3].level() == 4
1643 &&& r.continuations[3].entry_own.parent_level == 5
1644 &&& r.in_locked_range() ==> r.va.index[3] == r.continuations[3].idx
1645 });
1646
1647 assert(r.level <= 3 ==> {
1648 &&& r.continuations.contains_key(2)
1649 &&& r.continuations[2].inv()
1650 &&& r.continuations[2].level() == 3
1651 &&& r.continuations[2].entry_own.parent_level == 4
1652 &&& r.in_locked_range() ==> r.va.index[2] == r.continuations[2].idx
1653 &&& r.continuations[2].guard.inner.inner@.ptr.addr()
1654 != r.continuations[3].guard.inner.inner@.ptr.addr()
1655 &&& r.continuations[2].path() == r.continuations[3].path().push_tail(
1656 r.continuations[3].idx as usize,
1657 )
1658 });
1659
1660 assert(r.level <= 2 ==> {
1661 &&& r.continuations.contains_key(1)
1662 &&& r.continuations[1].inv()
1663 &&& r.continuations[1].level() == 2
1664 &&& r.continuations[1].entry_own.parent_level == 3
1665 &&& r.in_locked_range() ==> r.va.index[1] == r.continuations[1].idx
1666 &&& r.continuations[1].guard.inner.inner@.ptr.addr()
1667 != r.continuations[2].guard.inner.inner@.ptr.addr()
1668 &&& r.continuations[1].guard.inner.inner@.ptr.addr()
1669 != r.continuations[3].guard.inner.inner@.ptr.addr()
1670 &&& r.continuations[1].path() == r.continuations[2].path().push_tail(
1671 r.continuations[2].idx as usize,
1672 )
1673 });
1674
1675 assert(r.level == 1 ==> {
1676 &&& r.continuations.contains_key(0)
1677 &&& r.continuations[0].inv()
1678 &&& r.continuations[0].level() == 1
1679 &&& r.continuations[0].entry_own.parent_level == 2
1680 &&& r.in_locked_range() ==> r.va.index[0] == r.continuations[0].idx
1681 &&& r.continuations[0].guard.inner.inner@.ptr.addr()
1682 != r.continuations[1].guard.inner.inner@.ptr.addr()
1683 &&& r.continuations[0].guard.inner.inner@.ptr.addr()
1684 != r.continuations[2].guard.inner.inner@.ptr.addr()
1685 &&& r.continuations[0].guard.inner.inner@.ptr.addr()
1686 != r.continuations[3].guard.inner.inner@.ptr.addr()
1687 &&& r.continuations[0].path() == r.continuations[1].path().push_tail(
1688 r.continuations[1].idx as usize,
1689 )
1690 });
1691 }
1692
1693 pub proof fn tracked_pop_level_owner(tracked &mut self) -> (tracked guard: PageTableGuard<
1694 'rcu,
1695 C,
1696 >)
1697 requires
1698 old(self).inv(),
1699 old(self).level < NR_LEVELS,
1700 ensures
1701 *final(self) == old(self).pop_level_owner().0,
1702 guard == old(self).pop_level_owner().1,
1703 {
1704 let ghost self0 = *self;
1705 let tracked mut parent = self.continuations.tracked_remove(self.level as int);
1706 let tracked child = self.continuations.tracked_remove(self.level - 1);
1707
1708 let tracked guard = parent.tracked_restore(child);
1709
1710 self.continuations.tracked_insert(self.level as int, parent);
1711
1712 assert(self.continuations == self0.continuations.insert(self.level as int, parent).remove(
1713 self.level - 1,
1714 ));
1715
1716 self.level = (self.level + 1) as u8;
1717
1718 if self.level >= self.guard_level {
1719 self.popped_too_high = true;
1720 }
1721 guard
1722 }
1723
1724 pub open spec fn move_forward_owner_spec(self) -> Self
1725 recommends
1726 self.inv(),
1727 self.level < NR_LEVELS,
1728 self.in_locked_range(),
1729 decreases NR_LEVELS - self.level,
1730 when self.level <= NR_LEVELS
1731 {
1732 if self.index() + 1 < NR_ENTRIES {
1733 self.inc_index().zero_below_level()
1738 } else if self.level < NR_LEVELS {
1739 self.pop_level_owner().0.move_forward_owner_spec()
1740 } else {
1741 Self { va: self.va.next_index(NR_LEVELS as int), popped_too_high: false, ..self }
1744 }
1745 }
1746
1747 pub proof fn move_forward_increases_va(self)
1748 requires
1749 self.inv(),
1750 self.level <= NR_LEVELS,
1751 self.in_locked_range(),
1752 !self.popped_too_high,
1753 ensures
1754 self.move_forward_owner_spec().va.to_vaddr() > self.va.to_vaddr(),
1755 decreases NR_LEVELS - self.level,
1756 {
1757 self.in_locked_range_level_le_guard_level();
1758 if self.index() + 1 < NR_ENTRIES {
1759 self.inc_and_zero_increases_va();
1760 } else if self.level == self.guard_level {
1761 self.in_locked_range_guard_index_eq_prefix();
1764 let k = self.prefix.index[self.guard_level - 1];
1765 assert(self.index() == k);
1766 if self.guard_level < NR_LEVELS {
1767 assert(self.level < NR_LEVELS);
1769 self.pop_level_owner_preserves_inv();
1770 let popped = self.pop_level_owner().0;
1771 } else {
1775 self.cursor_top_idx_strict_lt_nr_entries();
1780 assert(false);
1781 }
1782 } else if self.level + 1 < self.guard_level {
1783 assert(self.level < NR_LEVELS);
1784 self.pop_level_owner_preserves_inv();
1785 self.pop_level_owner().0.move_forward_increases_va();
1786 } else {
1787 assert(self.level < NR_LEVELS);
1788 assert(self.guard_level == self.level + 1);
1789 self.in_locked_range_guard_index_eq_prefix();
1790 let k = self.prefix.index[self.guard_level - 1];
1791 assert(self.va.index[self.level as int] == k);
1792 self.pop_level_owner_preserves_inv();
1793 let popped = self.pop_level_owner().0;
1794 assert(self.move_forward_owner_spec() == popped.move_forward_owner_spec());
1795 if k + 1 < NR_ENTRIES {
1796 assert(popped.move_forward_owner_spec() == popped.inc_index().zero_below_level());
1797 popped.inc_and_zero_increases_va();
1798 } else {
1799 }
1803 }
1804 }
1805
1806 pub proof fn move_forward_not_popped_too_high(self)
1807 requires
1808 self.inv(),
1809 self.level <= NR_LEVELS,
1810 self.in_locked_range(),
1811 ensures
1812 !self.move_forward_owner_spec().popped_too_high,
1813 decreases NR_LEVELS - self.level,
1814 {
1815 if self.index() + 1 < NR_ENTRIES {
1816 self.inc_index().zero_preserves_all_but_va();
1817 } else if self.level < NR_LEVELS {
1818 self.pop_level_owner_preserves_inv();
1819 self.pop_level_owner().0.move_forward_not_popped_too_high();
1820 }
1821 }
1822
1823 pub proof fn move_forward_owner_popped_too_high_decreases(self)
1828 requires
1829 self.inv(),
1830 self.level <= NR_LEVELS,
1831 self.in_locked_range(),
1832 self.popped_too_high,
1833 self.continuations[NR_LEVELS - 1].idx + 1 < NR_ENTRIES,
1834 ensures
1835 self.move_forward_owner_spec().max_steps() + Self::max_steps_subtree(
1836 self.level as usize,
1837 ) <= self.max_steps(),
1838 decreases NR_LEVELS - self.level,
1839 {
1840 let l = self.level as usize;
1841 let st_l = Self::max_steps_subtree(l) as int;
1842 Self::max_steps_subtree_positive(l);
1843 if self.index() + 1 < NR_ENTRIES {
1844 let inc = self.inc_index();
1847 inc.zero_preserves_all_but_va();
1848 let new_state = inc.zero_below_level();
1849 assert(new_state.level == self.level);
1850 assert(new_state.continuations[self.level - 1].idx == self.continuations[self.level
1851 - 1].idx + 1);
1852 new_state.max_steps_partial_eq(self, (self.level + 1) as usize);
1853 let self_idx = self.continuations[self.level - 1].idx as int;
1854 vstd::arithmetic::mul::lemma_mul_is_distributive_add(
1855 st_l,
1856 NR_ENTRIES - self_idx - 2,
1857 1,
1858 );
1859 assert(self.move_forward_owner_spec() == new_state);
1860 assert(new_state.max_steps() + st_l == self.max_steps());
1861 } else if self.level < NR_LEVELS {
1862 self.pop_level_owner_preserves_inv();
1864 let popped2 = self.pop_level_owner().0;
1865 let lp1 = (self.level + 1) as usize;
1866 popped2.max_steps_partial_eq(self, lp1);
1867 Self::max_steps_subtree_positive(lp1);
1868
1869 assert(self.continuations[self.level - 1].idx + 1 == NR_ENTRIES);
1871 assert((NR_ENTRIES - self.continuations[self.level - 1].idx - 1) as nat == 0nat);
1872 assert(Self::max_steps_subtree(l) * 0nat == 0) by (nonlinear_arith);
1873 assert(self.max_steps_partial(l) == self.max_steps_partial(lp1));
1874 assert(popped2.level == lp1 as u8);
1875 assert(popped2.max_steps() == self.max_steps_partial(lp1) + Self::max_steps_subtree(
1876 lp1,
1877 ));
1878 assert(self.max_steps() == self.max_steps_partial(lp1) + Self::max_steps_subtree(l));
1879
1880 popped2.move_forward_owner_popped_too_high_decreases();
1887 assert(popped2.move_forward_owner_spec().max_steps() + Self::max_steps_subtree(lp1)
1888 <= popped2.max_steps());
1889 assert(self.move_forward_owner_spec() == popped2.move_forward_owner_spec());
1892 assert(popped2.move_forward_owner_spec().max_steps() <= self.max_steps_partial(lp1));
1897 assert(self.move_forward_owner_spec().max_steps() + st_l <= self.max_steps());
1898 } else {
1899 assert(false);
1902 }
1903 }
1904
1905 pub proof fn move_forward_owner_decreases_steps(self)
1906 requires
1907 self.inv(),
1908 self.level <= NR_LEVELS,
1909 self.in_locked_range(),
1910 !self.popped_too_high,
1911 self.continuations[NR_LEVELS - 1].idx + 1 < NR_ENTRIES,
1914 ensures
1915 self.move_forward_owner_spec().max_steps() + Self::max_steps_subtree(
1920 self.level as usize,
1921 ) <= self.max_steps(),
1922 self.move_forward_owner_spec().max_steps() < self.max_steps(),
1923 decreases NR_LEVELS - self.level,
1924 {
1925 let l = self.level as usize;
1926 let st_l = Self::max_steps_subtree(l) as int;
1927 Self::max_steps_subtree_positive(l);
1928 if self.index() + 1 < NR_ENTRIES {
1929 let inc = self.inc_index();
1933 inc.zero_preserves_all_but_va();
1934 let new_state = inc.zero_below_level();
1935 assert(new_state.level == self.level);
1936 assert(new_state.continuations[self.level - 1].idx == self.continuations[self.level
1937 - 1].idx + 1);
1938 new_state.max_steps_partial_eq(self, (self.level + 1) as usize);
1939 let self_idx = self.continuations[self.level - 1].idx as int;
1940 let tail = self.max_steps_partial((self.level + 1) as usize) as int;
1941 vstd::arithmetic::mul::lemma_mul_is_distributive_add(
1943 st_l,
1944 NR_ENTRIES - self_idx - 2,
1945 1,
1946 );
1947 assert(self.move_forward_owner_spec() == new_state);
1953 assert(new_state.max_steps() + st_l == self.max_steps());
1954 } else if self.level < NR_LEVELS {
1955 self.in_locked_range_level_le_guard_level();
1956 self.pop_level_owner_preserves_inv();
1957 let popped = self.pop_level_owner().0;
1958 let lp1 = (self.level + 1) as usize;
1959 popped.max_steps_partial_eq(self, lp1);
1960 Self::max_steps_subtree_positive(lp1);
1961
1962 assert(self.continuations[self.level - 1].idx + 1 == NR_ENTRIES);
1963 assert((NR_ENTRIES - self.continuations[self.level - 1].idx - 1) as nat == 0nat);
1964 assert(Self::max_steps_subtree(l) * 0nat == 0) by (nonlinear_arith);
1965 assert(self.max_steps_partial(l) == self.max_steps_partial(lp1));
1966 assert(popped.level == (self.level + 1) as u8);
1967 assert(popped.max_steps() == self.max_steps_partial(lp1) + Self::max_steps_subtree(
1968 lp1,
1969 ));
1970 assert(self.max_steps() == self.max_steps_partial(lp1) + Self::max_steps_subtree(l));
1971 if !popped.popped_too_high {
1972 popped.move_forward_owner_decreases_steps();
1973 assert(popped.move_forward_owner_spec().max_steps() + Self::max_steps_subtree(lp1)
1974 <= popped.max_steps());
1975 assert(self.move_forward_owner_spec() == popped.move_forward_owner_spec());
1976 assert(popped.move_forward_owner_spec().max_steps() <= self.max_steps_partial(lp1));
1982 assert(self.move_forward_owner_spec().max_steps() + st_l <= self.max_steps());
1983 } else {
1984 popped.move_forward_owner_popped_too_high_decreases();
1988 assert(popped.move_forward_owner_spec().max_steps() + Self::max_steps_subtree(lp1)
1989 <= popped.max_steps());
1990 assert(self.move_forward_owner_spec() == popped.move_forward_owner_spec());
1991 assert(popped.move_forward_owner_spec().max_steps() <= self.max_steps_partial(lp1));
1997 assert(self.move_forward_owner_spec().max_steps() + st_l <= self.max_steps());
1998 }
1999 } else {
2000 self.in_locked_range_level_le_nr_levels();
2001 self.in_locked_range_level_le_guard_level();
2002 self.cursor_top_idx_strict_lt_nr_entries();
2003 assert(false);
2004 }
2005 }
2006
2007 pub proof fn zero_below_level_eq_align_down(self)
2009 requires
2010 self.va.inv(),
2011 self.va.offset == 0,
2012 1 <= self.level <= NR_LEVELS,
2013 ensures
2014 self.zero_below_level().va == self.va.align_down(self.level as int),
2015 decreases self.level,
2016 {
2017 }
2018
2019 #[verifier::rlimit(4)]
2020 #[verifier::spinoff_prover]
2021 pub proof fn move_forward_va_is_align_up(self)
2022 requires
2023 self.inv(),
2024 self.level <= NR_LEVELS,
2025 self.in_locked_range(),
2026 !self.popped_too_high,
2027 self.level == self.guard_level ==> self.index() + 1 < NR_ENTRIES,
2033 ensures
2034 self.move_forward_owner_spec().va == self.va.align_up(self.level as int),
2035 decreases NR_LEVELS - self.level,
2036 {
2037 if self.level == self.guard_level {
2038 if self.index() + 1 < NR_ENTRIES {
2039 let inc = self.inc_index();
2041 inc.zero_preserves_all_but_va();
2042 inc.zero_below_level_va();
2043 assert(inc.va.inv()) by {
2044 assert forall|i: int| 0 <= i < NR_LEVELS implies inc.va.index.contains_key(i)
2045 && 0 <= #[trigger] inc.va.index[i] && inc.va.index[i] < NR_ENTRIES by {
2046 if i != self.level - 1 {
2047 assert(inc.va.index[i] == self.va.index[i]);
2048 }
2049 };
2050 };
2051 inc.va.align_down_concrete(self.level as int);
2052 let ps = page_size(self.level as PagingLevel) as nat;
2053 let self_va = self.va.to_vaddr() as nat;
2054 lemma_page_size_ge_page_size(self.level as PagingLevel);
2055 assert(self.va.index[self.level - 1] == self.continuations[self.level - 1].idx);
2056 self.va.index_increment_adds_page_size(self.level as int);
2057 let inc_va = inc.va.to_vaddr() as nat;
2058 assert(inc_va == self_va + ps);
2059 assert(self_va + ps == ps * 1 + self_va) by (nonlinear_arith);
2060 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
2061 1int,
2062 self_va as int,
2063 ps as int,
2064 );
2065 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(self_va as int, ps as int);
2066 vstd::arithmetic::div_mod::lemma_mod_bound(self_va as int, ps as int);
2067 vstd::arithmetic::div_mod::lemma_div_pos_is_pos(self_va as int, ps as int);
2068 assert(nat_align_down(inc_va, ps) == nat_align_down(self_va, ps) + ps);
2069 vstd_extra::arithmetic::lemma_nat_align_down_sound(self_va, ps);
2070 assert(vstd_extra::arithmetic::nat_align_down(self_va, ps) + ps
2071 <= usize::MAX as nat);
2072 self.va.align_up_advances_general(self.level as int);
2073 inc.va.align_down_shape(self.level as int);
2074 self.va.align_down_shape(self.level as int);
2075 AbstractVaddr::to_vaddr_from_vaddr_roundtrip(inc.va.align_down(self.level as int));
2076 AbstractVaddr::to_vaddr_from_vaddr_roundtrip(self.va.align_up(self.level as int));
2077 }
2078 return;
2082 }
2083 if self.index() + 1 < NR_ENTRIES {
2084 let inc = self.inc_index();
2085 inc.zero_preserves_all_but_va();
2086 inc.zero_below_level_va();
2087 assert(inc.va.inv()) by {
2088 assert forall|i: int| 0 <= i < NR_LEVELS implies inc.va.index.contains_key(i) && 0
2089 <= #[trigger] inc.va.index[i] && inc.va.index[i] < NR_ENTRIES by {
2090 if i != self.level - 1 {
2091 assert(inc.va.index[i] == self.va.index[i]);
2092 }
2093 };
2094 };
2095 inc.va.align_down_concrete(self.level as int);
2096 let ps = page_size(self.level as PagingLevel) as nat;
2097 let self_va = self.va.to_vaddr() as nat;
2098 lemma_page_size_ge_page_size(self.level as PagingLevel);
2099 assert(self.va.index[self.level - 1] == self.continuations[self.level - 1].idx);
2100 self.va.index_increment_adds_page_size(self.level as int);
2101 let inc_va = inc.va.to_vaddr() as nat;
2102 assert(inc_va == self_va + ps);
2103 assert(self_va + ps == ps * 1 + self_va) by (nonlinear_arith);
2104 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(1int, self_va as int, ps as int);
2105 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(self_va as int, ps as int);
2106 vstd::arithmetic::div_mod::lemma_mod_bound(self_va as int, ps as int);
2107 vstd::arithmetic::div_mod::lemma_div_pos_is_pos(self_va as int, ps as int);
2108 assert(nat_align_down(inc_va, ps) == nat_align_down(self_va, ps) + ps);
2111 vstd_extra::arithmetic::lemma_nat_align_down_sound(self_va, ps);
2115 assert(vstd_extra::arithmetic::nat_align_down(self_va, ps) + ps <= usize::MAX as nat);
2116 self.va.align_up_advances_general(self.level as int);
2117 inc.va.align_down_shape(self.level as int);
2121 self.va.align_down_shape(self.level as int);
2122 AbstractVaddr::to_vaddr_from_vaddr_roundtrip(inc.va.align_down(self.level as int));
2123 AbstractVaddr::to_vaddr_from_vaddr_roundtrip(self.va.align_up(self.level as int));
2124 } else if self.level < NR_LEVELS {
2125 self.in_locked_range_level_le_guard_level();
2126 self.pop_level_owner_preserves_inv();
2127 let popped = self.pop_level_owner().0;
2128 if !popped.popped_too_high {
2129 popped.move_forward_va_is_align_up();
2130 } else {
2131 let inc_p = popped.inc_index();
2132 inc_p.zero_preserves_all_but_va();
2133 inc_p.zero_below_level_va();
2134 assert(inc_p.va.inv()) by {
2135 assert forall|i: int| 0 <= i < NR_LEVELS implies inc_p.va.index.contains_key(i)
2136 && 0 <= #[trigger] inc_p.va.index[i] && inc_p.va.index[i] < NR_ENTRIES by {
2137 if i != popped.level - 1 {
2138 assert(inc_p.va.index[i] == popped.va.index[i]);
2139 }
2140 };
2141 };
2142 inc_p.va.align_down_concrete(popped.level as int);
2143 let ps_p = page_size(popped.level as PagingLevel) as nat;
2144 let popped_va = popped.va.to_vaddr() as nat;
2145 let inc_p_va = inc_p.va.to_vaddr() as nat;
2146 lemma_page_size_ge_page_size(popped.level as PagingLevel);
2147 assert(popped.va.index[popped.level as int - 1]
2148 == popped.continuations[popped.level as int - 1].idx);
2149 popped.va.index_increment_adds_page_size(popped.level as int);
2150 assert(inc_p_va == popped_va + ps_p);
2151 assert(popped_va + ps_p == ps_p * 1 + popped_va) by (nonlinear_arith);
2152 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
2153 1int,
2154 popped_va as int,
2155 ps_p as int,
2156 );
2157 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(popped_va as int, ps_p as int);
2158 vstd::arithmetic::div_mod::lemma_mod_bound(popped_va as int, ps_p as int);
2159 vstd::arithmetic::div_mod::lemma_div_pos_is_pos(popped_va as int, ps_p as int);
2160 vstd_extra::arithmetic::lemma_nat_align_down_sound(popped_va, ps_p);
2162 assert(vstd_extra::arithmetic::nat_align_down(popped_va, ps_p) + ps_p
2163 <= usize::MAX as nat);
2164 popped.va.align_up_advances_general(popped.level as int);
2165 assert(nat_align_down(inc_p_va, ps_p) == vstd_extra::arithmetic::nat_align_down(
2166 popped_va,
2167 ps_p,
2168 ) + ps_p);
2169 inc_p.va.align_down_shape(popped.level as int);
2170 popped.va.align_down_shape(popped.level as int);
2171 AbstractVaddr::to_vaddr_from_vaddr_roundtrip(
2172 inc_p.va.align_down(popped.level as int),
2173 );
2174 AbstractVaddr::to_vaddr_from_vaddr_roundtrip(
2175 popped.va.align_up(popped.level as int),
2176 );
2177 assert(inc_p.va.align_down(popped.level as int) == popped.va.align_up(
2178 popped.level as int,
2179 ));
2180 assert(popped.index() + 1 < NR_ENTRIES);
2181 assert(popped.move_forward_owner_spec().va == inc_p.zero_below_level().va);
2182 }
2183 assert(self.va.index[self.level as int - 1] == self.continuations[self.level as int
2184 - 1].idx);
2185 self.va.align_up_carry(self.level as int);
2186 }
2187 }
2188
2189 pub proof fn pop_level_owner_preserves_mappings(self)
2193 requires
2194 self.inv(),
2195 self.level < NR_LEVELS,
2196 self.in_locked_range(),
2197 ensures
2198 self.pop_level_owner().0@.mappings == self@.mappings,
2199 {
2200 let child = self.continuations[self.level - 1];
2201 let parent = self.continuations[self.level as int];
2202 let (restored_parent, _) = parent.restore(child);
2203 let popped = self.pop_level_owner().0;
2204 let child_subtree = child.as_subtree();
2205
2206 assert(child.inv());
2207 assert(child.all_some());
2208 assert(parent.inv());
2209 assert(parent.all_but_index_some());
2210 assert(child.path() == parent.path().push_tail(parent.idx as usize));
2211
2212 assert(child_subtree.inv()) by {
2213 assert(child_subtree.inv_node());
2214 assert forall|i: int|
2215 0 <= i < NR_ENTRIES implies match #[trigger] child_subtree.children[i] {
2216 Some(ch) => {
2217 &&& ch.level == child_subtree.level + 1
2218 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
2219 child_subtree.value,
2220 i,
2221 Some(ch.value),
2222 )
2223 },
2224 None => <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
2225 child_subtree.value,
2226 i,
2227 None,
2228 ),
2229 } by {
2230 let ch = child.children[i].unwrap();
2231 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
2232 child.entry_own,
2233 i,
2234 Some(ch.value),
2235 ));
2236 };
2237 assert(child_subtree.inv_children());
2238
2239 assert forall|i: int|
2240 0 <= i < NR_ENTRIES implies match #[trigger] child_subtree.children[i] {
2241 Some(ch) => ch.inv(),
2242 None => true,
2243 } by {
2244 child.inv_children_unroll(i);
2245 };
2246 };
2247
2248 parent.as_subtree_restore(child);
2249
2250 let r = restored_parent;
2251 let p = parent.put_child(child_subtree);
2252 assert forall|j: int| 0 <= j < r.children.len() implies r.children[j] == p.children[j] by {
2253 if j == parent.idx as int {
2254 assert(r.children[j] == Some(child_subtree));
2255 } else {
2256 assert(r.children[j] == parent.children[j]);
2257 }
2258 };
2259 assert(r.children =~= p.children);
2260 assert(restored_parent.view_mappings() =~= parent.put_child(child_subtree).view_mappings())
2261 by {
2262 assert(r.path() == p.path());
2263 assert forall|m: Mapping|
2264 r.view_mappings().contains(m) implies p.view_mappings().contains(m) by {
2265 let j = choose|j: int|
2266 #![auto]
2267 0 <= j < r.children.len() && r.children[j] is Some && PageTableOwner(
2268 r.children[j].unwrap(),
2269 ).view_rec(r.path().push_tail(j as usize)).contains(m);
2270 assert(p.children[j] is Some);
2271 assert(PageTableOwner(p.children[j].unwrap()).view_rec(
2272 p.path().push_tail(j as usize),
2273 ).contains(m));
2274 };
2275 assert forall|m: Mapping|
2276 p.view_mappings().contains(m) implies r.view_mappings().contains(m) by {
2277 let j = choose|j: int|
2278 #![auto]
2279 0 <= j < p.children.len() && p.children[j] is Some && PageTableOwner(
2280 p.children[j].unwrap(),
2281 ).view_rec(p.path().push_tail(j as usize)).contains(m);
2282 assert(r.children[j] is Some);
2283 assert(PageTableOwner(r.children[j].unwrap()).view_rec(
2284 r.path().push_tail(j as usize),
2285 ).contains(m));
2286 };
2287 };
2288
2289 parent.view_mappings_put_child(child_subtree);
2290 child.as_page_table_owner_preserves_view_mappings();
2291
2292 assert(popped.level == (self.level + 1) as u8);
2293 assert(popped.continuations[self.level as int] == restored_parent);
2294
2295 assert(popped.view_mappings() =~= self.view_mappings()) by {
2296 assert forall|m: Mapping|
2297 self.view_mappings().contains(m) implies popped.view_mappings().contains(m) by {
2298 let i = choose|i: int|
2299 self.level - 1 <= i < NR_LEVELS && (
2300 #[trigger] self.continuations[i]).view_mappings().contains(m);
2301 if i == self.level - 1 {
2302 assert(child.view_mappings().contains(m));
2303 assert(restored_parent.view_mappings().contains(m));
2304 assert(popped.continuations[self.level as int].view_mappings().contains(m));
2305 } else if i == self.level as int {
2306 assert(parent.view_mappings().contains(m));
2307 assert(restored_parent.view_mappings().contains(m));
2308 assert(popped.continuations[self.level as int].view_mappings().contains(m));
2309 } else {
2310 assert(popped.continuations[i] == self.continuations[i]);
2311 }
2312 };
2313 assert forall|m: Mapping|
2314 popped.view_mappings().contains(m) implies self.view_mappings().contains(m) by {
2315 let i = choose|i: int|
2316 popped.level - 1 <= i < NR_LEVELS && (
2317 #[trigger] popped.continuations[i]).view_mappings().contains(m);
2318 if i == self.level as int {
2319 assert(restored_parent.view_mappings().contains(m));
2320 if child.view_mappings().contains(m) {
2321 assert(self.continuations[self.level - 1].view_mappings().contains(m));
2322 } else {
2323 assert(parent.view_mappings().contains(m));
2324 assert(self.continuations[self.level as int].view_mappings().contains(m));
2325 }
2326 } else {
2327 assert(self.continuations[i] == popped.continuations[i]);
2328 }
2329 };
2330 };
2331 }
2332
2333 pub proof fn move_forward_owner_preserves_mappings(self)
2334 requires
2335 self.inv(),
2336 self.in_locked_range(),
2337 ensures
2338 self.move_forward_owner_spec()@.mappings == self@.mappings,
2339 decreases NR_LEVELS - self.level,
2340 {
2341 if self.index() + 1 < NR_ENTRIES {
2342 let inc = self.inc_index();
2343 let result = inc.zero_below_level();
2344
2345 inc.zero_preserves_all_but_va();
2346 assert(result.continuations =~= inc.continuations);
2347 assert(result.level == inc.level);
2348
2349 let old_cont = self.continuations[self.level - 1];
2350 let new_cont = old_cont.inc_index();
2351 assert(new_cont.children =~= old_cont.children);
2352 assert(new_cont.entry_own == old_cont.entry_own);
2353 assert(new_cont.path() == old_cont.path());
2354
2355 assert(new_cont.view_mappings() =~= old_cont.view_mappings()) by {
2356 assert forall|m: Mapping|
2357 old_cont.view_mappings().contains(m) implies new_cont.view_mappings().contains(
2358 m,
2359 ) by {
2360 let i = choose|i: int|
2361 #![auto]
2362 0 <= i < old_cont.children.len() && old_cont.children[i] is Some
2363 && PageTableOwner(old_cont.children[i].unwrap()).view_rec(
2364 old_cont.path().push_tail(i as usize),
2365 ).contains(m);
2366 assert(new_cont.children[i] is Some);
2367 assert(PageTableOwner(new_cont.children[i].unwrap()).view_rec(
2368 new_cont.path().push_tail(i as usize),
2369 ).contains(m));
2370 };
2371 assert forall|m: Mapping|
2372 new_cont.view_mappings().contains(m) implies old_cont.view_mappings().contains(
2373 m,
2374 ) by {
2375 let i = choose|i: int|
2376 #![auto]
2377 0 <= i < new_cont.children.len() && new_cont.children[i] is Some
2378 && PageTableOwner(new_cont.children[i].unwrap()).view_rec(
2379 new_cont.path().push_tail(i as usize),
2380 ).contains(m);
2381 assert(old_cont.children[i] is Some);
2382 assert(PageTableOwner(old_cont.children[i].unwrap()).view_rec(
2383 old_cont.path().push_tail(i as usize),
2384 ).contains(m));
2385 };
2386 };
2387
2388 assert(result.view_mappings() =~= self.view_mappings()) by {
2389 assert forall|m: Mapping|
2390 self.view_mappings().contains(m) implies result.view_mappings().contains(m) by {
2391 let i = choose|i: int|
2392 self.level - 1 <= i < NR_LEVELS && (
2393 #[trigger] self.continuations[i]).view_mappings().contains(m);
2394 if i == self.level - 1 {
2395 assert(result.continuations[i].view_mappings().contains(m));
2396 } else {
2397 assert(result.continuations[i] == self.continuations[i]);
2398 }
2399 };
2400 assert forall|m: Mapping|
2401 result.view_mappings().contains(m) implies self.view_mappings().contains(m) by {
2402 let i = choose|i: int|
2403 result.level - 1 <= i < NR_LEVELS && (
2404 #[trigger] result.continuations[i]).view_mappings().contains(m);
2405 if i == self.level - 1 {
2406 assert(self.continuations[i].view_mappings().contains(m));
2407 } else {
2408 assert(self.continuations[i] == result.continuations[i]);
2409 }
2410 };
2411 };
2412 } else if self.level < NR_LEVELS {
2413 let popped = self.pop_level_owner().0;
2414
2415 self.pop_level_owner_preserves_inv();
2416 assert(popped.in_locked_range()) by {
2417 assert(popped.va == self.va);
2418 assert(popped.prefix == self.prefix);
2419 assert(popped.guard_level == self.guard_level);
2420 };
2421
2422 self.pop_level_owner_preserves_mappings();
2423 popped.move_forward_owner_preserves_mappings();
2424 }
2425 }
2426}
2427
2428}