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 core::ops::Range;
20
21verus! {
22
23pub proof fn push_tail_different_indices_different_paths(
25 path: TreePath<NR_ENTRIES>,
26 i: usize,
27 j: usize,
28)
29 requires
30 path.inv(),
31 0 <= i < NR_ENTRIES,
32 0 <= j < NR_ENTRIES,
33 i != j,
34 ensures
35 path.push_tail(i) != path.push_tail(j),
36{
37 path.push_tail_property(i);
38 path.push_tail_property(j);
39 assert(path.push_tail(i).index(path.len() as int) == i as usize);
40 assert(path.push_tail(j).index(path.len() as int) == j as usize);
41 if path.push_tail(i) == path.push_tail(j) {
42 assert(i == j); }
44}
45
46pub proof fn different_length_different_paths(
48 path1: TreePath<NR_ENTRIES>,
49 path2: TreePath<NR_ENTRIES>,
50)
51 requires
52 path1.len() != path2.len(),
53 ensures
54 path1 != path2,
55{
56 if path1 == path2 {
58 assert(path1.len() == path2.len());
59 }
60}
61
62pub proof fn push_tail_increases_length(
64 path: TreePath<NR_ENTRIES>,
65 i: usize,
66)
67 requires
68 path.inv(),
69 0 <= i < NR_ENTRIES,
70 ensures
71 path.push_tail(i).len() > path.len(),
72{
73 path.push_tail_property(i);
74}
75
76impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
77
78 pub open spec fn max_steps_subtree(level: usize) -> usize
81 decreases level,
82 {
83 if level <= 1 {
84 NR_ENTRIES
85 } else {
86 (NR_ENTRIES * (Self::max_steps_subtree((level - 1) as usize) + 1)) as usize
88 }
89 }
90
91 pub open spec fn max_steps_partial(self, level: usize) -> usize
94 decreases NR_LEVELS - level,
95 when level <= NR_LEVELS
96 {
97 if level == NR_LEVELS {
98 0
99 } else {
100 let cont = self.continuations[(level - 1) as int];
102 let steps = Self::max_steps_subtree(level) * (NR_ENTRIES - cont.idx);
104 let remaining_steps = self.max_steps_partial((level + 1) as usize);
106 (steps + remaining_steps) as usize
107 }
108 }
109
110 pub open spec fn max_steps(self) -> usize {
111 self.max_steps_partial(self.level as usize)
112 }
113
114 pub proof fn max_steps_partial_inv(self, other: Self, level: usize)
115 requires
116 self.inv(),
117 other.inv(),
118 self.level == other.level,
119 self.level <= level <= NR_LEVELS,
120 forall |i: int|
121 #![trigger self.continuations[i].idx]
122 #![trigger other.continuations[i].idx]
123 self.level - 1 <= i < NR_LEVELS ==> self.continuations[i].idx == other.continuations[i].idx,
124 ensures
125 self.max_steps_partial(level) == other.max_steps_partial(level),
126 decreases NR_LEVELS - level,
127 {
128 if level < NR_LEVELS {
129 self.max_steps_partial_inv(other, (level + 1) as usize);
130 }
131 }
132
133 pub open spec fn push_level_owner_spec(self, guard_perm: GuardPerm<'rcu, C>) -> Self
134 {
135 let cont = self.continuations[self.level - 1];
136 let (child, cont) = cont.make_cont_spec(self.va.index[self.level - 2] as usize, guard_perm);
137 let new_continuations = self.continuations.insert(self.level - 1, cont);
138 let new_continuations = new_continuations.insert(self.level - 2, child);
139
140 let new_level = (self.level - 1) as u8;
141 Self {
142 continuations: new_continuations,
143 level: new_level,
144 popped_too_high: false,
145 ..self
146 }
147 }
148
149 pub proof fn push_level_owner_decreases_steps(self, guard_perm: GuardPerm<'rcu, C>)
150 requires
151 self.inv(),
152 self.level > 0,
153 ensures
154 self.push_level_owner_spec(guard_perm).max_steps() < self.max_steps()
155 { admit() }
156
157 pub proof fn push_level_owner_preserves_va(self, guard_perm: GuardPerm<'rcu, C>)
158 requires
159 self.inv(),
160 self.level > 1,
161 ensures
162 self.push_level_owner_spec(guard_perm).va == self.va,
163 self.push_level_owner_spec(guard_perm).continuations[self.level - 2].idx == self.va.index[self.level - 2],
164 {
165 assert(self.va.index.contains_key(self.level - 2));
166 }
167
168 pub proof fn push_level_owner_preserves_mappings(self, guard_perm: GuardPerm<'rcu, C>)
169 requires
170 self.inv(),
171 self.level > 1,
172 ensures
173 self.push_level_owner_spec(guard_perm)@.mappings == self@.mappings,
174 { admit() }
175
176 pub proof fn push_level_owner_preserves_inv(self, guard_perm: GuardPerm<'rcu, C>)
177 requires
178 self.inv(),
179 self.level > 1,
180 forall |i: int|
181 #![trigger self.continuations[i]]
182 self.level - 1 <= i < NR_LEVELS ==> self.continuations[i].guard_perm.addr() != guard_perm.addr(),
183 ensures
184 self.push_level_owner_spec(guard_perm).inv(),
185 {
186 admit();
187 let new_owner = self.push_level_owner_spec(guard_perm);
188 let new_level = (self.level - 1) as u8;
189
190 let old_cont = self.continuations[self.level - 1];
191 old_cont.inv_children_unroll(old_cont.idx as int);
192 let child_node = old_cont.children[old_cont.idx as int].unwrap();
193 let (child, modified_cont) = old_cont.make_cont_spec(self.va.index[self.level - 2] as usize, guard_perm);
194
195 assert(child.inv()) by { admit() };
196
197 assert(new_owner.level == new_level);
198 assert(new_owner.va == self.va);
199 assert(new_owner.guard_level == self.guard_level);
200 assert(new_owner.prefix == self.prefix);
201 assert(new_owner.popped_too_high == false);
202 assert(new_owner.continuations[self.level - 1] == modified_cont);
203 assert(new_owner.continuations[self.level - 2] == child);
204
205 assert(modified_cont.entry_own == old_cont.entry_own);
206 assert(modified_cont.idx == old_cont.idx);
207 assert(modified_cont.tree_level == old_cont.tree_level);
208 assert(modified_cont.path == old_cont.path);
209 assert(modified_cont.guard_perm == old_cont.guard_perm);
210 assert(modified_cont.children == old_cont.children.update(old_cont.idx as int, None));
211
212 assert(child.entry_own == child_node.value);
213 assert(child.tree_level == old_cont.tree_level + 1);
214 assert(child.idx == self.va.index[self.level - 2] as usize);
215 assert(child.children == child_node.children);
216 assert(child.guard_perm == guard_perm);
217
218 assert(new_owner.va.inv());
219
220 assert(1 <= new_owner.level <= NR_LEVELS);
221
222 assert(new_owner.guard_level <= NR_LEVELS);
223
224 assert(!new_owner.popped_too_high ==> new_owner.level < new_owner.guard_level || new_owner.above_locked_range()) by {
225 if self.popped_too_high {
226 admit();
227 }
228 };
229
230 assert(new_owner.prefix.inv());
231
232 assert(new_owner.continuations[new_owner.level - 1].all_some()) by { admit() };
233
234 assert(modified_cont.all_but_index_some()) by {
235 assert(modified_cont.children[modified_cont.idx as int] is None);
236 assert forall |i: int| 0 <= i < modified_cont.idx implies
237 modified_cont.children[i] is Some by {
238 assert(modified_cont.children[i] == old_cont.children[i]);
239 };
240 assert forall |i: int| modified_cont.idx < i < NR_ENTRIES implies
241 modified_cont.children[i] is Some by {
242 assert(modified_cont.children[i] == old_cont.children[i]);
243 };
244 };
245
246 assert(forall|i: int| new_owner.level <= i < NR_LEVELS ==> {
247 (#[trigger] new_owner.continuations[i]).all_but_index_some()
248 }) by {
249 assert forall |i: int| new_owner.level <= i < NR_LEVELS implies
250 (#[trigger] new_owner.continuations[i]).all_but_index_some() by {
251 if i == self.level - 1 {
252 assert(new_owner.continuations[i] == modified_cont);
253 } else {
254 assert(new_owner.continuations[i] == self.continuations[i]);
256 }
257 };
258 };
259
260 assert(modified_cont.inv()) by {
261 assert(modified_cont.children.len() == NR_ENTRIES);
262 assert(0 <= modified_cont.idx < NR_ENTRIES);
263 assert(modified_cont.inv_children()) by {
264 assert forall |i: int| 0 <= i < modified_cont.children.len() && #[trigger] modified_cont.children[i] is Some
265 implies modified_cont.children[i].unwrap().inv() by {
266 assert(i != modified_cont.idx);
267 assert(modified_cont.children[i] == old_cont.children[i]);
268 old_cont.inv_children_unroll(i);
269 };
270 };
271 assert(modified_cont.inv_children_rel()) by {
272 assert forall |i: int| 0 <= i < NR_ENTRIES && #[trigger] modified_cont.children[i] is Some
273 implies {
274 &&& modified_cont.children[i].unwrap().value.parent_level == modified_cont.level()
275 &&& modified_cont.children[i].unwrap().level == modified_cont.tree_level + 1
276 &&& !modified_cont.children[i].unwrap().value.in_scope
277 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
278 modified_cont.entry_own, i, Some(modified_cont.children[i].unwrap().value))
279 &&& modified_cont.children[i].unwrap().value.path == modified_cont.path().push_tail(i as usize)
280 } by {
281 assert(i != modified_cont.idx);
282 assert(modified_cont.children[i] == old_cont.children[i]);
283 assert(old_cont.inv_children_rel());
284 };
285 };
286 assert(modified_cont.entry_own.is_node());
287 assert(modified_cont.entry_own.inv());
288 assert(modified_cont.entry_own.node.unwrap().relate_guard_perm(modified_cont.guard_perm));
289 assert(modified_cont.tree_level == INC_LEVELS - modified_cont.level() - 1);
290 assert(modified_cont.tree_level < INC_LEVELS - 1);
291 assert(modified_cont.path().len() == modified_cont.tree_level);
292 };
293
294 assert(new_owner.level <= 4 ==> {
295 &&& new_owner.continuations.contains_key(3)
296 &&& new_owner.continuations[3].inv()
297 &&& new_owner.continuations[3].level() == 4
298 &&& new_owner.continuations[3].entry_own.parent_level == 5
299 &&& new_owner.va.index[3] == new_owner.continuations[3].idx
300 }) by {
301 if new_owner.level <= 4 {
302 if self.level == 4 {
303 assert(new_owner.continuations[3] == modified_cont);
304 } else {
305 assert(new_owner.continuations[3] == self.continuations[3]);
306 }
307 }
308 };
309
310 assert(new_owner.level <= 3 ==> {
312 &&& new_owner.continuations.contains_key(2)
313 &&& new_owner.continuations[2].inv()
314 &&& new_owner.continuations[2].level() == 3
315 &&& new_owner.continuations[2].entry_own.parent_level == 4
316 &&& new_owner.va.index[2] == new_owner.continuations[2].idx
317 &&& new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr() !=
318 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
319 }) by {
320 if new_owner.level <= 3 {
321 if self.level == 4 {
322 assert(self.va.index.contains_key(2));
323 assert(new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr() !=
325 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()) by {
326 assert(new_owner.continuations[2].guard_perm == guard_perm);
327 assert(new_owner.continuations[3] == modified_cont);
328 assert(self.continuations[3].guard_perm.addr() != guard_perm.addr());
329 };
330 }
331 }
332 };
333
334 assert(new_owner.level <= 2 ==> {
336 &&& new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
337 new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
338 &&& new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
339 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
340 }) by {
341 if new_owner.level <= 2 {
342 if self.level == 3 {
343 assert(self.va.index.contains_key(1));
345 assert(new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
346 new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr()) by {
347 admit();
348 };
349 assert(new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
350 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()) by {
351 admit();
352 };
353 }
354 }
355 };
356
357 assert(new_owner.level == 1 ==> {
359 &&& new_owner.continuations.contains_key(0)
360 &&& new_owner.continuations[0].inv()
361 &&& new_owner.continuations[0].level() == 1
362 &&& new_owner.continuations[0].entry_own.parent_level == 2
363 &&& new_owner.va.index[0] == new_owner.continuations[0].idx
364 &&& new_owner.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
365 new_owner.continuations[1].guard_perm.value().inner.inner@.ptr.addr()
366 &&& new_owner.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
367 new_owner.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
368 &&& new_owner.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
369 new_owner.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
370 }) by { admit() };
371 }
372
373 pub proof fn push_level_owner_preserves_invs(self, guard_perm: GuardPerm<'rcu, C>, regions: MetaRegionOwners, guards: Guards<'rcu, C>)
374 requires
375 self.inv(),
376 self.level > 1,
377 self.only_current_locked(guards),
378 self.nodes_locked(guards),
379 self.relate_region(regions),
380 guards.lock_held(guard_perm.value().inner.inner@.ptr.addr()),
382 ensures
383 self.push_level_owner_spec(guard_perm).inv(),
384 self.push_level_owner_spec(guard_perm).children_not_locked(guards),
385 self.push_level_owner_spec(guard_perm).nodes_locked(guards),
386 self.push_level_owner_spec(guard_perm).relate_region(regions),
387 {
388 reveal(CursorContinuation::inv_children);
389 let new_owner = self.push_level_owner_spec(guard_perm);
390 let new_level = (self.level - 1) as u8;
391
392 let old_cont = self.continuations[self.level - 1];
393
394 old_cont.inv_children_unroll_all();
395
396 let (child_cont, modified_cont) = old_cont.make_cont_spec(self.va.index[self.level - 2] as usize, guard_perm);
397 assert(forall |i: int|
398 #![trigger self.continuations[i]]
399 self.level - 1 <= i < NR_LEVELS ==> self.continuations[i].guard_perm.addr() != guard_perm.addr()) by { admit() };
400 self.push_level_owner_preserves_inv(guard_perm);
401
402 let cur_entry = self.cur_entry_owner();
403 let cur_entry_addr = cur_entry.node.unwrap().meta_perm.addr();
404 let cur_entry_path = old_cont.path().push_tail(old_cont.idx as usize);
405
406 assert(cur_entry.relate_region(regions));
407
408 assert(new_owner.children_not_locked(guards)) by {
409 assert forall |i: int|
410 #![trigger new_owner.continuations[i]]
411 new_owner.level - 1 <= i < NR_LEVELS implies
412 new_owner.continuations[i].map_children(CursorOwner::<'rcu, C>::node_unlocked(guards)) by {
413
414 if i == self.level - 2 {
415 assert(new_owner.continuations[i] == child_cont);
416 admit();
417 } else if i == self.level - 1 {
418 assert(new_owner.continuations[i] == modified_cont);
419 assert(modified_cont.path() == old_cont.path());
420
421 assert forall |j: int|
422 #![trigger modified_cont.children[j]]
423 0 <= j < modified_cont.children.len() && modified_cont.children[j] is Some implies
424 modified_cont.children[j].unwrap().tree_predicate_map(
425 modified_cont.path().push_tail(j as usize),
426 CursorOwner::<'rcu, C>::node_unlocked(guards)) by {
427 assert(j != old_cont.idx as int);
428 assert(modified_cont.children[j] == old_cont.children[j]);
429 let sibling_root_path = old_cont.path().push_tail(j as usize);
430 assume(old_cont.path().inv());
431
432 push_tail_different_indices_different_paths(old_cont.path(), j as usize, old_cont.idx);
433 assert(sibling_root_path != cur_entry_path);
434
435 admit();
436 };
437 } else {
438 assert(new_owner.continuations[i] == self.continuations[i]);
439 admit();
440 }
441 };
442 };
443 assert(new_owner.nodes_locked(guards)) by {
444 assert forall |i: int|
445 #![trigger new_owner.continuations[i]]
446 new_owner.level - 1 <= i < NR_LEVELS implies
447 new_owner.continuations[i].node_locked(guards) by {
448
449 if i == self.level - 2 {
450 assert(new_owner.continuations[i] == child_cont);
451 assert(child_cont.guard_perm == guard_perm);
452 } else {
453 assert(i >= self.level - 1);
454 if i == self.level - 1 {
455 assert(new_owner.continuations[i] == modified_cont);
456 assert(modified_cont.guard_perm == old_cont.guard_perm);
457 } else {
458 assert(new_owner.continuations[i] == self.continuations[i]);
459 }
460 }
461 };
462 };
463
464 assert(new_owner.relate_region(regions)) by {
465 let f = PageTableOwner::<C>::relate_region_pred(regions);
466 let g = PageTableOwner::<C>::path_tracked_pred(regions);
467 let child_subtree = child_cont.as_subtree();
468 self.cont_entries_relate_region(regions);
469
470 assert forall |i: int| #![auto]
471 new_owner.level - 1 <= i < NR_LEVELS implies {
472 &&& f(new_owner.continuations[i].entry_own, new_owner.continuations[i].path())
473 &&& new_owner.continuations[i].map_children(f)
474 &&& g(new_owner.continuations[i].entry_own, new_owner.continuations[i].path())
475 &&& new_owner.continuations[i].map_children(g)
476 } by {
477 if i == self.level - 2 {
478 assert(new_owner.continuations[i] == child_cont);
479 assert(f(new_owner.continuations[i].entry_own, new_owner.continuations[i].path()));
480 assert(g(new_owner.continuations[i].entry_own, new_owner.continuations[i].path()));
481 assert(child_subtree.inv()) by {
482 assert(child_subtree.value.inv());
483 assert(child_subtree.level < INC_LEVELS);
484 assert(child_subtree.children.len() == NR_ENTRIES);
485 assert(child_cont.entry_own.is_node());
486 assert(child_cont.tree_level < INC_LEVELS - 1);
487 assert(child_subtree.inv_node());
488 assert(child_subtree.inv_children()) by {
489 assert(child_subtree.level < INC_LEVELS - 1);
490 assert forall |j: int| 0 <= j < NR_ENTRIES implies
491 match #[trigger] child_subtree.children[j] {
492 Some(ch) => {
493 &&& ch.level == child_subtree.level + 1
494 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(child_subtree.value, j, Some(ch.value))
495 },
496 None => <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(child_subtree.value, j, None),
497 }
498 by {
499 assert(child_cont.children[j] is Some);
500 let ch = child_cont.children[j].unwrap();
501 assert(ch.level == child_cont.tree_level + 1);
502 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
503 child_cont.entry_own, j, Some(ch.value)));
504 };
505 };
506 assert forall |j: int| 0 <= j < NR_ENTRIES implies
507 match #[trigger] child_subtree.children[j] {
508 Some(ch) => ch.inv(),
509 None => true,
510 }
511 by {
512 child_cont.inv_children_unroll(j);
513 assert(child_cont.children[j] is Some);
514 assert(child_cont.children[j].unwrap().inv());
515 };
516 };
517 assert(child_subtree.tree_predicate_map(child_cont.path(), f)) by {
518 assert(f(child_subtree.value, child_cont.path()));
519 assert forall |j: int| 0 <= j < child_subtree.children.len() implies
520 match #[trigger] child_subtree.children[j] {
521 Some(ch) => ch.tree_predicate_map(child_cont.path().push_tail(j as usize), f),
522 None => true,
523 }
524 by {
525 child_subtree.map_unroll_once(child_cont.path(), f, j);
526 };
527 };
528 assert(child_subtree.tree_predicate_map(child_cont.path(), g)) by {
529 assert(g(child_subtree.value, child_cont.path()));
530 assert forall |j: int| 0 <= j < child_subtree.children.len() implies
531 match #[trigger] child_subtree.children[j] {
532 Some(ch) => ch.tree_predicate_map(child_cont.path().push_tail(j as usize), g),
533 None => true,
534 }
535 by {
536 child_subtree.map_unroll_once(child_cont.path(), g, j);
537 };
538 };
539 assert(new_owner.continuations[i].map_children(f));
540 assert(new_owner.continuations[i].map_children(g));
541 } else if i == self.level - 1 {
542 assert(new_owner.continuations[i] == modified_cont);
543 assert(modified_cont.entry_own == old_cont.entry_own);
544 assert(modified_cont.path() == old_cont.path());
545 assert(f(modified_cont.entry_own, modified_cont.path()));
546 assert(g(modified_cont.entry_own, modified_cont.path()));
547 assert(modified_cont.map_children(f)) by {
548 assert forall |j: int|
549 0 <= j < modified_cont.children.len() && #[trigger] modified_cont.children[j] is Some implies
550 modified_cont.children[j].unwrap().tree_predicate_map(modified_cont.path().push_tail(j as usize), f) by {
551 assert(j != old_cont.idx as int);
552 assert(modified_cont.children[j] == old_cont.children[j]);
553 };
554 };
555 assert(modified_cont.map_children(g)) by {
556 assert forall |j: int|
557 0 <= j < modified_cont.children.len() && #[trigger] modified_cont.children[j] is Some implies
558 modified_cont.children[j].unwrap().tree_predicate_map(modified_cont.path().push_tail(j as usize), g) by {
559 assert(j != old_cont.idx as int);
560 assert(modified_cont.children[j] == old_cont.children[j]);
561 };
562 };
563 } else {
564 assert(new_owner.continuations[i] == self.continuations[i]);
565 assert(f(new_owner.continuations[i].entry_own, new_owner.continuations[i].path()));
566 assert(new_owner.continuations[i].map_children(f));
567 assert(g(new_owner.continuations[i].entry_own, new_owner.continuations[i].path()));
568 assert(new_owner.continuations[i].map_children(g));
569 }
570 };
571 };
572 }
573
574 #[verifier::returns(proof)]
575 pub proof fn push_level_owner(tracked &mut self, tracked guard_perm: Tracked<GuardPerm<'rcu, C>>)
576 requires
577 old(self).inv(),
578 old(self).level > 1,
579 ensures
580 *self == old(self).push_level_owner_spec(guard_perm@),
581 {
582 assert(self.va.index.contains_key(self.level - 2));
583
584 let ghost self0 = *self;
585 let tracked mut cont = self.continuations.tracked_remove(self.level - 1);
586 let ghost cont0 = cont;
587 let tracked child = cont.make_cont(self.va.index[self.level - 2] as usize, guard_perm);
588
589 assert((child, cont) == cont0.make_cont_spec(self.va.index[self.level - 2] as usize, guard_perm@));
590
591 self.continuations.tracked_insert(self.level - 1, cont);
592 self.continuations.tracked_insert(self.level - 2, child);
593
594 assert(self.continuations == self0.continuations.insert(self.level - 1, cont).insert(self.level - 2, child));
595
596 self.popped_too_high = false;
597
598 self.level = (self.level - 1) as u8;
599 }
600
601 pub open spec fn pop_level_owner_spec(self) -> (Self, GuardPerm<'rcu, C>)
602 {
603 let child = self.continuations[self.level - 1];
604 let cont = self.continuations[self.level as int];
605 let (new_cont, guard_perm) = cont.restore_spec(child);
606 let new_continuations = self.continuations.insert(self.level as int, new_cont);
607 let new_continuations = new_continuations.remove(self.level - 1);
608 let new_level = (self.level + 1) as u8;
609 let popped_too_high = if new_level >= self.guard_level { true } else { false };
610 (Self {
611 continuations: new_continuations,
612 level: new_level,
613 popped_too_high: popped_too_high,
614 ..self
615 }, guard_perm)
616 }
617
618 pub proof fn pop_level_owner_preserves_inv(self)
619 requires
620 self.inv(),
621 self.level < NR_LEVELS,
622 ensures
623 self.pop_level_owner_spec().0.inv(),
624 {
625 reveal(CursorContinuation::inv_children);
626 let child = self.continuations[self.level - 1];
627 assert(child.inv());
628
629 let cont = self.continuations[self.level as int];
630 assert(cont.inv());
631 let (new_cont, _) = cont.restore_spec(child);
632
633 let child_node = OwnerSubtree {
634 value: child.entry_own,
635 level: child.tree_level,
636 children: child.children,
637 };
638
639 assert(new_cont.children[new_cont.idx as int].unwrap() == child_node);
640 admit();
641 }
642
643 pub proof fn pop_level_owner_preserves_invs(self, guards: Guards<'rcu, C>, regions: MetaRegionOwners)
644 requires
645 self.inv(),
646 self.level < NR_LEVELS,
647 self.children_not_locked(guards),
648 self.nodes_locked(guards),
649 self.relate_region(regions),
650 ensures
651 self.pop_level_owner_spec().0.inv(),
652 self.pop_level_owner_spec().0.only_current_locked(guards),
653 self.pop_level_owner_spec().0.nodes_locked(guards),
654 self.pop_level_owner_spec().0.relate_region(regions),
655 {
656 let new_owner = self.pop_level_owner_spec().0;
657 let child = self.continuations[self.level - 1];
658 let cont = self.continuations[self.level as int];
659 let (new_cont, _guard_perm) = cont.restore_spec(child);
660 let child_node = OwnerSubtree {
661 value: child.entry_own,
662 level: child.tree_level,
663 children: child.children,
664 };
665
666 self.pop_level_owner_preserves_inv();
667
668 assert(new_owner.va == self.va);
670 assert(new_owner.prefix == self.prefix);
671 assert(new_owner.guard_level == self.guard_level);
672
673 assert(new_owner.nodes_locked(guards)) by {
676 assert forall |i: int|
677 #![trigger new_owner.continuations[i]]
678 new_owner.level - 1 <= i < NR_LEVELS implies
679 new_owner.continuations[i].node_locked(guards) by {
680 if i == self.level as int {
681 assert(new_owner.continuations[i] == new_cont);
682 assert(new_cont.guard_perm == cont.guard_perm);
683 } else {
684 assert(new_owner.continuations[i] == self.continuations[i]);
685 }
686 };
687 };
688
689 let child_addr = child.entry_own.node.unwrap().meta_perm.addr();
692
693 assert(OwnerSubtree::<C>::implies(
695 CursorOwner::<'rcu, C>::node_unlocked(guards),
696 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr),
697 ));
698
699 self.map_children_implies(
701 CursorOwner::<'rcu, C>::node_unlocked(guards),
702 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr),
703 );
704
705 assert(new_owner.only_current_locked(guards)) by {
708 assert forall |i: int|
709 #![trigger new_owner.continuations[i]]
710 new_owner.level - 1 <= i < NR_LEVELS implies
711 new_owner.continuations[i].map_children(
712 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr)) by {
713 if i > self.level as int {
714 assert(new_owner.continuations[i] == self.continuations[i]);
715 } else {
717 assert(new_owner.continuations[i] == new_cont);
719 let child_subtree = child.as_subtree();
725 assert(child_subtree.inv()) by {
726 assert(child_subtree.value.inv());
727 assert(child_subtree.level < INC_LEVELS);
728 assert(child_subtree.children.len() == NR_ENTRIES);
729 assert forall |j: int| 0 <= j < NR_ENTRIES implies
730 match #[trigger] child_subtree.children[j] {
731 Some(ch) => ch.inv(),
732 None => true,
733 }
734 by {
735 child.inv_children_unroll(j);
736 };
737 };
738 new_cont.map_children_lift_skip_idx(
739 cont,
740 cont.idx as int,
741 CursorOwner::<'rcu, C>::node_unlocked(guards),
742 CursorOwner::<'rcu, C>::node_unlocked_except(guards, child_addr),
743 );
744 }
745 };
746 };
747
748 assert(new_owner.relate_region(regions)) by {
753 let f = PageTableOwner::<C>::relate_region_pred(regions);
754 let g = PageTableOwner::<C>::path_tracked_pred(regions);
755 let child_subtree = child.as_subtree();
756 self.cont_entries_relate_region(regions);
757
758 assert forall |i: int| #![auto]
759 new_owner.level - 1 <= i < NR_LEVELS implies {
760 &&& new_owner.continuations[i].map_children(f)
761 &&& new_owner.continuations[i].map_children(g)
762 } by {
763 if i > self.level as int {
764 } else {
765 assert(child_subtree.inv()) by {
766 assert forall |j: int| 0 <= j < NR_ENTRIES implies
767 match #[trigger] child_subtree.children[j] {
768 Some(ch) => ch.inv(),
769 None => true,
770 }
771 by {
772 child.inv_children_unroll(j);
773 };
774 };
775 new_cont.map_children_lift_skip_idx(cont, cont.idx as int, f, f);
776 new_cont.map_children_lift_skip_idx(cont, cont.idx as int, g, g);
777 }
778 };
779 };
780 }
781
782 pub proof fn set_va_preserves_inv(self, new_va: AbstractVaddr)
788 requires
789 self.inv(),
790 new_va.inv(),
791 forall |i: int| #![auto] self.level - 1 <= i < NR_LEVELS ==> new_va.index[i] == self.va.index[i],
792 forall |i: int| #![auto] self.guard_level - 1 <= i < NR_LEVELS ==> new_va.index[i] == self.prefix.index[i],
793 ensures
794 self.set_va_spec(new_va).inv(),
795 {
796 admit()
797 }
798
799 #[verifier::returns(proof)]
800 pub proof fn pop_level_owner(tracked &mut self) -> (tracked guard_perm: GuardPerm<'rcu, C>)
801 requires
802 old(self).inv(),
803 old(self).level < NR_LEVELS,
804 ensures
805 *self == old(self).pop_level_owner_spec().0,
806 guard_perm == old(self).pop_level_owner_spec().1,
807 {
808 let ghost self0 = *self;
809 let tracked mut parent = self.continuations.tracked_remove(self.level as int);
810 let tracked child = self.continuations.tracked_remove(self.level - 1);
811
812 let tracked guard_perm = parent.restore(child);
813
814 self.continuations.tracked_insert(self.level as int, parent);
815
816 assert(self.continuations == self0.continuations.insert(self.level as int, parent).remove(self.level - 1));
817
818 self.level = (self.level + 1) as u8;
819
820 if self.level >= self.guard_level {
821 self.popped_too_high = true;
822 }
823
824 guard_perm
825 }
826
827 pub open spec fn move_forward_owner_spec(self) -> Self
828 recommends
829 self.inv(),
830 self.level < NR_LEVELS,
831 self.in_locked_range(),
832 decreases NR_LEVELS - self.level when self.level <= NR_LEVELS
833 {
834 if self.index() + 1 < NR_ENTRIES {
835 self.inc_index().zero_below_level()
836 } else if self.level < NR_LEVELS {
837 self.pop_level_owner_spec().0.move_forward_owner_spec()
838 } else {
839 Self {
841 popped_too_high: false,
842 ..self
843 }
844 }
845 }
846
847 pub proof fn move_forward_increases_va(self)
848 requires
849 self.inv(),
850 self.level <= NR_LEVELS,
851 self.in_locked_range(),
852 ensures
853 self.move_forward_owner_spec().va.to_vaddr() > self.va.to_vaddr(),
854 decreases NR_LEVELS - self.level
855 {
856 if self.index() + 1 < NR_ENTRIES {
857 self.inc_and_zero_increases_va();
858 } else if self.level < NR_LEVELS {
859 self.pop_level_owner_preserves_inv();
860 self.pop_level_owner_spec().0.move_forward_increases_va();
861 } else {
862 admit();
863 }
864 }
865
866 pub proof fn move_forward_not_popped_too_high(self)
867 requires
868 self.inv(),
869 self.level <= NR_LEVELS,
870 self.in_locked_range(),
871 ensures
872 !self.move_forward_owner_spec().popped_too_high,
873 decreases NR_LEVELS - self.level,
874 {
875 if self.index() + 1 < NR_ENTRIES {
876 self.inc_index().zero_preserves_all_but_va();
877 } else if self.level < NR_LEVELS {
878 self.pop_level_owner_preserves_inv();
879 self.pop_level_owner_spec().0.move_forward_not_popped_too_high();
880 }
881 }
882
883 pub proof fn move_forward_owner_decreases_steps(self)
884 requires
885 self.inv(),
886 self.level <= NR_LEVELS,
887 ensures
888 self.move_forward_owner_spec().max_steps() < self.max_steps()
889 { admit() }
890
891 pub proof fn move_forward_va_is_align_up(self)
892 requires
893 self.inv(),
894 self.level <= NR_LEVELS,
895 ensures
896 self.move_forward_owner_spec().va == self.va.align_up(self.level as int),
897 decreases NR_LEVELS - self.level
898 {
899 admit()
900 }
901
902 pub proof fn pop_level_owner_preserves_mappings(self)
906 requires
907 self.inv(),
908 self.level < NR_LEVELS,
909 self.in_locked_range(),
910 ensures
911 self.pop_level_owner_spec().0@.mappings == self@.mappings,
912 {
913 let child = self.continuations[self.level - 1];
914 let parent = self.continuations[self.level as int];
915 let (restored_parent, _) = parent.restore_spec(child);
916 let popped = self.pop_level_owner_spec().0;
917 let child_subtree = child.as_subtree();
918
919 assert(child.inv());
921 assert(child.all_some());
922 assert(parent.inv());
923 assert(parent.all_but_index_some());
924
925 assert(child.path() == parent.path().push_tail(parent.idx as usize));
927
928 assert(child_subtree.inv()) by {
930 assert(child_subtree.value.inv());
932 assert(child_subtree.level < INC_LEVELS);
933 assert(child_subtree.children.len() == NR_ENTRIES);
934 assert(child.entry_own.is_node());
936 assert(child.tree_level < INC_LEVELS - 1);
937 assert(child_subtree.inv_node());
938
939 assert(child_subtree.inv_children()) by {
941 assert(child_subtree.level < INC_LEVELS - 1);
942 assert forall |i: int| 0 <= i < NR_ENTRIES implies
943 match #[trigger] child_subtree.children[i] {
944 Some(ch) => {
945 &&& ch.level == child_subtree.level + 1
946 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(child_subtree.value, i, Some(ch.value))
947 },
948 None => <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(child_subtree.value, i, None),
949 }
950 by {
951 assert(child.children[i] is Some);
952 let ch = child.children[i].unwrap();
953 assert(ch.level == child.tree_level + 1);
954 assert(<EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(
956 child.entry_own, i, Some(ch.value)));
957 };
958 };
959
960 assert forall |i: int| 0 <= i < NR_ENTRIES implies
962 match #[trigger] child_subtree.children[i] {
963 Some(ch) => ch.inv(),
964 None => true,
965 }
966 by {
967 child.inv_children_unroll(i);
968 assert(child.children[i] is Some);
969 assert(child.children[i].unwrap().inv());
970 };
971 };
972
973 parent.as_subtree_restore(child);
975 assert(restored_parent.view_mappings() =~=
980 parent.put_child_spec(child_subtree).view_mappings()) by {
981 let r = restored_parent;
982 let p = parent.put_child_spec(child_subtree);
983 assert(r.children =~= p.children) by {
984 assert forall |j: int| 0 <= j < r.children.len()
985 implies r.children[j] == p.children[j] by {
986 if j == parent.idx as int {
987 assert(r.children[j] == Some(child_subtree));
988 } else {
989 assert(r.children[j] == parent.children[j]);
990 }
991 };
992 };
993 assert(r.path() == p.path());
994 assert forall |m: Mapping| r.view_mappings().contains(m)
996 implies p.view_mappings().contains(m) by {
997 let j = choose |j: int| #![auto]
998 0 <= j < r.children.len()
999 && r.children[j] is Some
1000 && PageTableOwner(r.children[j].unwrap()).view_rec(
1001 r.path().push_tail(j as usize)).contains(m);
1002 assert(p.children[j] is Some);
1003 assert(PageTableOwner(p.children[j].unwrap()).view_rec(
1004 p.path().push_tail(j as usize)).contains(m));
1005 };
1006 assert forall |m: Mapping| p.view_mappings().contains(m)
1007 implies r.view_mappings().contains(m) by {
1008 let j = choose |j: int| #![auto]
1009 0 <= j < p.children.len()
1010 && p.children[j] is Some
1011 && PageTableOwner(p.children[j].unwrap()).view_rec(
1012 p.path().push_tail(j as usize)).contains(m);
1013 assert(r.children[j] is Some);
1014 assert(PageTableOwner(r.children[j].unwrap()).view_rec(
1015 r.path().push_tail(j as usize)).contains(m));
1016 };
1017 };
1018
1019 parent.view_mappings_put_child(child_subtree);
1022
1023 child.as_page_table_owner_preserves_view_mappings();
1026
1027 assert(popped.level == (self.level + 1) as u8);
1036 assert(popped.continuations[self.level as int] == restored_parent);
1037
1038 assert(popped.view_mappings() =~= self.view_mappings()) by {
1041 assert forall |m: Mapping| self.view_mappings().contains(m)
1043 implies popped.view_mappings().contains(m) by {
1044 let i = choose |i: int|
1045 self.level - 1 <= i < NR_LEVELS
1046 && (#[trigger] self.continuations[i]).view_mappings().contains(m);
1047 if i == self.level - 1 {
1048 assert(child.view_mappings().contains(m));
1050 assert(restored_parent.view_mappings().contains(m));
1051 assert(popped.continuations[self.level as int].view_mappings().contains(m));
1052 } else if i == self.level as int {
1053 assert(parent.view_mappings().contains(m));
1055 assert(restored_parent.view_mappings().contains(m));
1056 assert(popped.continuations[self.level as int].view_mappings().contains(m));
1057 } else {
1058 assert(popped.continuations[i] == self.continuations[i]);
1060 }
1061 };
1062 assert forall |m: Mapping| popped.view_mappings().contains(m)
1064 implies self.view_mappings().contains(m) by {
1065 let i = choose |i: int|
1066 popped.level - 1 <= i < NR_LEVELS
1067 && (#[trigger] popped.continuations[i]).view_mappings().contains(m);
1068 if i == self.level as int {
1069 assert(restored_parent.view_mappings().contains(m));
1072 if child.view_mappings().contains(m) {
1073 assert(self.continuations[self.level - 1].view_mappings().contains(m));
1074 } else {
1075 assert(parent.view_mappings().contains(m));
1076 assert(self.continuations[self.level as int].view_mappings().contains(m));
1077 }
1078 } else {
1079 assert(self.continuations[i] == popped.continuations[i]);
1080 }
1081 };
1082 };
1083 }
1084
1085 pub proof fn move_forward_owner_preserves_mappings(self)
1086 requires
1087 self.inv(),
1088 self.in_locked_range(),
1089 ensures
1090 self.move_forward_owner_spec()@.mappings == self@.mappings,
1091 decreases NR_LEVELS - self.level,
1092 {
1093 if self.index() + 1 < NR_ENTRIES {
1094 let inc = self.inc_index();
1096 let result = inc.zero_below_level();
1097
1098 inc.zero_preserves_all_but_va();
1100 assert(result.continuations =~= inc.continuations);
1101 assert(result.level == inc.level);
1102
1103 let old_cont = self.continuations[self.level - 1];
1105 let new_cont = old_cont.inc_index();
1106 assert(new_cont.children =~= old_cont.children);
1107 assert(new_cont.entry_own == old_cont.entry_own);
1108 assert(new_cont.path() == old_cont.path());
1109
1110 assert(new_cont.view_mappings() =~= old_cont.view_mappings()) by {
1112 assert forall |m: Mapping| old_cont.view_mappings().contains(m)
1113 implies new_cont.view_mappings().contains(m) by {
1114 let i = choose |i: int| #![auto]
1115 0 <= i < old_cont.children.len()
1116 && old_cont.children[i] is Some
1117 && PageTableOwner(old_cont.children[i].unwrap()).view_rec(
1118 old_cont.path().push_tail(i as usize)).contains(m);
1119 assert(new_cont.children[i] is Some);
1120 assert(PageTableOwner(new_cont.children[i].unwrap()).view_rec(
1121 new_cont.path().push_tail(i as usize)).contains(m));
1122 };
1123 assert forall |m: Mapping| new_cont.view_mappings().contains(m)
1124 implies old_cont.view_mappings().contains(m) by {
1125 let i = choose |i: int| #![auto]
1126 0 <= i < new_cont.children.len()
1127 && new_cont.children[i] is Some
1128 && PageTableOwner(new_cont.children[i].unwrap()).view_rec(
1129 new_cont.path().push_tail(i as usize)).contains(m);
1130 assert(old_cont.children[i] is Some);
1131 assert(PageTableOwner(old_cont.children[i].unwrap()).view_rec(
1132 old_cont.path().push_tail(i as usize)).contains(m));
1133 };
1134 };
1135
1136 assert(result.view_mappings() =~= self.view_mappings()) by {
1138 assert forall |m: Mapping| self.view_mappings().contains(m)
1139 implies result.view_mappings().contains(m) by {
1140 let i = choose |i: int|
1141 self.level - 1 <= i < NR_LEVELS
1142 && (#[trigger] self.continuations[i]).view_mappings().contains(m);
1143 if i == self.level - 1 {
1144 assert(result.continuations[i].view_mappings().contains(m));
1145 } else {
1146 assert(result.continuations[i] == self.continuations[i]);
1147 }
1148 };
1149 assert forall |m: Mapping| result.view_mappings().contains(m)
1150 implies self.view_mappings().contains(m) by {
1151 let i = choose |i: int|
1152 result.level - 1 <= i < NR_LEVELS
1153 && (#[trigger] result.continuations[i]).view_mappings().contains(m);
1154 if i == self.level - 1 {
1155 assert(self.continuations[i].view_mappings().contains(m));
1156 } else {
1157 assert(self.continuations[i] == result.continuations[i]);
1158 }
1159 };
1160 };
1161 } else if self.level < NR_LEVELS {
1162 let popped = self.pop_level_owner_spec().0;
1164
1165 self.pop_level_owner_preserves_inv();
1167 assert(popped.in_locked_range()) by {
1168 assert(popped.va == self.va);
1169 assert(popped.prefix == self.prefix);
1170 assert(popped.guard_level == self.guard_level);
1171 };
1172
1173 self.pop_level_owner_preserves_mappings();
1175 popped.move_forward_owner_preserves_mappings();
1177 } else {
1178 }
1181 }
1182
1183 pub proof fn move_forward_owner_preserves_in_locked_range(self)
1185 requires
1186 self.inv(),
1187 self.level <= NR_LEVELS,
1188 self.in_locked_range(),
1189 ensures
1190 self.move_forward_owner_spec().in_locked_range(),
1191 decreases NR_LEVELS - self.level,
1192 {
1193 if self.index() + 1 < NR_ENTRIES {
1194 admit();
1197 } else if self.level < NR_LEVELS {
1198 self.pop_level_owner_preserves_inv();
1201 let popped = self.pop_level_owner_spec().0;
1202 assert(popped.in_locked_range());
1204 popped.move_forward_owner_preserves_in_locked_range();
1205 } else {
1206 }
1209 }
1210
1211 pub proof fn move_forward_pop_loop_level_lt_guard(self, owner0: Self)
1220 requires
1221 self.inv(),
1222 self.in_locked_range(),
1223 self.level <= self.guard_level,
1224 owner0.inv(),
1225 owner0.in_locked_range(),
1226 self.move_forward_owner_spec() == owner0.move_forward_owner_spec(),
1227 !owner0.move_forward_owner_spec().popped_too_high,
1228 ensures
1229 self.level < self.guard_level,
1230 {
1231 if !self.popped_too_high {
1235 assert(self.in_locked_range() ==> !self.above_locked_range());
1236 } else {
1237 admit();
1247 }
1248 }
1249}
1250
1251}