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