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::page_table::cursor::owners::*;
11use crate::specs::mm::page_table::node::EntryOwner;
12use crate::specs::mm::page_table::node::GuardPerm;
13use crate::specs::mm::page_table::owners::{OwnerSubtree, PageTableOwner, INC_LEVELS};
14use crate::specs::mm::page_table::AbstractVaddr;
15use crate::specs::mm::Guards;
16use crate::specs::mm::Mapping;
17use crate::specs::mm::MetaRegionOwners;
18
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_ge_page_size,
22 lemma_page_size_divides,
23};
24use vstd_extra::arithmetic::{
25 lemma_nat_align_down_sound,
26 lemma_nat_align_down_within_block,
27 nat_align_down,
28 nat_align_up,
29};
30use crate::mm::page_table::page_size_spec as page_size;
31
32use core::ops::Range;
33
34verus! {
35
36pub proof fn push_tail_different_indices_different_paths(
38 path: TreePath<NR_ENTRIES>,
39 i: usize,
40 j: usize,
41)
42 requires
43 path.inv(),
44 0 <= i < NR_ENTRIES,
45 0 <= j < NR_ENTRIES,
46 i != j,
47 ensures
48 path.push_tail(i) != path.push_tail(j),
49{
50 path.push_tail_property(i);
51 path.push_tail_property(j);
52 assert(path.push_tail(i).index(path.len() as int) == i as usize);
53 assert(path.push_tail(j).index(path.len() as int) == j as usize);
54 if path.push_tail(i) == path.push_tail(j) {
55 assert(i == j); }
57}
58
59pub proof fn different_length_different_paths(
61 path1: TreePath<NR_ENTRIES>,
62 path2: TreePath<NR_ENTRIES>,
63)
64 requires
65 path1.len() != path2.len(),
66 ensures
67 path1 != path2,
68{
69 if path1 == path2 {
71 assert(path1.len() == path2.len());
72 }
73}
74
75pub proof fn push_tail_increases_length(
77 path: TreePath<NR_ENTRIES>,
78 i: usize,
79)
80 requires
81 path.inv(),
82 0 <= i < NR_ENTRIES,
83 ensures
84 path.push_tail(i).len() > path.len(),
85{
86 path.push_tail_property(i);
87}
88
89pub proof fn subtree_unlock_upgrade<'rcu, C: PageTableConfig>(
95 subtree: OwnerSubtree<C>,
96 path: TreePath<NR_ENTRIES>,
97 guards: Guards<'rcu, C>,
98 regions: MetaRegionOwners,
99 excepted_addr: usize,
100 excepted_path: TreePath<NR_ENTRIES>,
101)
102 requires
103 subtree.inv(),
104 PageTableOwner::<C>(subtree).pt_inv(),
105 subtree.tree_predicate_map(path, PageTableOwner::<C>::metaregion_sound_pred(regions)),
106 subtree.tree_predicate_map(path, CursorOwner::<'rcu, C>::node_unlocked_except(guards, excepted_addr)),
107 regions.slot_owners[frame_to_index(meta_to_frame(excepted_addr))].paths_in_pt
108 == set![excepted_path],
109 path == subtree.value.path,
111 path.inv(),
112 path != excepted_path,
114 excepted_path.len() <= path.len() ||
118 (exists|k: int| 0 <= k < path.len() && #[trigger] excepted_path.index(k) != path.index(k)),
119 ensures
120 subtree.tree_predicate_map(path, CursorOwner::<'rcu, C>::node_unlocked(guards)),
121 decreases INC_LEVELS - subtree.level,
122{
123 let f = PageTableOwner::<C>::metaregion_sound_pred(regions);
124 let g = CursorOwner::<'rcu, C>::node_unlocked_except(guards, excepted_addr);
125 let h = CursorOwner::<'rcu, C>::node_unlocked(guards);
126
127 assert(f(subtree.value, path));
128 assert(g(subtree.value, path));
129 if subtree.value.is_node() {
130 if subtree.value.node.unwrap().meta_perm.addr() == excepted_addr {
131 let idx = frame_to_index(meta_to_frame(excepted_addr));
134 assert(subtree.value.metaregion_sound(regions));
135 assert(regions.slot_owners[idx].paths_in_pt == set![subtree.value.path]);
136 assert(set![subtree.value.path].contains(excepted_path));
137 assert(false);
138 }
139 }
140 assert(h(subtree.value, path));
141
142 if subtree.level < INC_LEVELS - 1 && subtree.value.is_node() {
143 assert forall |i: int|
144 #![trigger subtree.children[i]]
145 0 <= i < subtree.children.len() && subtree.children[i] is Some implies
146 subtree.children[i].unwrap().tree_predicate_map(path.push_tail(i as usize), h) by {
147 let child = subtree.children[i].unwrap();
148 subtree.map_unroll_once(path, f, i);
149 subtree.map_unroll_once(path, g, i);
150
151 PageTableOwner::<C>(subtree).pt_inv_unroll(i);
152 let child_path = path.push_tail(i as usize);
153 path.push_tail_property(i as usize);
154
155 assert(child_path != excepted_path) by {
156 if excepted_path.len() <= path.len() {
157 } else {
158 let k = choose|k: int| 0 <= k < path.len() && #[trigger] excepted_path.index(k) != path.index(k);
159 assert(child_path.index(k) == path.index(k));
160 }
161 };
162
163 assert(excepted_path.len() <= child_path.len() ||
164 (exists|k: int| 0 <= k < child_path.len() && #[trigger] excepted_path.index(k) != child_path.index(k))) by {
165 if excepted_path.len() <= path.len() {
166 } else {
167 let k = choose|k: int| 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(child, child_path, guards, regions, excepted_addr, excepted_path);
173 };
174 } else if subtree.level < INC_LEVELS - 1 && !subtree.value.is_node() {
175 assert forall |i: int|
178 #![trigger subtree.children[i]]
179 0 <= i < subtree.children.len() && subtree.children[i] is Some implies
180 subtree.children[i].unwrap().tree_predicate_map(path.push_tail(i as usize), h) by {
181 PageTableOwner::<C>(subtree).pt_inv_non_node(i);
182 };
183 }
184}
185
186impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
187
188 pub open spec fn max_steps_subtree(level: usize) -> nat
191 decreases level,
192 {
193 if level <= 1 {
194 NR_ENTRIES as nat
195 } else {
196 (NR_ENTRIES as nat) * (Self::max_steps_subtree((level - 1) as usize) + 1)
197 }
198 }
199
200 pub open spec fn max_steps_partial(self, level: usize) -> nat
203 decreases NR_LEVELS - level,
204 when level <= NR_LEVELS
205 {
206 if level == NR_LEVELS {
207 0
208 } else {
209 let cont = self.continuations[(level - 1) as int];
211 let steps = Self::max_steps_subtree(level) * ((NR_ENTRIES - cont.idx) as nat);
213 let remaining_steps = self.max_steps_partial((level + 1) as usize);
215 steps + remaining_steps
216 }
217 }
218
219 pub open spec fn max_steps(self) -> nat {
220 self.max_steps_partial(self.level as usize)
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,
237 forall |k: int|
238 start - 1 <= k < NR_LEVELS ==> #[trigger] self.continuations[k].idx == other.continuations[k].idx,
239 ensures
240 self.max_steps_partial(start) == other.max_steps_partial(start),
241 decreases NR_LEVELS - start,
242 {
243 if start < NR_LEVELS {
244 self.max_steps_partial_eq(other, (start + 1) as usize);
245 }
246 }
247
248 pub proof fn max_steps_partial_inv(self, other: Self, level: usize)
249 requires
250 self.inv(),
251 other.inv(),
252 self.level == other.level,
253 self.level <= level <= NR_LEVELS,
254 forall |i: int|
255 #![trigger self.continuations[i].idx]
256 #![trigger other.continuations[i].idx]
257 self.level - 1 <= i < NR_LEVELS ==> self.continuations[i].idx == other.continuations[i].idx,
258 ensures
259 self.max_steps_partial(level) == other.max_steps_partial(level),
260 decreases NR_LEVELS - level,
261 {
262 if level < NR_LEVELS {
263 self.max_steps_partial_inv(other, (level + 1) as usize);
264 }
265 }
266
267 pub open spec fn push_level_owner_spec(self, guard_perm: GuardPerm<'rcu, C>) -> Self
268 {
269 let cont = self.continuations[self.level - 1];
270 let (child, cont) = cont.make_cont_spec(self.va.index[self.level - 2] as usize, guard_perm);
271 let new_continuations = self.continuations.insert(self.level - 1, cont);
272 let new_continuations = new_continuations.insert(self.level - 2, child);
273
274 let new_level = (self.level - 1) as u8;
275 Self {
276 continuations: new_continuations,
277 level: new_level,
278 popped_too_high: false,
279 ..self
280 }
281 }
282
283 pub proof fn push_level_owner_decreases_steps(self, guard_perm: GuardPerm<'rcu, C>)
284 requires
285 self.inv(),
286 self.level > 0,
287 ensures
288 self.push_level_owner_spec(guard_perm).max_steps() < self.max_steps()
289 { admit() }
290
291 pub proof fn push_level_owner_preserves_va(self, guard_perm: GuardPerm<'rcu, C>)
292 requires
293 self.inv(),
294 self.level > 1,
295 ensures
296 self.push_level_owner_spec(guard_perm).va == self.va,
297 self.push_level_owner_spec(guard_perm).continuations[self.level - 2].idx == self.va.index[self.level - 2],
298 {
299 assert(self.va.index.contains_key(self.level - 2));
300 }
301
302 pub proof fn push_level_owner_preserves_mappings(self, guard_perm: GuardPerm<'rcu, C>)
303 requires
304 self.inv(),
305 self.level > 1,
306 self.cur_entry_owner().is_node(),
307 ensures
308 self.push_level_owner_spec(guard_perm)@.mappings == self@.mappings,
309 {
310 let new_owner = self.push_level_owner_spec(guard_perm);
311 let old_cont = self.continuations[self.level - 1];
312 let (child_cont, modified_cont) = old_cont.make_cont_spec(self.va.index[self.level - 2] as usize, guard_perm);
313
314 assert(old_cont.all_some());
315 old_cont.view_mappings_take_child();
316
317 let taken = old_cont.take_child_spec().1;
318
319 assert(modified_cont.children =~= taken.children) by {
320 assert forall |j: int| 0 <= j < modified_cont.children.len()
321 implies modified_cont.children[j] == taken.children[j] by {
322 if j == old_cont.idx as int {
323 assert(modified_cont.children[j] is None);
324 assert(taken.children[j] is None);
325 } else {
326 assert(modified_cont.children[j] == old_cont.children[j]);
327 }
328 };
329 };
330 assert(modified_cont.view_mappings() =~= taken.view_mappings()) by {
331 assert(modified_cont.path() == taken.path());
332 };
333
334 old_cont.inv_children_rel_unroll(old_cont.idx as int);
335 let child_subtree = old_cont.children[old_cont.idx as int].unwrap();
336 let child_path = old_cont.path().push_tail(old_cont.idx as usize);
337 assert(child_cont.children == child_subtree.children);
338 assert(child_cont.path() == child_path);
339 assert(child_subtree.value.is_node());
340 assert(child_path.len() < INC_LEVELS - 1) by {
341 assert(old_cont.tree_level < INC_LEVELS - 1);
342 assert(old_cont.entry_own.inv_base());
343 old_cont.path().push_tail_property(old_cont.idx as usize);
344 };
345 old_cont.inv_children_unroll(old_cont.idx as int);
346 assert(child_subtree.inv());
347 let pto = PageTableOwner(child_subtree);
348 assert(pto.view_rec(child_path) =~= child_cont.view_mappings()) by {
349 assert forall |m: Mapping| #[trigger] child_cont.view_mappings().contains(m) implies
350 pto.view_rec(child_path).contains(m) by {
351 let j = choose |j: int| #![auto]
352 0 <= j < child_cont.children.len()
353 && child_cont.children[j] is Some
354 && PageTableOwner(child_cont.children[j].unwrap()).view_rec(
355 child_cont.path().push_tail(j as usize)).contains(m);
356 assert(pto.0.children[j] is Some);
357 assert(pto.0.children[j] == child_cont.children[j]);
358 };
359 assert forall |m: Mapping| pto.view_rec(child_path).contains(m) implies
360 #[trigger] child_cont.view_mappings().contains(m) by {
361 let j = choose |j: int|
362 #![trigger pto.0.children[j]]
363 0 <= j < pto.0.children.len()
364 && pto.0.children[j] is Some
365 && PageTableOwner(pto.0.children[j].unwrap()).view_rec(
366 child_path.push_tail(j as usize)).contains(m);
367 assert(child_cont.children[j] == pto.0.children[j]);
368 assert(child_cont.children[j] is Some);
369 };
370 };
371 assert(child_cont.view_mappings() =~= old_cont.view_mappings_take_child_spec());
372
373 assert forall |m: Mapping| self.view_mappings().contains(m)
374 implies new_owner.view_mappings().contains(m) by {
375 let i = choose |i: int|
376 self.level - 1 <= i < NR_LEVELS
377 && (#[trigger] self.continuations[i]).view_mappings().contains(m);
378 if i == self.level - 1 {
379 if old_cont.view_mappings_take_child_spec().contains(m) {
380 assert(new_owner.continuations[self.level - 2].view_mappings().contains(m));
381 } else {
382 assert(taken.view_mappings().contains(m));
383 assert(modified_cont.view_mappings().contains(m));
384 assert(new_owner.continuations[self.level - 1].view_mappings().contains(m));
385 }
386 } else {
387 assert(new_owner.continuations[i] == self.continuations[i]);
388 }
389 };
390 assert forall |m: Mapping| new_owner.view_mappings().contains(m)
391 implies self.view_mappings().contains(m) by {
392 let i = choose |i: int|
393 new_owner.level - 1 <= i < NR_LEVELS
394 && (#[trigger] new_owner.continuations[i]).view_mappings().contains(m);
395 if i == self.level - 2 {
396 assert(child_cont.view_mappings().contains(m));
397 assert(old_cont.view_mappings_take_child_spec().contains(m));
398 let child_subtree = old_cont.children[old_cont.idx as int].unwrap();
401 assert(PageTableOwner(child_subtree).view_rec(
402 old_cont.path().push_tail(old_cont.idx as usize)).contains(m));
403 assert(old_cont.view_mappings().contains(m));
404 assert(self.continuations[self.level - 1].view_mappings().contains(m));
405 } else if i == self.level - 1 {
406 assert(modified_cont.view_mappings().contains(m));
407 assert(taken.view_mappings().contains(m));
408 assert(old_cont.view_mappings().contains(m));
410 assert(self.continuations[self.level - 1].view_mappings().contains(m));
411 } else {
412 assert(self.continuations[i] == new_owner.continuations[i]);
413 }
414 };
415 assert(new_owner.view_mappings() =~= self.view_mappings());
416 }
417
418 pub proof fn push_level_owner_preserves_inv(self, guard_perm: GuardPerm<'rcu, C>)
419 requires
420 self.inv(),
421 self.level > 1,
422 !self.popped_too_high,
423 self.level < self.guard_level,
424 self.cur_entry_owner().is_node(),
426 self.cur_entry_owner().node.unwrap().relate_guard_perm(guard_perm),
428 forall |i: int|
430 #![trigger self.continuations[i]]
431 self.level - 1 <= i < NR_LEVELS ==>
432 self.continuations[i].guard_perm.value().inner.inner@.ptr.addr()
433 != guard_perm.value().inner.inner@.ptr.addr(),
434 ensures
435 self.push_level_owner_spec(guard_perm).inv(),
436 {
437 let new_owner = self.push_level_owner_spec(guard_perm);
438 let new_level = (self.level - 1) as u8;
439
440 let old_cont = self.continuations[self.level - 1];
441 old_cont.inv_children_unroll(old_cont.idx as int);
442 let child_node = old_cont.children[old_cont.idx as int].unwrap();
443 let (child, modified_cont) = old_cont.make_cont_spec(self.va.index[self.level - 2] as usize, guard_perm);
444
445 old_cont.inv_children_rel_unroll(old_cont.idx as int);
446 assert(child.entry_own == child_node.value);
447 assert(child.entry_own == self.cur_entry_owner());
448 assert(child.children == child_node.children);
449 assert(child.tree_level == old_cont.tree_level + 1);
450
451 reveal(CursorContinuation::inv_children);
452
453 assert(self.va.inv());
454 assert(self.va.index.contains_key(self.level - 2));
455 assert(0 <= self.va.index[self.level - 2] < NR_ENTRIES);
456 assert(child.idx == self.va.index[self.level - 2] as usize);
457
458 assert(child.entry_own.inv()) by {
459 old_cont.inv_children_unroll(old_cont.idx as int);
460 };
461
462 assert(child.entry_own.path.len() == old_cont.entry_own.node.unwrap().tree_level + 1);
463 assert(old_cont.entry_own.node.unwrap().tree_level == old_cont.tree_level) by {
464 assert(old_cont.tree_level == INC_LEVELS - old_cont.level() - 1);
465 };
466 assert(child.entry_own.path.len() == child.tree_level) by {
467 assert(child.tree_level == old_cont.tree_level + 1);
468 };
469
470 assert(child.entry_own.node.unwrap().tree_level == child.entry_own.path.len()) by {
471 assert(child.children[0] is Some);
472 let gc = child.children[0].unwrap();
473 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
474 child.entry_own, 0, Some(gc.value)));
475 assert(gc.value.path.len() == child.entry_own.node.unwrap().tree_level + 1);
476 assert(gc.value.path == child.entry_own.path.push_tail(0usize));
477 assert(child.entry_own.inv_base());
478 assert(child.entry_own.path.inv());
479 child.entry_own.path.push_tail_property(0usize);
480 assert(child.entry_own.path.push_tail(0usize).len() == child.entry_own.path.len() + 1);
481 };
482
483 assert(child.tree_level == child.entry_own.node.unwrap().tree_level);
484 assert(child.tree_level == INC_LEVELS - child.level() - 1);
485
486 assert(child.inv_children()) by {
487 assert forall |j: int| 0 <= j < child.children.len() && #[trigger] child.children[j] is Some
488 implies child.children[j].unwrap().inv() by {
489 assert(child.children[j] == child_node.children[j]);
490 old_cont.inv_children_unroll(old_cont.idx as int);
491 };
492 };
493 assert(child.inv_children_rel()) by {
494 assert forall |j: int| 0 <= j < NR_ENTRIES && #[trigger] child.children[j] is Some
495 implies {
496 &&& child.children[j].unwrap().value.parent_level == child.level()
497 &&& child.children[j].unwrap().level == child.tree_level + 1
498 &&& !child.children[j].unwrap().value.in_scope
499 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
500 child.entry_own, j, Some(child.children[j].unwrap().value))
501 &&& child.children[j].unwrap().value.path == child.path().push_tail(j as usize)
502 } by {
503 let gc = child.children[j].unwrap();
504 assert(child.children[j] == child_node.children[j]);
505 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
506 child.entry_own, j, Some(gc.value)));
507 child.inv_children_unroll(j);
508 assert(gc.inv());
509 };
510 };
511 assert(child.inv());
512
513 assert(new_owner.continuations[new_owner.level - 1].all_some()) by {
514 assert(new_owner.continuations[new_owner.level - 1] == child);
515 assert forall |j: int| 0 <= j < NR_ENTRIES implies child.children[j] is Some by {
516 if child.children[j] is None {
517 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
518 child.entry_own, j, None));
519 }
520 };
521 };
522
523 assert(modified_cont.all_but_index_some()) by {
524 assert(modified_cont.children[modified_cont.idx as int] is None);
525 assert forall |i: int| 0 <= i < modified_cont.idx implies
526 modified_cont.children[i] is Some by {
527 assert(modified_cont.children[i] == old_cont.children[i]);
528 };
529 assert forall |i: int| modified_cont.idx < i < NR_ENTRIES implies
530 modified_cont.children[i] is Some by {
531 assert(modified_cont.children[i] == old_cont.children[i]);
532 };
533 };
534
535 assert(forall|i: int| new_owner.level <= i < NR_LEVELS ==> {
536 (#[trigger] new_owner.continuations[i]).all_but_index_some()
537 }) by {
538 assert forall |i: int| new_owner.level <= i < NR_LEVELS implies
539 (#[trigger] new_owner.continuations[i]).all_but_index_some() by {
540 if i == self.level - 1 {
541 assert(new_owner.continuations[i] == modified_cont);
542 } else {
543 assert(new_owner.continuations[i] == self.continuations[i]);
545 }
546 };
547 };
548
549 assert(modified_cont.children.len() == NR_ENTRIES);
552 assert(0 <= modified_cont.idx < NR_ENTRIES);
553 assert(modified_cont.inv_children()) by {
554 assert forall |i: int| 0 <= i < modified_cont.children.len() && #[trigger] modified_cont.children[i] is Some
555 implies modified_cont.children[i].unwrap().inv() by {
556 assert(i != modified_cont.idx);
557 assert(modified_cont.children[i] == old_cont.children[i]);
558 old_cont.inv_children_unroll(i);
559 };
560 };
561 assert(modified_cont.inv_children_rel()) by {
562 assert forall |i: int| 0 <= i < NR_ENTRIES && #[trigger] modified_cont.children[i] is Some
563 implies {
564 &&& modified_cont.children[i].unwrap().value.parent_level == modified_cont.level()
565 &&& modified_cont.children[i].unwrap().level == modified_cont.tree_level + 1
566 &&& !modified_cont.children[i].unwrap().value.in_scope
567 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
568 modified_cont.entry_own, i, Some(modified_cont.children[i].unwrap().value))
569 &&& modified_cont.children[i].unwrap().value.path == modified_cont.path().push_tail(i as usize)
570 } by {
571 assert(i != modified_cont.idx);
572 assert(modified_cont.children[i] == old_cont.children[i]);
573 assert(old_cont.inv_children_rel());
574 };
575 };
576 assert(modified_cont.entry_own.is_node());
577 assert(modified_cont.entry_own.inv());
578 assert(modified_cont.entry_own.node.unwrap().relate_guard_perm(modified_cont.guard_perm));
579 assert(modified_cont.tree_level == INC_LEVELS - modified_cont.level() - 1);
580 assert(modified_cont.tree_level < INC_LEVELS - 1);
581 assert(modified_cont.path().len() == modified_cont.tree_level);
582 assert(modified_cont.inv());
583
584 assert(new_owner.level <= 4 ==> {
585 &&& new_owner.continuations.contains_key(3)
586 &&& new_owner.continuations[3].inv()
587 &&& new_owner.continuations[3].level() == 4
588 &&& new_owner.continuations[3].entry_own.parent_level == 5
589 &&& new_owner.va.index[3] == new_owner.continuations[3].idx
590 }) by {
591 if new_owner.level <= 4 {
592 if self.level == 4 {
593 assert(new_owner.continuations[3] == modified_cont);
594 } else {
595 assert(new_owner.continuations[3] == self.continuations[3]);
596 }
597 }
598 };
599
600 assert(new_owner.level <= 3 ==> {
602 &&& new_owner.continuations.contains_key(2)
603 &&& new_owner.continuations[2].inv()
604 &&& new_owner.continuations[2].level() == 3
605 &&& new_owner.continuations[2].entry_own.parent_level == 4
606 &&& new_owner.va.index[2] == new_owner.continuations[2].idx
607 &&& new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr() !=
608 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
609 &&& new_owner.continuations[2].path() == new_owner.continuations[3].path().push_tail(new_owner.continuations[3].idx as usize)
610 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
611 new_owner.continuations[3].entry_own, new_owner.continuations[3].idx as int,
612 Some(new_owner.continuations[2].entry_own))
613 }) by {
614 if new_owner.level <= 3 {
615 if self.level == 4 {
616 assert(self.va.index.contains_key(2));
617 assert(new_owner.continuations[2].guard_perm == guard_perm);
618 assert(new_owner.continuations[3] == modified_cont);
619 assert(modified_cont.guard_perm == old_cont.guard_perm);
620 assert(new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr() !=
622 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()) by {
623 assert(self.continuations[self.level - 1].guard_perm.value().inner.inner@.ptr.addr()
624 != guard_perm.value().inner.inner@.ptr.addr());
625 };
626 assert(new_owner.continuations[2].path() == new_owner.continuations[3].path().push_tail(new_owner.continuations[3].idx as usize)) by {
628 assert(modified_cont.path() == old_cont.path());
629 assert(modified_cont.idx == old_cont.idx);
630 old_cont.inv_children_rel_unroll(old_cont.idx as int);
631 };
632 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
634 new_owner.continuations[3].entry_own, new_owner.continuations[3].idx as int,
635 Some(new_owner.continuations[2].entry_own))) by {
636 old_cont.inv_children_rel_unroll(old_cont.idx as int);
637 };
638 } else {
639 }
641 }
642 };
643
644 assert(new_owner.level <= 2 ==> {
646 &&& new_owner.continuations.contains_key(1)
647 &&& new_owner.continuations[1].inv()
648 &&& new_owner.continuations[1].level() == 2
649 &&& new_owner.continuations[1].entry_own.parent_level == 3
650 &&& new_owner.va.index[1] == new_owner.continuations[1].idx
651 &&& new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
652 new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
653 &&& new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
654 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
655 &&& new_owner.continuations[1].path() == new_owner.continuations[2].path().push_tail(new_owner.continuations[2].idx as usize)
656 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
657 new_owner.continuations[2].entry_own, new_owner.continuations[2].idx as int,
658 Some(new_owner.continuations[1].entry_own))
659 }) by {
660 if new_owner.level <= 2 {
661 if self.level == 3 {
662 assert(self.va.index.contains_key(1));
663 assert(new_owner.continuations[1].guard_perm == guard_perm);
664 assert(new_owner.continuations[2] == modified_cont);
665 assert(modified_cont.guard_perm == old_cont.guard_perm);
666
667 assert(new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
668 new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr()) by {
669 assert(self.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
670 != guard_perm.value().inner.inner@.ptr.addr());
671 };
672 assert(new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
673 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()) by {
674 assert(self.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
675 != guard_perm.value().inner.inner@.ptr.addr());
676 };
677 assert(new_owner.continuations[1].path() == new_owner.continuations[2].path().push_tail(new_owner.continuations[2].idx as usize)) by {
679 assert(modified_cont.path() == old_cont.path());
680 assert(modified_cont.idx == old_cont.idx);
681 old_cont.inv_children_rel_unroll(old_cont.idx as int);
682 };
683 assert(old_cont.level() == 3);
685 assert(child.entry_own.parent_level == 3) by {
686 old_cont.inv_children_rel_unroll(old_cont.idx as int);
687 };
688 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
690 new_owner.continuations[2].entry_own, new_owner.continuations[2].idx as int,
691 Some(new_owner.continuations[1].entry_own))) by {
692 old_cont.inv_children_rel_unroll(old_cont.idx as int);
693 };
694 } else {
695 }
697 }
698 };
699
700 assert(new_owner.level == 1 ==> {
702 &&& new_owner.continuations.contains_key(0)
703 &&& new_owner.continuations[0].inv()
704 &&& new_owner.continuations[0].level() == 1
705 &&& new_owner.continuations[0].entry_own.parent_level == 2
706 &&& new_owner.va.index[0] == new_owner.continuations[0].idx
707 &&& new_owner.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
708 new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr()
709 &&& new_owner.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
710 new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
711 &&& new_owner.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
712 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
713 &&& new_owner.continuations[0].path() == new_owner.continuations[1].path().push_tail(new_owner.continuations[1].idx as usize)
714 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
715 new_owner.continuations[1].entry_own, new_owner.continuations[1].idx as int,
716 Some(new_owner.continuations[0].entry_own))
717 }) by {
718 if new_owner.level == 1 {
719 assert(new_owner.continuations[0].guard_perm == guard_perm);
721 assert(new_owner.continuations[1] == modified_cont);
722 assert(modified_cont.guard_perm == old_cont.guard_perm);
723
724 assert(self.continuations[1].guard_perm.value().inner.inner@.ptr.addr()
726 != guard_perm.value().inner.inner@.ptr.addr());
727 assert(self.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
728 != guard_perm.value().inner.inner@.ptr.addr());
729 assert(self.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
730 != guard_perm.value().inner.inner@.ptr.addr());
731
732 assert(old_cont.level() == 2);
735 assert(child.tree_level == INC_LEVELS - child.level() - 1);
740
741 assert(child.entry_own.parent_level == 2) by {
743 old_cont.inv_children_rel_unroll(old_cont.idx as int);
744 assert(child.entry_own.parent_level == old_cont.level());
745 };
746
747 assert(new_owner.va.index[0] == child.idx);
749
750 assert(child.path() == modified_cont.path().push_tail(modified_cont.idx as usize)) by {
752 assert(modified_cont.path() == old_cont.path());
753 assert(modified_cont.idx == old_cont.idx);
754 old_cont.inv_children_rel_unroll(old_cont.idx as int);
755 assert(child.entry_own.path == old_cont.path().push_tail(old_cont.idx as usize));
756 };
757
758 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
760 new_owner.continuations[1].entry_own, new_owner.continuations[1].idx as int,
761 Some(new_owner.continuations[0].entry_own))) by {
762 old_cont.inv_children_rel_unroll(old_cont.idx as int);
763 };
764 }
765 };
766
767 }
768
769 pub proof fn push_level_owner_preserves_invs(self, guard_perm: GuardPerm<'rcu, C>, regions: MetaRegionOwners, guards: Guards<'rcu, C>)
770 requires
771 self.inv(),
772 self.level > 1,
773 !self.popped_too_high,
774 self.level < self.guard_level,
775 self.only_current_locked(guards),
776 self.nodes_locked(guards),
777 self.metaregion_sound(regions),
778 self.cur_entry_owner().is_node(),
780 self.cur_entry_owner().node.unwrap().relate_guard_perm(guard_perm),
782 guards.lock_held(guard_perm.value().inner.inner@.ptr.addr()),
784 ensures
785 self.push_level_owner_spec(guard_perm).inv(),
786 self.push_level_owner_spec(guard_perm).children_not_locked(guards),
787 self.push_level_owner_spec(guard_perm).nodes_locked(guards),
788 self.push_level_owner_spec(guard_perm).metaregion_sound(regions),
789 {
790 reveal(CursorContinuation::inv_children);
791 let new_owner = self.push_level_owner_spec(guard_perm);
792 let old_cont = self.continuations[self.level - 1];
793 old_cont.inv_children_unroll_all();
794 let (child_cont, modified_cont) = old_cont.make_cont_spec(self.va.index[self.level - 2] as usize, guard_perm);
795
796 let cur_entry = self.cur_entry_owner();
797 let cur_entry_addr = cur_entry.node.unwrap().meta_perm.addr();
798 let cur_entry_path = old_cont.path().push_tail(old_cont.idx as usize);
799 self.cont_entries_metaregion(regions);
800
801 assert forall |i: int|
802 #![trigger self.continuations[i]]
803 self.level - 1 <= i < NR_LEVELS implies
804 self.continuations[i].guard_perm.value().inner.inner@.ptr.addr()
805 != guard_perm.value().inner.inner@.ptr.addr() by {
806 let cont_i = self.continuations[i];
807
808 if cont_i.guard_perm.value().inner.inner@.ptr.addr()
809 == guard_perm.value().inner.inner@.ptr.addr()
810 {
811 let addr = cont_i.entry_own.node.unwrap().meta_perm.addr();
812 assert(addr == cur_entry.node.unwrap().meta_perm.addr());
813 let idx = frame_to_index(meta_to_frame(addr));
814 assert(regions.slot_owners[idx].paths_in_pt == set![cont_i.path()]);
815 assert(regions.slot_owners[idx].paths_in_pt == set![cur_entry_path]);
816 assert(set![cont_i.path()].contains(cur_entry_path));
817
818 assert(cur_entry_path.len() == old_cont.tree_level + 1) by {
819 old_cont.inv_children_rel_unroll(old_cont.idx as int);
820 old_cont.entry_own.path.push_tail_property(old_cont.idx as usize);
821 };
822 assert(cont_i.tree_level <= old_cont.tree_level) by {
823 if self.level as int == 1 {
824 assert(old_cont.level() == 1);
825 } else if self.level as int == 2 {
826 assert(old_cont.level() == 2);
827 } else if self.level as int == 3 {
828 assert(old_cont.level() == 3);
829 } else {
830 assert(old_cont.level() == 4);
831 }
832 };
833 assert(false);
834 }
835 };
836 self.push_level_owner_preserves_inv(guard_perm);
837
838 let excepted_idx = frame_to_index(meta_to_frame(cur_entry_addr));
839 assert(regions.slot_owners[excepted_idx].paths_in_pt == set![cur_entry_path]) by {
840 old_cont.inv_children_rel_unroll(old_cont.idx as int);
841 };
842
843 let f = PageTableOwner::<C>::metaregion_sound_pred(regions);
844 let g_except = CursorOwner::<'rcu, C>::node_unlocked_except(guards, cur_entry_addr);
845 let h = CursorOwner::<'rcu, C>::node_unlocked(guards);
846
847 assert forall |i: int|
851 #![trigger new_owner.continuations[i]]
852 new_owner.level - 1 <= i < NR_LEVELS implies
853 new_owner.continuations[i].map_children(h) by {
854
855 if i == self.level - 2 {
856 assert(new_owner.continuations[i] == child_cont);
857 assert forall |j: int|
858 #![trigger child_cont.children[j]]
859 0 <= j < child_cont.children.len() && child_cont.children[j] is Some implies
860 child_cont.children[j].unwrap().tree_predicate_map(
861 child_cont.path().push_tail(j as usize), h) by {
862 let gc = child_cont.children[j].unwrap();
863 let gc_path = child_cont.path().push_tail(j as usize);
864 child_cont.inv_children_unroll(j);
865 child_cont.inv_children_rel_unroll(j);
866 child_cont.path().push_tail_property(j as usize);
867
868 let child_subtree = old_cont.children[old_cont.idx as int].unwrap();
869 child_subtree.map_unroll_once(cur_entry_path, f, j);
870 child_subtree.map_unroll_once(cur_entry_path, g_except, j);
871
872 assert(child_cont.path() == cur_entry_path);
873 assert(gc_path == cur_entry_path.push_tail(j as usize));
874 assert(cur_entry_path.len() < gc_path.len());
875 child_cont.pt_inv_children_unroll(j);
876 subtree_unlock_upgrade(gc, gc_path, guards, regions,
877 cur_entry_addr, cur_entry_path);
878 };
879 } else if i == self.level - 1 {
880 assert(new_owner.continuations[i] == modified_cont);
881 assert(modified_cont.path() == old_cont.path());
882 assert forall |j: int|
883 #![trigger modified_cont.children[j]]
884 0 <= j < modified_cont.children.len() && modified_cont.children[j] is Some implies
885 modified_cont.children[j].unwrap().tree_predicate_map(
886 modified_cont.path().push_tail(j as usize), h) by {
887 assert(j != old_cont.idx as int);
888 assert(modified_cont.children[j] == old_cont.children[j]);
889 let sibling = old_cont.children[j].unwrap();
890 let sibling_path = old_cont.path().push_tail(j as usize);
891 old_cont.inv_children_unroll(j);
892 old_cont.inv_children_rel_unroll(j);
893 old_cont.path().push_tail_property(j as usize);
894
895 push_tail_different_indices_different_paths(old_cont.path(), j as usize, old_cont.idx);
896 old_cont.inv_children_rel_unroll(old_cont.idx as int);
899 old_cont.path().push_tail_property(old_cont.idx as usize);
900 assert(cur_entry_path.len() <= sibling_path.len());
901 old_cont.pt_inv_children_unroll(j);
902 subtree_unlock_upgrade(sibling, sibling_path, guards, regions,
903 cur_entry_addr, cur_entry_path);
904 };
905 } else {
906 assert(new_owner.continuations[i] == self.continuations[i]);
907 let cont_i = self.continuations[i];
908
909 old_cont.entry_own.path.push_tail_property(old_cont.idx as usize);
913 if i == self.level as int {
914 assert(old_cont.path() == cont_i.path().push_tail(cont_i.idx as usize));
915 cont_i.entry_own.path.push_tail_property(cont_i.idx as usize);
916 } else if i == self.level as int + 1 {
917 let cont_sl = self.continuations[self.level as int];
918 assert(old_cont.path() == cont_sl.path().push_tail(cont_sl.idx as usize));
919 assert(cont_sl.path() == cont_i.path().push_tail(cont_i.idx as usize));
920 cont_i.entry_own.path.push_tail_property(cont_i.idx as usize);
921 cont_i.path().push_tail(cont_i.idx as usize).push_tail_property(cont_sl.idx as usize);
922 } else {
923 let cont_sl = self.continuations[self.level as int];
924 let cont_sl1 = self.continuations[self.level as int + 1];
925 assert(old_cont.path() == cont_sl.path().push_tail(cont_sl.idx as usize));
926 assert(cont_sl.path() == cont_sl1.path().push_tail(cont_sl1.idx as usize));
927 assert(cont_sl1.path() == cont_i.path().push_tail(cont_i.idx as usize));
928 cont_i.entry_own.path.push_tail_property(cont_i.idx as usize);
929 cont_i.path().push_tail(cont_i.idx as usize).push_tail_property(cont_sl1.idx as usize);
930 cont_sl1.path().push_tail(cont_sl1.idx as usize).push_tail_property(cont_sl.idx as usize);
931 }
932 assert(cur_entry_path.index(cont_i.tree_level as int) == cont_i.idx as usize);
933
934 assert forall |j: int|
935 #![trigger cont_i.children[j]]
936 0 <= j < cont_i.children.len() && cont_i.children[j] is Some implies
937 cont_i.children[j].unwrap().tree_predicate_map(
938 cont_i.path().push_tail(j as usize), h) by {
939 let child_sub = cont_i.children[j].unwrap();
940 let child_path = cont_i.path().push_tail(j as usize);
941 cont_i.inv_children_unroll(j);
942 cont_i.inv_children_rel_unroll(j);
943 cont_i.path().push_tail_property(j as usize);
944
945 assert(child_path.index(cont_i.tree_level as int) == j as usize);
946 assert(j != cont_i.idx as int);
947 assert(child_path.index(cont_i.tree_level as int)
948 != cur_entry_path.index(cont_i.tree_level as int));
949 assert(cont_i.tree_level < child_path.len());
950 cont_i.pt_inv_children_unroll(j);
951 subtree_unlock_upgrade(child_sub, child_path, guards, regions,
952 cur_entry_addr, cur_entry_path);
953 };
954 }
955 };
956 assert(new_owner.children_not_locked(guards));
957 assert forall |i: int|
958 #![trigger new_owner.continuations[i]]
959 new_owner.level - 1 <= i < NR_LEVELS implies
960 new_owner.continuations[i].node_locked(guards) by {
961
962 if i == self.level - 2 {
963 assert(new_owner.continuations[i] == child_cont);
964 assert(child_cont.guard_perm == guard_perm);
965 } else if i == self.level - 1 {
966 assert(new_owner.continuations[i] == modified_cont);
967 assert(modified_cont.guard_perm == old_cont.guard_perm);
968 } else {
969 assert(new_owner.continuations[i] == self.continuations[i]);
970 }
971 };
972 assert(new_owner.nodes_locked(guards));
973
974 let f = PageTableOwner::<C>::metaregion_sound_pred(regions);
975 let child_subtree = child_cont.as_subtree();
976
977 assert(child_subtree.inv_children()) by {
978 assert forall |j: int| 0 <= j < NR_ENTRIES implies
979 match #[trigger] child_subtree.children[j] {
980 Some(ch) => {
981 &&& ch.level == child_subtree.level + 1
982 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(child_subtree.value, j, Some(ch.value))
983 },
984 None => <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(child_subtree.value, j, None),
985 }
986 by {
987 assert(child_cont.children[j] is Some);
988 let ch = child_cont.children[j].unwrap();
989 assert(ch.level == child_cont.tree_level + 1);
990 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
991 child_cont.entry_own, j, Some(ch.value)));
992 };
993 };
994 assert forall |j: int| 0 <= j < NR_ENTRIES implies
995 match #[trigger] child_subtree.children[j] {
996 Some(ch) => ch.inv(),
997 None => true,
998 }
999 by {
1000 child_cont.inv_children_unroll(j);
1001 };
1002 assert(child_subtree.inv()) by {
1003 assert(child_subtree.inv_node());
1004 };
1005
1006 assert(child_subtree.tree_predicate_map(child_cont.path(), f)) by {
1008 assert(f(child_subtree.value, child_cont.path()));
1009 assert forall |j: int| 0 <= j < child_subtree.children.len() implies
1010 match #[trigger] child_subtree.children[j] {
1011 Some(ch) => ch.tree_predicate_map(child_cont.path().push_tail(j as usize), f),
1012 None => true,
1013 }
1014 by { child_subtree.map_unroll_once(child_cont.path(), f, j); };
1015 };
1016
1017 assert(modified_cont.map_children(f)) by {
1019 assert forall |j: int|
1020 0 <= j < modified_cont.children.len() && #[trigger] modified_cont.children[j] is Some implies
1021 modified_cont.children[j].unwrap().tree_predicate_map(modified_cont.path().push_tail(j as usize), f) by {
1022 assert(j != old_cont.idx as int);
1023 assert(modified_cont.children[j] == old_cont.children[j]);
1024 };
1025 };
1026
1027 assert(new_owner.metaregion_sound(regions)) by {
1028 assert forall |i: int| #![auto]
1029 new_owner.level - 1 <= i < NR_LEVELS implies {
1030 &&& f(new_owner.continuations[i].entry_own, new_owner.continuations[i].path())
1031 &&& new_owner.continuations[i].map_children(f)
1032 } by {
1033 if i == self.level - 2 {
1034 assert(new_owner.continuations[i] == child_cont);
1035 } else if i == self.level - 1 {
1036 assert(new_owner.continuations[i] == modified_cont);
1037 assert(modified_cont.entry_own == old_cont.entry_own);
1038 assert(modified_cont.path() == old_cont.path());
1039 } else {
1040 assert(new_owner.continuations[i] == self.continuations[i]);
1041 }
1042 };
1043 };
1044 }
1045
1046 #[verifier::returns(proof)]
1047 pub proof fn push_level_owner(tracked &mut self, tracked guard_perm: Tracked<GuardPerm<'rcu, C>>)
1048 requires
1049 old(self).inv(),
1050 old(self).level > 1,
1051 ensures
1052 *final(self) == old(self).push_level_owner_spec(guard_perm@),
1053 {
1054 assert(self.va.index.contains_key(self.level - 2));
1055
1056 let ghost self0 = *self;
1057 let tracked mut cont = self.continuations.tracked_remove(self.level - 1);
1058 let ghost cont0 = cont;
1059 let tracked child = cont.make_cont(self.va.index[self.level - 2] as usize, guard_perm);
1060
1061 assert((child, cont) == cont0.make_cont_spec(self.va.index[self.level - 2] as usize, guard_perm@));
1062
1063 self.continuations.tracked_insert(self.level - 1, cont);
1064 self.continuations.tracked_insert(self.level - 2, child);
1065
1066 assert(self.continuations == self0.continuations.insert(self.level - 1, cont).insert(self.level - 2, child));
1067
1068 self.popped_too_high = false;
1069
1070 self.level = (self.level - 1) as u8;
1071 }
1072
1073 pub open spec fn pop_level_owner_spec(self) -> (Self, GuardPerm<'rcu, C>)
1074 {
1075 let child = self.continuations[self.level - 1];
1076 let cont = self.continuations[self.level as int];
1077 let (new_cont, guard_perm) = cont.restore_spec(child);
1078 let new_continuations = self.continuations.insert(self.level as int, new_cont);
1079 let new_continuations = new_continuations.remove(self.level - 1);
1080 let new_level = (self.level + 1) as u8;
1081 let popped_too_high = if new_level >= self.guard_level { true } else { false };
1082 (Self {
1083 continuations: new_continuations,
1084 level: new_level,
1085 popped_too_high: popped_too_high,
1086 ..self
1087 }, guard_perm)
1088 }
1089
1090 pub proof fn pop_level_owner_preserves_inv(self)
1091 requires
1092 self.inv(),
1093 self.level < NR_LEVELS,
1094 self.in_locked_range(),
1095 ensures
1096 self.pop_level_owner_spec().0.inv(),
1097 {
1098 let child = self.continuations[self.level - 1];
1099 assert(child.inv());
1100 assert(child.all_some());
1101 let cont = self.continuations[self.level as int];
1102 assert(cont.inv());
1103 let (new_cont, _) = cont.restore_spec(child);
1104 let new_owner = self.pop_level_owner_spec().0;
1105
1106 let child_node = OwnerSubtree {
1107 value: child.entry_own,
1108 level: child.tree_level,
1109 children: child.children,
1110 };
1111
1112 let nc = self.continuations.insert(self.level as int, new_cont).remove(self.level - 1);
1113 assert(new_owner.continuations == nc);
1114 if self.level < 3 {
1115 assert(nc[3] == self.continuations[3]);
1116 }
1117 if self.level < 2 {
1118 assert(nc[2] == self.continuations[2]);
1119 }
1120 assert(new_cont.all_some()) by {
1121 assert forall |i: int| 0 <= i < NR_ENTRIES implies new_cont.children[i] is Some by {
1122 if i == cont.idx as int {
1123 assert(new_cont.children[i] == Some(child_node));
1124 } else {
1125 assert(new_cont.children[i] == cont.children[i]);
1126 }
1127 };
1128 };
1129
1130 assert forall |i: int| new_owner.level <= i < NR_LEVELS implies
1131 (#[trigger] new_owner.continuations[i]).all_but_index_some() by {
1132 if i == self.level as int {
1133 assert(new_owner.continuations[i] == new_cont);
1134 assert(new_cont.all_some());
1135 } else {
1136 assert(new_owner.continuations[i] == self.continuations[i]);
1137 }
1138 };
1139
1140 assert(child.path() == cont.path().push_tail(cont.idx as usize));
1141 assert(child.entry_own.path == new_cont.path().push_tail(cont.idx as usize));
1142 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1143 new_cont.entry_own, cont.idx as int, Some(child.entry_own)));
1144
1145 assert(child_node.inv_children()) by {
1146 assert forall |j: int| 0 <= j < NR_ENTRIES implies
1147 match #[trigger] child_node.children[j] {
1148 Some(ch) => {
1149 &&& ch.level == child_node.level + 1
1150 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(child_node.value, j, Some(ch.value))
1151 },
1152 None => <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(child_node.value, j, None),
1153 }
1154 by {
1155 assert(child.children[j] is Some);
1156 let ch = child.children[j].unwrap();
1157 assert(ch.level == child.tree_level + 1);
1158 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1159 child.entry_own, j, Some(ch.value)));
1160 };
1161 };
1162 assert forall |j: int| 0 <= j < NR_ENTRIES implies
1163 match #[trigger] child_node.children[j] {
1164 Some(ch) => ch.inv(),
1165 None => true,
1166 }
1167 by {
1168 child.inv_children_unroll(j);
1169 };
1170 assert(child_node.inv()) by {
1171 assert(child_node.inv_node());
1172 };
1173
1174 assert(new_cont.inv_children()) by {
1175 assert forall |i: int| 0 <= i < new_cont.children.len() && #[trigger] new_cont.children[i] is Some
1176 implies new_cont.children[i].unwrap().inv() by {
1177 if i == cont.idx as int {
1178 assert(new_cont.children[i].unwrap() == child_node);
1179 } else {
1180 assert(new_cont.children[i] == cont.children[i]);
1181 cont.inv_children_unroll(i);
1182 }
1183 };
1184 };
1185
1186 assert(new_cont.inv_children_rel()) by {
1187 assert forall |i: int| 0 <= i < NR_ENTRIES && #[trigger] new_cont.children[i] is Some
1188 implies {
1189 &&& new_cont.children[i].unwrap().value.parent_level == new_cont.level()
1190 &&& new_cont.children[i].unwrap().level == new_cont.tree_level + 1
1191 &&& !new_cont.children[i].unwrap().value.in_scope
1192 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1193 new_cont.entry_own, i, Some(new_cont.children[i].unwrap().value))
1194 &&& new_cont.children[i].unwrap().value.path == new_cont.path().push_tail(i as usize)
1195 } by {
1196 if i == cont.idx as int {
1197 assert(new_cont.children[i].unwrap() == child_node);
1198 assert(!child.entry_own.in_scope);
1199 } else {
1200 assert(new_cont.children[i] == cont.children[i]);
1201 cont.inv_children_rel_unroll(i);
1202 }
1203 };
1204 };
1205
1206 assert(new_cont.inv()) by {
1207 assert(new_cont.tree_level == INC_LEVELS - new_cont.level() - 1);
1208 assert(new_cont.path().len() == new_cont.tree_level);
1209 };
1210
1211 assert(new_owner.level <= 4 ==> {
1212 &&& new_owner.continuations.contains_key(3)
1213 &&& new_owner.continuations[3].inv()
1214 &&& new_owner.continuations[3].level() == 4
1215 &&& new_owner.continuations[3].entry_own.parent_level == 5
1216 &&& new_owner.va.index[3] == new_owner.continuations[3].idx
1217 }) by {
1218 if self.level as int == 3 {
1219 assert(new_owner.continuations[3] == new_cont);
1220 } else {
1221 assert(new_owner.continuations[3] == self.continuations[3]);
1222 }
1223 };
1224
1225 assert(new_owner.level <= 3 ==> {
1227 &&& new_owner.continuations.contains_key(2)
1228 &&& new_owner.continuations[2].inv()
1229 &&& new_owner.continuations[2].level() == 3
1230 &&& new_owner.continuations[2].entry_own.parent_level == 4
1231 &&& new_owner.va.index[2] == new_owner.continuations[2].idx
1232 &&& new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr() !=
1233 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
1234 &&& new_owner.continuations[2].path() == new_owner.continuations[3].path().push_tail(new_owner.continuations[3].idx as usize)
1235 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1236 new_owner.continuations[3].entry_own, new_owner.continuations[3].idx as int,
1237 Some(new_owner.continuations[2].entry_own))
1238 }) by {
1239 if new_owner.level <= 3 {
1240 if self.level as int == 2 {
1241 assert(new_owner.continuations[2] == new_cont);
1242 } else {
1243 assert(new_owner.continuations[2] == self.continuations[2]);
1244 }
1245 }
1246 };
1247
1248 assert(new_owner.level <= 2 ==> {
1250 &&& new_owner.continuations.contains_key(1)
1251 &&& new_owner.continuations[1].inv()
1252 &&& new_owner.continuations[1].level() == 2
1253 &&& new_owner.continuations[1].entry_own.parent_level == 3
1254 &&& new_owner.va.index[1] == new_owner.continuations[1].idx
1255 &&& new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
1256 new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
1257 &&& new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
1258 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
1259 &&& new_owner.continuations[1].path() == new_owner.continuations[2].path().push_tail(new_owner.continuations[2].idx as usize)
1260 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1261 new_owner.continuations[2].entry_own, new_owner.continuations[2].idx as int,
1262 Some(new_owner.continuations[1].entry_own))
1263 }) by {
1264 if new_owner.level <= 2 {
1265 assert(new_owner.continuations[1] == new_cont);
1266 }
1267 };
1268 }
1269
1270 pub proof fn pop_level_owner_preserves_invs(self, guards: Guards<'rcu, C>, regions: MetaRegionOwners)
1271 requires
1272 self.inv(),
1273 self.level < NR_LEVELS,
1274 self.in_locked_range(),
1275 self.children_not_locked(guards),
1276 self.nodes_locked(guards),
1277 self.metaregion_sound(regions),
1278 ensures
1279 self.pop_level_owner_spec().0.inv(),
1280 self.pop_level_owner_spec().0.only_current_locked(guards),
1281 self.pop_level_owner_spec().0.nodes_locked(guards),
1282 self.pop_level_owner_spec().0.metaregion_sound(regions),
1283 {
1284 let new_owner = self.pop_level_owner_spec().0;
1285 let child = self.continuations[self.level - 1];
1286 let cont = self.continuations[self.level as int];
1287 let (new_cont, _guard_perm) = cont.restore_spec(child);
1288 let child_node = OwnerSubtree {
1289 value: child.entry_own,
1290 level: child.tree_level,
1291 children: child.children,
1292 };
1293
1294 self.pop_level_owner_preserves_inv();
1295
1296 assert(new_owner.va == self.va);
1297
1298 assert(new_owner.nodes_locked(guards)) by {
1299 assert forall |i: int|
1300 #![trigger new_owner.continuations[i]]
1301 new_owner.level - 1 <= i < NR_LEVELS implies
1302 new_owner.continuations[i].node_locked(guards) by {
1303 if i == self.level as int {
1304 assert(new_owner.continuations[i] == new_cont);
1305 assert(new_cont.guard_perm == cont.guard_perm);
1306 } else {
1307 assert(new_owner.continuations[i] == self.continuations[i]);
1308 }
1309 };
1310 };
1311
1312 let child_addr = child.entry_own.node.unwrap().meta_perm.addr();
1313 let child_subtree = child.as_subtree();
1314
1315 assert forall |j: int| 0 <= j < NR_ENTRIES implies
1316 match #[trigger] child_subtree.children[j] {
1317 Some(ch) => ch.inv(),
1318 None => true,
1319 }
1320 by { child.inv_children_unroll(j); };
1321 assert(child_subtree.inv());
1322
1323 assert(OwnerSubtree::<C>::implies(
1324 CursorOwner::<'rcu, C>::node_unlocked(guards),
1325 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr),
1326 ));
1327 self.map_children_implies(
1328 CursorOwner::<'rcu, C>::node_unlocked(guards),
1329 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr),
1330 );
1331
1332 assert(new_owner.only_current_locked(guards)) by {
1333 assert forall |i: int|
1334 #![trigger new_owner.continuations[i]]
1335 new_owner.level - 1 <= i < NR_LEVELS implies
1336 new_owner.continuations[i].map_children(
1337 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr)) by {
1338 if i > self.level as int {
1339 assert(new_owner.continuations[i] == self.continuations[i]);
1340 } else {
1341 assert(new_owner.continuations[i] == new_cont);
1342 new_cont.map_children_lift_skip_idx(
1343 cont,
1344 cont.idx as int,
1345 CursorOwner::<'rcu, C>::node_unlocked(guards),
1346 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr),
1347 );
1348 }
1349 };
1350 };
1351
1352 let f = PageTableOwner::<C>::metaregion_sound_pred(regions);
1353 self.cont_entries_metaregion(regions);
1354
1355 assert(new_owner.metaregion_sound(regions)) by {
1356 assert forall |i: int| #![auto]
1357 new_owner.level - 1 <= i < NR_LEVELS implies
1358 new_owner.continuations[i].map_children(f)
1359 by {
1360 if i > self.level as int {
1361 } else {
1362 new_cont.map_children_lift_skip_idx(cont, cont.idx as int, f, f);
1363 }
1364 };
1365 };
1366 }
1367
1368 pub proof fn set_va_preserves_inv(self, new_va: AbstractVaddr)
1374 requires
1375 self.inv(),
1376 !self.popped_too_high,
1377 self.level < self.guard_level,
1378 new_va.inv(),
1379 new_va.offset == 0,
1380 new_va.leading_bits == self.prefix.leading_bits,
1381 forall |i: int| #![auto] self.level - 1 <= i < NR_LEVELS ==> new_va.index[i] == self.va.index[i],
1382 forall |i: int| #![auto] self.guard_level - 1 <= i < NR_LEVELS ==> new_va.index[i] == self.prefix.index[i],
1383 ensures
1384 self.set_va_spec(new_va).inv(),
1385 {
1386 let r = self.set_va_spec(new_va);
1387
1388 assert(r.in_locked_range()) by {
1389 let gl = self.guard_level;
1390 if gl >= 1 && gl <= NR_LEVELS {
1391 r.va.align_down_to_vaddr_eq_if_upper_indices_eq(r.prefix, gl as int);
1392 r.va.align_down_concrete(gl as int);
1393 r.prefix.align_down_concrete(gl as int);
1394 r.prefix.align_diff(gl as int);
1395 r.prefix.align_up_concrete(gl as int);
1396 AbstractVaddr::from_vaddr_to_vaddr_roundtrip(
1397 nat_align_down(r.va.to_vaddr() as nat, page_size(gl as PagingLevel) as nat) as Vaddr);
1398 AbstractVaddr::from_vaddr_to_vaddr_roundtrip(
1399 nat_align_down(r.prefix.to_vaddr() as nat, page_size(gl as PagingLevel) as nat) as Vaddr);
1400 AbstractVaddr::from_vaddr_to_vaddr_roundtrip(
1401 nat_align_up(r.prefix.to_vaddr() as nat, page_size(gl as PagingLevel) as nat) as Vaddr);
1402 lemma_page_size_ge_page_size(gl as PagingLevel);
1403 lemma_nat_align_down_sound(r.va.to_vaddr() as nat, page_size(gl as PagingLevel) as nat);
1404 r.prefix.align_down_shape(gl as int);
1405 r.prefix.align_down(gl as int).reflect_prop(
1406 nat_align_down(r.prefix.to_vaddr() as nat, page_size(gl as PagingLevel) as nat) as Vaddr);
1407 r.prefix.align_up(gl as int).reflect_prop(
1408 nat_align_up(r.prefix.to_vaddr() as nat, page_size(gl as PagingLevel) as nat) as Vaddr);
1409 }
1410 };
1411
1412 assert(r.continuations[r.level - 1].all_some());
1413 assert(r.level <= 4 ==> {
1414 &&& r.continuations.contains_key(3)
1415 &&& r.continuations[3].inv()
1416 &&& r.continuations[3].level() == 4
1417 &&& r.continuations[3].entry_own.parent_level == 5
1418 &&& r.va.index[3] == r.continuations[3].idx
1419 });
1420
1421 assert(r.level <= 3 ==> {
1422 &&& r.continuations.contains_key(2)
1423 &&& r.continuations[2].inv()
1424 &&& r.continuations[2].level() == 3
1425 &&& r.continuations[2].entry_own.parent_level == 4
1426 &&& r.va.index[2] == r.continuations[2].idx
1427 &&& r.continuations[2].guard_perm.value().inner.inner@.ptr.addr() !=
1428 r.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
1429 &&& r.continuations[2].path() == r.continuations[3].path().push_tail(r.continuations[3].idx as usize)
1430 });
1431
1432 assert(r.level <= 2 ==> {
1433 &&& r.continuations.contains_key(1)
1434 &&& r.continuations[1].inv()
1435 &&& r.continuations[1].level() == 2
1436 &&& r.continuations[1].entry_own.parent_level == 3
1437 &&& r.va.index[1] == r.continuations[1].idx
1438 &&& r.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
1439 r.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
1440 &&& r.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
1441 r.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
1442 &&& r.continuations[1].path() == r.continuations[2].path().push_tail(r.continuations[2].idx as usize)
1443 });
1444
1445 assert(r.level == 1 ==> {
1446 &&& r.continuations.contains_key(0)
1447 &&& r.continuations[0].inv()
1448 &&& r.continuations[0].level() == 1
1449 &&& r.continuations[0].entry_own.parent_level == 2
1450 &&& r.va.index[0] == r.continuations[0].idx
1451 &&& r.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
1452 r.continuations[1].guard_perm.value().inner.inner@.ptr.addr()
1453 &&& r.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
1454 r.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
1455 &&& r.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
1456 r.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
1457 &&& r.continuations[0].path() == r.continuations[1].path().push_tail(r.continuations[1].idx as usize)
1458 });
1459 }
1460
1461 #[verifier::returns(proof)]
1462 pub proof fn pop_level_owner(tracked &mut self) -> (tracked guard_perm: GuardPerm<'rcu, C>)
1463 requires
1464 old(self).inv(),
1465 old(self).level < NR_LEVELS,
1466 ensures
1467 *final(self) == old(self).pop_level_owner_spec().0,
1468 guard_perm == old(self).pop_level_owner_spec().1,
1469 {
1470 let ghost self0 = *self;
1471 let tracked mut parent = self.continuations.tracked_remove(self.level as int);
1472 let tracked child = self.continuations.tracked_remove(self.level - 1);
1473
1474 let tracked guard_perm = parent.restore(child);
1475
1476 self.continuations.tracked_insert(self.level as int, parent);
1477
1478 assert(self.continuations == self0.continuations.insert(self.level as int, parent).remove(self.level - 1));
1479
1480 self.level = (self.level + 1) as u8;
1481
1482 if self.level >= self.guard_level {
1483 self.popped_too_high = true;
1484 }
1485
1486 guard_perm
1487 }
1488
1489 pub open spec fn move_forward_owner_spec(self) -> Self
1490 recommends
1491 self.inv(),
1492 self.level < NR_LEVELS,
1493 self.in_locked_range(),
1494 decreases NR_LEVELS - self.level when self.level <= NR_LEVELS
1495 {
1496 if self.index() + 1 < NR_ENTRIES {
1497 self.inc_index().zero_below_level()
1502 } else if self.level < NR_LEVELS {
1503 self.pop_level_owner_spec().0.move_forward_owner_spec()
1504 } else {
1505 Self {
1507 popped_too_high: false,
1508 ..self
1509 }
1510 }
1511 }
1512
1513 pub proof fn move_forward_increases_va(self)
1514 requires
1515 self.inv(),
1516 self.level <= NR_LEVELS,
1517 self.in_locked_range(),
1518 !self.popped_too_high,
1519 ensures
1520 self.move_forward_owner_spec().va.to_vaddr() > self.va.to_vaddr(),
1521 decreases NR_LEVELS - self.level
1522 {
1523 self.in_locked_range_level_lt_guard_level();
1524 assert(self.level < NR_LEVELS);
1525 if self.index() + 1 < NR_ENTRIES {
1526 self.inc_and_zero_increases_va();
1527 } else if self.level + 1 < self.guard_level {
1528 self.pop_level_owner_preserves_inv();
1529 self.pop_level_owner_spec().0.move_forward_increases_va();
1530 } else {
1531 assert(self.guard_level == self.level + 1);
1532 assert(self.va.index[self.level as int] == 0);
1533 self.pop_level_owner_preserves_inv();
1534 let popped = self.pop_level_owner_spec().0;
1535 assert(self.move_forward_owner_spec() == popped.move_forward_owner_spec());
1536 assert(popped.move_forward_owner_spec() == popped.inc_index().zero_below_level());
1537 popped.inc_and_zero_increases_va();
1538 }
1539 }
1540
1541 pub proof fn move_forward_not_popped_too_high(self)
1542 requires
1543 self.inv(),
1544 self.level <= NR_LEVELS,
1545 self.in_locked_range(),
1546 ensures
1547 !self.move_forward_owner_spec().popped_too_high,
1548 decreases NR_LEVELS - self.level,
1549 {
1550 if self.index() + 1 < NR_ENTRIES {
1551 self.inc_index().zero_preserves_all_but_va();
1552 } else if self.level < NR_LEVELS {
1553 self.pop_level_owner_preserves_inv();
1554 self.pop_level_owner_spec().0.move_forward_not_popped_too_high();
1555 }
1556 }
1557
1558 pub proof fn move_forward_owner_decreases_steps(self)
1559 requires
1560 self.inv(),
1561 self.level <= NR_LEVELS,
1562 self.in_locked_range(),
1563 !self.popped_too_high,
1564 ensures
1565 self.move_forward_owner_spec().max_steps() < self.max_steps()
1566 decreases NR_LEVELS - self.level,
1567 {
1568 if self.index() + 1 < NR_ENTRIES {
1569 let inc = self.inc_index();
1570 inc.zero_preserves_all_but_va();
1571 Self::max_steps_subtree_positive(self.level as usize);
1572 if self.level < NR_LEVELS {
1573 inc.zero_below_level().max_steps_partial_eq(self, (self.level + 1) as usize);
1574 }
1575 vstd::arithmetic::mul::lemma_mul_is_distributive_add(
1576 Self::max_steps_subtree(self.level as usize) as int,
1577 (NR_ENTRIES - self.index() - 1) as int, 1);
1578 if self.level as usize == NR_LEVELS {
1579 self.in_locked_range_level_lt_nr_levels();
1580 }
1581 } else if self.level < NR_LEVELS {
1582 self.in_locked_range_level_lt_guard_level();
1583 self.pop_level_owner_preserves_inv();
1584 let popped = self.pop_level_owner_spec().0;
1585 popped.max_steps_partial_eq(self, (self.level + 1) as usize);
1586 Self::max_steps_subtree_positive(self.level as usize);
1587 Self::max_steps_subtree_positive((self.level + 1) as usize);
1588 if !popped.popped_too_high {
1589 popped.move_forward_owner_decreases_steps();
1590 } else {
1591 assert(popped.level == self.level + 1);
1595 assert(popped.level == self.guard_level);
1596 assert(popped.guard_level == self.guard_level);
1597 assert(self.va.index[self.guard_level - 1] == 0);
1601 assert(popped.va == self.va);
1602 assert(popped.continuations[popped.level - 1].idx == 0);
1603 assert(popped.index() == 0);
1604 let inc = popped.inc_index();
1607 let q = inc.zero_below_level();
1608 assert(popped.move_forward_owner_spec() == q);
1609 inc.zero_preserves_all_but_va();
1610 let lp1 = (self.level + 1) as usize;
1614 let lp2 = (self.level + 2) as usize;
1615 assert(self.va.index[self.level as int] == 0);
1617 assert(self.continuations[self.level as int].idx == 0);
1618 if (self.level + 1) < NR_LEVELS {
1621 q.max_steps_partial_eq(self, lp2);
1622 }
1623 assert(self.continuations[self.level - 1].idx + 1 == NR_ENTRIES);
1626 assert(q.continuations[self.level as int].idx == 1);
1628 let st_l = Self::max_steps_subtree(self.level as usize) as int;
1631 let st_lp1 = Self::max_steps_subtree(lp1) as int;
1632 vstd::arithmetic::mul::lemma_mul_is_distributive_add(
1633 st_lp1, (NR_ENTRIES - 1) as int, 1);
1634 vstd::arithmetic::mul::lemma_mul_is_distributive_add(
1635 st_l, (NR_ENTRIES - 1) as int, 1);
1636 }
1637 } else {
1638 self.in_locked_range_level_lt_nr_levels();
1639 }
1640 }
1641
1642 pub proof fn zero_below_level_eq_align_down(self)
1644 requires
1645 self.va.inv(),
1646 self.va.offset == 0,
1647 1 <= self.level <= NR_LEVELS,
1648 ensures
1649 self.zero_below_level().va == self.va.align_down(self.level as int),
1650 decreases self.level,
1651 {}
1652
1653 pub proof fn move_forward_va_is_align_up(self)
1654 requires
1655 self.inv(),
1656 self.level <= NR_LEVELS,
1657 self.in_locked_range(),
1658 !self.popped_too_high,
1659 ensures
1660 self.move_forward_owner_spec().va == self.va.align_up(self.level as int),
1661 decreases NR_LEVELS - self.level
1662 {
1663 if self.index() + 1 < NR_ENTRIES {
1664 let inc = self.inc_index();
1665 inc.zero_preserves_all_but_va();
1666 inc.zero_below_level_va();
1667 self.va.align_up_concrete(self.level as int);
1668 assert(inc.va.inv()) by {
1669 assert forall |i: int| 0 <= i < NR_LEVELS implies
1670 inc.va.index.contains_key(i) && 0 <= #[trigger] inc.va.index[i] && inc.va.index[i] < NR_ENTRIES
1671 by { if i != self.level - 1 { assert(inc.va.index[i] == self.va.index[i]); } };
1672 };
1673 inc.va.align_down_concrete(self.level as int);
1674 let ps = page_size(self.level as PagingLevel) as nat;
1675 let self_va = self.va.to_vaddr() as nat;
1676 self.va.align_diff(self.level as int);
1677 lemma_page_size_ge_page_size(self.level as PagingLevel);
1678 assert(self.va.index[self.level - 1] == self.continuations[self.level - 1].idx);
1679 self.va.index_increment_adds_page_size(self.level as int);
1680 assert(self_va + ps == ps * 1 + self_va) by (nonlinear_arith);
1681 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(1int, self_va as int, ps as int);
1682 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(self_va as int, ps as int);
1683 vstd::arithmetic::div_mod::lemma_mod_bound(self_va as int, ps as int);
1684 vstd::arithmetic::div_mod::lemma_div_pos_is_pos(self_va as int, ps as int);
1685 } else if self.level < NR_LEVELS {
1686 self.in_locked_range_level_lt_guard_level();
1687 self.pop_level_owner_preserves_inv();
1688 let popped = self.pop_level_owner_spec().0;
1689 if !popped.popped_too_high {
1690 popped.move_forward_va_is_align_up();
1691 } else {
1692 let inc_p = popped.inc_index();
1693 inc_p.zero_preserves_all_but_va();
1694 inc_p.zero_below_level_va();
1695 popped.va.align_up_concrete(popped.level as int);
1696 assert(inc_p.va.inv()) by {
1697 assert forall |i: int| 0 <= i < NR_LEVELS implies
1698 inc_p.va.index.contains_key(i) && 0 <= #[trigger] inc_p.va.index[i] && inc_p.va.index[i] < NR_ENTRIES
1699 by { if i != popped.level - 1 { assert(inc_p.va.index[i] == popped.va.index[i]); } };
1700 };
1701 inc_p.va.align_down_concrete(popped.level as int);
1702 let ps_p = page_size(popped.level as PagingLevel) as nat;
1703 let popped_va = popped.va.to_vaddr() as nat;
1704 let inc_p_va = inc_p.va.to_vaddr() as nat;
1705 popped.va.align_diff(popped.level as int);
1706 lemma_page_size_ge_page_size(popped.level as PagingLevel);
1707 assert(popped.va.index[popped.level as int - 1] == popped.continuations[popped.level as int - 1].idx);
1708 popped.va.index_increment_adds_page_size(popped.level as int);
1709 assert(popped_va + ps_p == ps_p * 1 + popped_va) by (nonlinear_arith);
1710 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(1int, popped_va as int, ps_p as int);
1711 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(popped_va as int, ps_p as int);
1712 vstd::arithmetic::div_mod::lemma_mod_bound(popped_va as int, ps_p as int);
1713 vstd::arithmetic::div_mod::lemma_div_pos_is_pos(popped_va as int, ps_p as int);
1714 assert(nat_align_down(inc_p_va, ps_p) == nat_align_up(popped_va, ps_p));
1715 assert(inc_p.va.align_down(popped.level as int) == popped.va.align_up(popped.level as int));
1716 assert(popped.index() + 1 < NR_ENTRIES);
1720 assert(popped.move_forward_owner_spec().va == inc_p.zero_below_level().va);
1721 }
1722 assert(self.va.index[self.level as int - 1] == self.continuations[self.level as int - 1].idx);
1723 self.va.align_up_carry(self.level as int);
1724 } else {
1725 }
1726 }
1727
1728 pub proof fn pop_level_owner_preserves_mappings(self)
1732 requires
1733 self.inv(),
1734 self.level < NR_LEVELS,
1735 self.in_locked_range(),
1736 ensures
1737 self.pop_level_owner_spec().0@.mappings == self@.mappings,
1738 {
1739 let child = self.continuations[self.level - 1];
1740 let parent = self.continuations[self.level as int];
1741 let (restored_parent, _) = parent.restore_spec(child);
1742 let popped = self.pop_level_owner_spec().0;
1743 let child_subtree = child.as_subtree();
1744
1745 assert(child.inv());
1746 assert(child.all_some());
1747 assert(parent.inv());
1748 assert(parent.all_but_index_some());
1749 assert(child.path() == parent.path().push_tail(parent.idx as usize));
1750
1751 assert(child_subtree.inv()) by {
1752 assert(child_subtree.inv_node());
1753 assert forall |i: int| 0 <= i < NR_ENTRIES implies
1754 match #[trigger] child_subtree.children[i] {
1755 Some(ch) => {
1756 &&& ch.level == child_subtree.level + 1
1757 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(child_subtree.value, i, Some(ch.value))
1758 },
1759 None => <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(child_subtree.value, i, None),
1760 }
1761 by {
1762 let ch = child.children[i].unwrap();
1763 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
1764 child.entry_own, i, Some(ch.value)));
1765 };
1766 assert(child_subtree.inv_children());
1767
1768 assert forall |i: int| 0 <= i < NR_ENTRIES implies
1769 match #[trigger] child_subtree.children[i] {
1770 Some(ch) => ch.inv(),
1771 None => true,
1772 }
1773 by {
1774 child.inv_children_unroll(i);
1775 };
1776 };
1777
1778 parent.as_subtree_restore(child);
1779
1780 let r = restored_parent;
1781 let p = parent.put_child_spec(child_subtree);
1782 assert forall |j: int| 0 <= j < r.children.len()
1783 implies r.children[j] == p.children[j] by {
1784 if j == parent.idx as int {
1785 assert(r.children[j] == Some(child_subtree));
1786 } else {
1787 assert(r.children[j] == parent.children[j]);
1788 }
1789 };
1790 assert(r.children =~= p.children);
1791 assert(restored_parent.view_mappings() =~=
1792 parent.put_child_spec(child_subtree).view_mappings()) by {
1793 assert(r.path() == p.path());
1794 assert forall |m: Mapping| r.view_mappings().contains(m)
1795 implies p.view_mappings().contains(m) by {
1796 let j = choose |j: int| #![auto]
1797 0 <= j < r.children.len()
1798 && r.children[j] is Some
1799 && PageTableOwner(r.children[j].unwrap()).view_rec(
1800 r.path().push_tail(j as usize)).contains(m);
1801 assert(p.children[j] is Some);
1802 assert(PageTableOwner(p.children[j].unwrap()).view_rec(
1803 p.path().push_tail(j as usize)).contains(m));
1804 };
1805 assert forall |m: Mapping| p.view_mappings().contains(m)
1806 implies r.view_mappings().contains(m) by {
1807 let j = choose |j: int| #![auto]
1808 0 <= j < p.children.len()
1809 && p.children[j] is Some
1810 && PageTableOwner(p.children[j].unwrap()).view_rec(
1811 p.path().push_tail(j as usize)).contains(m);
1812 assert(r.children[j] is Some);
1813 assert(PageTableOwner(r.children[j].unwrap()).view_rec(
1814 r.path().push_tail(j as usize)).contains(m));
1815 };
1816 };
1817
1818 parent.view_mappings_put_child(child_subtree);
1819 child.as_page_table_owner_preserves_view_mappings();
1820
1821 assert(popped.level == (self.level + 1) as u8);
1822 assert(popped.continuations[self.level as int] == restored_parent);
1823
1824 assert(popped.view_mappings() =~= self.view_mappings()) by {
1825 assert forall |m: Mapping| self.view_mappings().contains(m)
1826 implies popped.view_mappings().contains(m) by {
1827 let i = choose |i: int|
1828 self.level - 1 <= i < NR_LEVELS
1829 && (#[trigger] self.continuations[i]).view_mappings().contains(m);
1830 if i == self.level - 1 {
1831 assert(child.view_mappings().contains(m));
1832 assert(restored_parent.view_mappings().contains(m));
1833 assert(popped.continuations[self.level as int].view_mappings().contains(m));
1834 } else if i == self.level as int {
1835 assert(parent.view_mappings().contains(m));
1836 assert(restored_parent.view_mappings().contains(m));
1837 assert(popped.continuations[self.level as int].view_mappings().contains(m));
1838 } else {
1839 assert(popped.continuations[i] == self.continuations[i]);
1840 }
1841 };
1842 assert forall |m: Mapping| popped.view_mappings().contains(m)
1843 implies self.view_mappings().contains(m) by {
1844 let i = choose |i: int|
1845 popped.level - 1 <= i < NR_LEVELS
1846 && (#[trigger] popped.continuations[i]).view_mappings().contains(m);
1847 if i == self.level as int {
1848 assert(restored_parent.view_mappings().contains(m));
1849 if child.view_mappings().contains(m) {
1850 assert(self.continuations[self.level - 1].view_mappings().contains(m));
1851 } else {
1852 assert(parent.view_mappings().contains(m));
1853 assert(self.continuations[self.level as int].view_mappings().contains(m));
1854 }
1855 } else {
1856 assert(self.continuations[i] == popped.continuations[i]);
1857 }
1858 };
1859 };
1860 }
1861
1862 pub proof fn move_forward_owner_preserves_mappings(self)
1863 requires
1864 self.inv(),
1865 self.in_locked_range(),
1866 ensures
1867 self.move_forward_owner_spec()@.mappings == self@.mappings,
1868 decreases NR_LEVELS - self.level,
1869 {
1870 if self.index() + 1 < NR_ENTRIES {
1871 let inc = self.inc_index();
1872 let result = inc.zero_below_level();
1873
1874 inc.zero_preserves_all_but_va();
1875 assert(result.continuations =~= inc.continuations);
1876 assert(result.level == inc.level);
1877
1878 let old_cont = self.continuations[self.level - 1];
1879 let new_cont = old_cont.inc_index();
1880 assert(new_cont.children =~= old_cont.children);
1881 assert(new_cont.entry_own == old_cont.entry_own);
1882 assert(new_cont.path() == old_cont.path());
1883
1884 assert(new_cont.view_mappings() =~= old_cont.view_mappings()) by {
1885 assert forall |m: Mapping| old_cont.view_mappings().contains(m)
1886 implies new_cont.view_mappings().contains(m) by {
1887 let i = choose |i: int| #![auto]
1888 0 <= i < old_cont.children.len()
1889 && old_cont.children[i] is Some
1890 && PageTableOwner(old_cont.children[i].unwrap()).view_rec(
1891 old_cont.path().push_tail(i as usize)).contains(m);
1892 assert(new_cont.children[i] is Some);
1893 assert(PageTableOwner(new_cont.children[i].unwrap()).view_rec(
1894 new_cont.path().push_tail(i as usize)).contains(m));
1895 };
1896 assert forall |m: Mapping| new_cont.view_mappings().contains(m)
1897 implies old_cont.view_mappings().contains(m) by {
1898 let i = choose |i: int| #![auto]
1899 0 <= i < new_cont.children.len()
1900 && new_cont.children[i] is Some
1901 && PageTableOwner(new_cont.children[i].unwrap()).view_rec(
1902 new_cont.path().push_tail(i as usize)).contains(m);
1903 assert(old_cont.children[i] is Some);
1904 assert(PageTableOwner(old_cont.children[i].unwrap()).view_rec(
1905 old_cont.path().push_tail(i as usize)).contains(m));
1906 };
1907 };
1908
1909 assert(result.view_mappings() =~= self.view_mappings()) by {
1910 assert forall |m: Mapping| self.view_mappings().contains(m)
1911 implies result.view_mappings().contains(m) by {
1912 let i = choose |i: int|
1913 self.level - 1 <= i < NR_LEVELS
1914 && (#[trigger] self.continuations[i]).view_mappings().contains(m);
1915 if i == self.level - 1 {
1916 assert(result.continuations[i].view_mappings().contains(m));
1917 } else {
1918 assert(result.continuations[i] == self.continuations[i]);
1919 }
1920 };
1921 assert forall |m: Mapping| result.view_mappings().contains(m)
1922 implies self.view_mappings().contains(m) by {
1923 let i = choose |i: int|
1924 result.level - 1 <= i < NR_LEVELS
1925 && (#[trigger] result.continuations[i]).view_mappings().contains(m);
1926 if i == self.level - 1 {
1927 assert(self.continuations[i].view_mappings().contains(m));
1928 } else {
1929 assert(self.continuations[i] == result.continuations[i]);
1930 }
1931 };
1932 };
1933 } else if self.level < NR_LEVELS {
1934 let popped = self.pop_level_owner_spec().0;
1935
1936 self.pop_level_owner_preserves_inv();
1937 assert(popped.in_locked_range()) by {
1938 assert(popped.va == self.va);
1939 assert(popped.prefix == self.prefix);
1940 assert(popped.guard_level == self.guard_level);
1941 };
1942
1943 self.pop_level_owner_preserves_mappings();
1944 popped.move_forward_owner_preserves_mappings();
1945 }
1946 }
1947
1948 }
1950
1951}
1952
1953
1954
1955