1use vstd::prelude::*;
2
3use vstd_extra::drop_tracking::*;
4use vstd_extra::ghost_tree::*;
5use vstd_extra::ownership::*;
6
7use crate::mm::page_table::*;
8
9use core::marker::PhantomData;
10use core::ops::Range;
11
12use crate::mm::page_prop::PageProperty;
13use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr};
14use crate::specs::arch::mm::MAX_USERSPACE_VADDR;
15use crate::specs::arch::mm::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
16use crate::specs::arch::paging_consts::PagingConsts;
17use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
18use crate::specs::mm::page_table::node::GuardPerm;
19use crate::specs::mm::page_table::owners::*;
20use crate::specs::mm::page_table::view::PageTableView;
21use crate::specs::mm::page_table::AbstractVaddr;
22use crate::specs::mm::page_table::Guards;
23use crate::specs::mm::page_table::Mapping;
24use crate::specs::mm::page_table::{nat_align_down, nat_align_up};
25use crate::specs::task::InAtomicMode;
26
27verus! {
28
29pub tracked struct CursorContinuation<'rcu, C: PageTableConfig> {
30 pub entry_own: EntryOwner<C>,
31 pub idx: usize,
32 pub tree_level: nat,
33 pub children: Seq<Option<OwnerSubtree<C>>>,
34 pub path: TreePath<NR_ENTRIES>,
35 pub guard_perm: GuardPerm<'rcu, C>,
36}
37
38impl<'rcu, C: PageTableConfig> CursorContinuation<'rcu, C> {
39 pub open spec fn path(self) -> TreePath<NR_ENTRIES> {
40 self.entry_own.path
41 }
42
43 pub open spec fn child(self) -> OwnerSubtree<C> {
44 self.children[self.idx as int].unwrap()
45 }
46
47 pub open spec fn take_child_spec(self) -> (OwnerSubtree<C>, Self) {
48 let child = self.children[self.idx as int].unwrap();
49 let cont = Self {
50 children: self.children.remove(self.idx as int).insert(self.idx as int, None),
51 ..self
52 };
53 (child, cont)
54 }
55
56 #[verifier::returns(proof)]
57 pub proof fn take_child(tracked &mut self) -> (res: OwnerSubtree<C>)
58 requires
59 old(self).idx < old(self).children.len(),
60 old(self).children[old(self).idx as int] is Some,
61 ensures
62 res == old(self).take_child_spec().0,
63 *self == old(self).take_child_spec().1,
64 {
65 let tracked child = self.children.tracked_remove(old(self).idx as int).tracked_unwrap();
66 self.children.tracked_insert(old(self).idx as int, None);
67 child
68 }
69
70 pub open spec fn put_child_spec(self, child: OwnerSubtree<C>) -> Self {
71 Self {
72 children: self.children.remove(self.idx as int).insert(self.idx as int, Some(child)),
73 ..self
74 }
75 }
76
77 #[verifier::returns(proof)]
78 pub proof fn put_child(tracked &mut self, tracked child: OwnerSubtree<C>)
79 requires
80 old(self).idx < old(self).children.len(),
81 old(self).children[old(self).idx as int] is None,
82 ensures
83 *self == old(self).put_child_spec(child)
84 {
85 let _ = self.children.tracked_remove(old(self).idx as int);
86 self.children.tracked_insert(old(self).idx as int, Some(child));
87 }
88
89 pub proof fn take_put_child(self)
90 requires
91 self.idx < self.children.len(),
92 self.children[self.idx as int] is Some,
93 ensures
94 self.take_child_spec().1.put_child_spec(self.take_child_spec().0) == self,
95 {
96 let child = self.take_child_spec().0;
97 let cont = self.take_child_spec().1;
98 assert(cont.put_child_spec(child).children == self.children);
99 }
100
101 pub open spec fn make_cont_spec(self, idx: usize, guard_perm: GuardPerm<'rcu, C>) -> (Self, Self) {
102 let child = Self {
103 entry_own: self.children[self.idx as int].unwrap().value,
104 tree_level: (self.tree_level + 1) as nat,
105 idx: idx,
106 children: self.children[self.idx as int].unwrap().children,
107 path: self.path.push_tail(self.idx as usize),
108 guard_perm: guard_perm,
109 };
110 let cont = Self {
111 children: self.children.update(self.idx as int, None),
112 ..self
113 };
114 (child, cont)
115 }
116
117 #[verifier::returns(proof)]
118 pub axiom fn make_cont(tracked &mut self, idx: usize, tracked guard_perm: Tracked<GuardPerm<'rcu, C>>) -> (res: Self)
119 requires
120 old(self).all_some(),
121 old(self).idx < NR_ENTRIES,
122 idx < NR_ENTRIES,
123 ensures
124 res == old(self).make_cont_spec(idx, guard_perm@).0,
125 *self == old(self).make_cont_spec(idx, guard_perm@).1,
126 ;
127
128 pub open spec fn restore_spec(self, child: Self) -> (Self, GuardPerm<'rcu, C>) {
129 let child_node = OwnerSubtree {
130 value: child.entry_own,
131 level: child.tree_level,
132 children: child.children,
133 };
134 (Self { children: self.children.update(self.idx as int, Some(child_node)), ..self }, child.guard_perm)
135 }
136
137 #[verifier::returns(proof)]
138 pub axiom fn restore(tracked &mut self, tracked child: Self) -> (tracked guard_perm: GuardPerm<'rcu, C>)
139 ensures
140 *self == old(self).restore_spec(child).0,
141 guard_perm == old(self).restore_spec(child).1,
142 ;
143
144 pub open spec fn map_children(self, f: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool) -> bool {
145 forall |i: int|
146 #![trigger self.children[i]]
147 0 <= i < self.children.len() ==>
148 self.children[i] is Some ==>
149 self.children[i].unwrap().tree_predicate_map(self.path().push_tail(i as usize), f)
150 }
151
152 pub open spec fn level(self) -> PagingLevel {
153 self.entry_own.node.unwrap().level
154 }
155
156 pub open spec fn inv(self) -> bool {
157 &&& self.children.len() == NR_ENTRIES
158 &&& 0 <= self.idx < NR_ENTRIES
159 &&& forall|i: int|
160 #![trigger self.children[i]]
161 0 <= i < NR_ENTRIES ==>
162 self.children[i] is Some ==> {
163 &&& self.children[i].unwrap().value.path == self.path().push_tail(i as usize)
164 &&& self.children[i].unwrap().value.parent_level == self.level()
165 &&& self.children[i].unwrap().inv()
166 &&& self.children[i].unwrap().level == self.tree_level + 1
167 &&& <EntryOwner<C> as TreeNodeValue<NR_LEVELS>>::rel_children(self.entry_own, i, Some(self.children[i].unwrap().value))
168 }
169 &&& self.entry_own.is_node()
170 &&& self.entry_own.inv()
171 &&& self.entry_own.node.unwrap().relate_guard_perm(self.guard_perm)
172 &&& self.tree_level == INC_LEVELS - self.level()
173 &&& self.tree_level < INC_LEVELS - 1
174 &&& self.path().len() == self.tree_level
175 }
176
177 pub open spec fn all_some(self) -> bool {
178 forall|i: int| 0 <= i < NR_ENTRIES ==> self.children[i] is Some
179 }
180
181 pub open spec fn all_but_index_some(self) -> bool {
182 &&& forall|i: int| 0 <= i < self.idx ==> self.children[i] is Some
183 &&& forall|i: int| self.idx < i < NR_ENTRIES ==> self.children[i] is Some
184 &&& self.children[self.idx as int] is None
185 }
186
187 pub open spec fn inc_index(self) -> Self {
188 Self {
189 idx: (self.idx + 1) as usize,
190 ..self
191 }
192 }
193
194 pub proof fn do_inc_index(tracked &mut self)
195 requires
196 old(self).idx + 1 < NR_ENTRIES,
197 ensures
198 *self == old(self).inc_index(),
199 {
200 self.idx = (self.idx + 1) as usize;
201 }
202
203 pub open spec fn node_locked(self, guards: Guards<'rcu, C>) -> bool {
204 guards.lock_held(self.guard_perm.value().inner.inner@.ptr.addr())
205 }
206
207 pub open spec fn view_mappings(self) -> Set<Mapping> {
208 Set::new(
209 |m: Mapping| exists|i:int|
210 #![trigger self.children[i]]
211 0 <= i < self.children.len() &&
212 self.children[i] is Some &&
213 PageTableOwner(self.children[i].unwrap()).view_rec(self.path().push_tail(i as usize)).contains(m)
214 )
215 }
216
217 pub open spec fn as_subtree(self) -> OwnerSubtree<C> {
218 OwnerSubtree {
219 value: self.entry_own,
220 level: self.tree_level,
221 children: self.children,
222 }
223 }
224
225 pub open spec fn as_page_table_owner(self) -> PageTableOwner<C> {
226 PageTableOwner(self.as_subtree())
227 }
228
229 pub proof fn as_page_table_owner_preserves_view_mappings(self)
230 requires
231 self.inv(),
232 self.all_some(),
233 ensures
234 self.as_page_table_owner().view_rec(self.path()) == self.view_mappings(),
235 { }
236
237 pub proof fn as_subtree_restore(self, child: Self)
238 requires
239 self.inv(),
240 child.inv(),
241 self.all_but_index_some(),
242 child.all_some(),
243 ensures
244 self.restore_spec(child).0.as_subtree() ==
245 self.put_child_spec(child.as_subtree()).as_subtree(),
246 {
247 assert(self.put_child_spec(child.as_subtree()).children ==
248 self.children.update(self.idx as int, Some(child.as_subtree())));
249 }
250
251 pub open spec fn view_mappings_take_child_spec(self) -> Set<Mapping> {
252 PageTableOwner(self.children[self.idx as int].unwrap()).view_rec(self.path().push_tail(self.idx as usize))
253 }
254
255 pub proof fn view_mappings_take_child(self)
256 requires
257 self.inv(),
258 self.all_some(),
259 ensures
260 self.take_child_spec().1.view_mappings() == self.view_mappings() - self.view_mappings_take_child_spec()
261 {
262 let def = self.take_child_spec().1.view_mappings();
263 let diff = self.view_mappings() - self.view_mappings_take_child_spec();
264 assert forall |m: Mapping| diff.contains(m) implies def.contains(m) by {
265 let i = choose|i: int| 0 <= i < self.children.len() && #[trigger] self.children[i] is Some &&
266 PageTableOwner(self.children[i].unwrap()).view_rec(self.path().push_tail(i as usize)).contains(m);
267 assert(i != self.idx);
268 assert(self.take_child_spec().1.children[i] is Some);
269 };
270 assert forall |m: Mapping|
271 #![trigger def.contains(m)]
272 def.contains(m) implies diff.contains(m) by {
273 let left = self.take_child_spec().1;
274 assert(left.view_mappings().contains(m));
275 if self.view_mappings_take_child_spec().contains(m) {
276 assert(PageTableOwner(self.children[self.idx as int].unwrap()).view_rec(self.path().push_tail(self.idx as usize)).contains(m));
277 let i = choose|i: int| 0 <= i < left.children.len() && #[trigger] left.children[i] is Some &&
278 PageTableOwner(left.children[i].unwrap()).view_rec(left.path().push_tail(i as usize)).contains(m);
279 assert(i != self.idx);
280 assert(PageTableOwner(left.children[i as int].unwrap()).view_rec(left.path().push_tail(i as usize)).contains(m));
281
282 PageTableOwner(self.children[self.idx as int].unwrap()).view_rec_vaddr_range(self.path().push_tail(self.idx as usize), m);
283 PageTableOwner(left.children[i as int].unwrap()).view_rec_vaddr_range(left.path().push_tail(i as usize), m);
284
285 let size = page_size(self.path().push_tail(self.idx as usize).len() as PagingLevel);
286
287 sibling_paths_disjoint(self.path(), self.idx, i as usize, size);
289 assert(vaddr(self.path().push_tail(self.idx as usize)) + size <= vaddr(left.path().push_tail(i as usize)) ||
290 vaddr(left.path().push_tail(i as usize)) + size <= vaddr(self.path().push_tail(self.idx as usize)));
291
292 }
293 };
294 }
295
296 pub proof fn view_mappings_put_child(self, child: OwnerSubtree<C>)
297 requires
298 self.inv(),
299 child.inv(),
300 self.all_but_index_some(),
301 ensures
302 self.put_child_spec(child).view_mappings() == self.view_mappings() + PageTableOwner(child).view_rec(self.path().push_tail(self.idx as usize))
303 {
304 let def = self.put_child_spec(child).view_mappings();
305 let sum = self.view_mappings() + PageTableOwner(child).view_rec(self.path().push_tail(self.idx as usize));
306 assert forall |m: Mapping| sum.contains(m) implies def.contains(m) by {
307 if self.view_mappings().contains(m) {
308 let i = choose|i: int| 0 <= i < self.children.len() && #[trigger] self.children[i] is Some &&
309 PageTableOwner(self.children[i].unwrap()).view_rec(self.path().push_tail(i as usize)).contains(m);
310 assert(i != self.idx);
311 assert(self.put_child_spec(child).children[i] == self.children[i]);
312 } else {
313 assert(PageTableOwner(child).view_rec(self.path().push_tail(self.idx as usize)).contains(m));
314 assert(self.put_child_spec(child).children[self.idx as int] == Some(child));
315 }
316 };
317 }
318
319 pub proof fn new_child(tracked &self, paddr: Paddr, prop: PageProperty) -> (tracked res: OwnerSubtree<C>)
320 requires
321 self.inv(),
322 ensures
323 res.value == EntryOwner::<C>::new_frame_spec(paddr, self.path().push_tail(self.idx as usize), self.level(), prop),
324 res.inv(),
325 res.level == self.tree_level + 1
326 {
327 let tracked owner = EntryOwner::<C>::new_frame(paddr, self.path().push_tail(self.idx as usize), self.level(), prop);
328 OwnerSubtree::new_val_tracked(owner, self.tree_level + 1)
329 }
330
331}
332
333pub tracked struct CursorOwner<'rcu, C: PageTableConfig> {
334 pub level: PagingLevel,
335 pub continuations: Map<int, CursorContinuation<'rcu, C>>,
336 pub va: AbstractVaddr,
337 pub guard_level: PagingLevel,
338 pub prefix: AbstractVaddr,
339 pub popped_too_high: bool,
340}
341
342impl<'rcu, C: PageTableConfig> Inv for CursorOwner<'rcu, C> {
343 open spec fn inv(self) -> bool {
344 &&& self.va.inv()
345 &&& 1 <= self.level <= NR_LEVELS
346 &&& self.guard_level <= NR_LEVELS
347 &&& self.popped_too_high ==> self.level >= self.guard_level && self.in_locked_range()
350 &&& !self.popped_too_high ==> self.level < self.guard_level || self.above_locked_range()
351 &&& self.continuations[self.level - 1].all_some()
352 &&& forall|i: int| self.level <= i < NR_LEVELS ==> {
353 (#[trigger] self.continuations[i]).all_but_index_some()
354 }
355 &&& self.prefix.inv()
356 &&& forall|i: int| i < self.guard_level ==> self.prefix.index[i] == 0
357 &&& self.level <= 4 ==> {
358 &&& self.continuations.contains_key(3)
359 &&& self.continuations[3].inv()
360 &&& self.continuations[3].level() == 4
361 &&& self.continuations[3].entry_own.parent_level == 5
363 &&& self.va.index[3] == self.continuations[3].idx
364 }
365 &&& self.level <= 3 ==> {
366 &&& self.continuations.contains_key(2)
367 &&& self.continuations[2].inv()
368 &&& self.continuations[2].level() == 3
369 &&& self.continuations[2].entry_own.parent_level == 4
370 &&& self.va.index[2] == self.continuations[2].idx
371 &&& self.continuations[2].guard_perm.value().inner.inner@.ptr.addr() !=
372 self.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
373 }
374 &&& self.level <= 2 ==> {
375 &&& self.continuations.contains_key(1)
376 &&& self.continuations[1].inv()
377 &&& self.continuations[1].level() == 2
378 &&& self.continuations[1].entry_own.parent_level == 3
379 &&& self.va.index[1] == self.continuations[1].idx
380 &&& self.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
381 self.continuations[2].guard_perm.value().inner.inner@.ptr.addr()
382 &&& self.continuations[1].guard_perm.value().inner.inner@.ptr.addr() !=
383 self.continuations[3].guard_perm.value().inner.inner@.ptr.addr()
384 }
385 &&& self.level == 1 ==> {
386 &&& self.continuations.contains_key(0)
387 &&& self.continuations[0].inv()
388 &&& self.continuations[0].level() == 1
389 &&& self.continuations[0].entry_own.parent_level == 2
390 &&& self.va.index[0] == self.continuations[0].idx
391 &&& self.continuations[0].guard_perm.value().inner.inner@.ptr.addr() !=
392 self.continuations[1].guard_perm.value().inner.inner@.ptr.addr()
393 }
394 }
395}
396
397impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
398
399 pub open spec fn node_unlocked(guards: Guards<'rcu, C>) ->
400 (spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool) {
401 |owner: EntryOwner<C>, path: TreePath<NR_ENTRIES>|
402 owner.is_node() ==>
403 guards.unlocked(owner.node.unwrap().meta_perm.addr())
404 }
405
406 pub open spec fn node_unlocked_except(guards: Guards<'rcu, C>, addr: usize) ->
407 (spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool) {
408 |owner: EntryOwner<C>, path: TreePath<NR_ENTRIES>|
409 owner.is_node() ==>
410 owner.node.unwrap().meta_perm.addr() != addr ==>
411 guards.unlocked(owner.node.unwrap().meta_perm.addr())
412 }
413
414 pub open spec fn map_full_tree(self, f: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool) -> bool {
415 forall|i: int|
416 #![trigger self.continuations[i]]
417 self.level - 1 <= i < NR_LEVELS ==> {
418 self.continuations[i].map_children(f)
419 }
420 }
421
422 pub open spec fn map_only_children(self, f: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool) -> bool {
423 forall|i: int|
424 #![trigger self.continuations[i]]
425 self.level - 1 <= i < NR_LEVELS ==>
426 self.continuations[i].map_children(f)
427 }
428
429 pub open spec fn children_not_locked(self, guards: Guards<'rcu, C>) -> bool {
430 self.map_only_children(Self::node_unlocked(guards))
431 }
432
433 pub open spec fn only_current_locked(self, guards: Guards<'rcu, C>) -> bool {
434 self.map_only_children(Self::node_unlocked_except(guards, self.cur_entry_owner().node.unwrap().meta_perm.addr()))
435 }
436
437 pub proof fn never_drop_restores_children_not_locked(
438 self,
439 guard: PageTableGuard<'rcu, C>,
440 guards0: Guards<'rcu, C>,
441 guards1: Guards<'rcu, C>)
442 requires
443 self.inv(),
444 self.only_current_locked(guards0),
445 <PageTableGuard<'rcu, C> as TrackDrop>::constructor_requires(guard, guards0),
446 <PageTableGuard<'rcu, C> as TrackDrop>::constructor_ensures(guard, guards0, guards1),
447 ensures
448 self.children_not_locked(guards1),
449 {
450 admit()
451 }
452
453 pub proof fn map_children_implies(
454 self,
455 f: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool,
456 g: spec_fn(EntryOwner<C>, TreePath<NR_ENTRIES>) -> bool,
457 )
458 requires
459 self.inv(),
460 OwnerSubtree::implies(f, g),
461 forall|i: int|
462 #![trigger self.continuations[i]]
463 self.level - 1 <= i < NR_LEVELS ==>
464 self.continuations[i].map_children(f),
465 ensures
466 forall|i: int|
467 #![trigger self.continuations[i]]
468 self.level - 1 <= i < NR_LEVELS ==>
469 self.continuations[i].map_children(g),
470 {
471 assert forall|i: int|
472 #![trigger self.continuations[i]]
473 self.level - 1 <= i < NR_LEVELS implies self.continuations[i].map_children(g) by {
474 let cont = self.continuations[i];
475 assert forall|j: int|
476 #![trigger cont.children[j]]
477 0 <= j < cont.children.len() && cont.children[j] is Some
478 implies cont.children[j].unwrap().tree_predicate_map(cont.path().push_tail(j as usize), g) by {
479 OwnerSubtree::map_implies(cont.children[j].unwrap(), cont.path().push_tail(j as usize), f, g);
480 }
481 }
482 }
483
484 pub open spec fn nodes_locked(self, guards: Guards<'rcu, C>) -> bool {
485 forall|i: int|
486 #![trigger self.continuations[i]]
487 self.level - 1 <= i < NR_LEVELS ==> {
488 self.continuations[i].node_locked(guards)
489 }
490 }
491
492 pub open spec fn index(self) -> usize {
493 self.continuations[self.level - 1].idx
494 }
495
496 pub open spec fn inc_index(self) -> Self {
497 Self {
498 continuations: self.continuations.insert(self.level - 1, self.continuations[self.level - 1].inc_index()),
499 va: AbstractVaddr {
500 offset: self.va.offset,
501 index: self.va.index.insert(self.level - 1, self.continuations[self.level - 1].inc_index().idx as int)
502 },
503 popped_too_high: false,
504 ..self
505 }
506 }
507
508 pub open spec fn zero_below_level_rec(self, level: PagingLevel) -> Self
509 decreases self.level - level
510 {
511 if self.level <= level {
512 self
513 } else {
514 Self {
515 va: AbstractVaddr {
516 offset: self.va.offset,
517 index: self.va.index.insert(level - 1, 0)
518 },
519 ..self.zero_below_level_rec((level + 1) as u8)
520 }
521 }
522 }
523
524 pub open spec fn zero_below_level(self) -> Self {
525 self.zero_below_level_rec(1u8)
526 }
527
528 pub proof fn zero_below_level_rec_preserves_above(self, level: PagingLevel)
529 ensures
530 forall |lv: int| lv >= self.level ==> self.zero_below_level_rec(level).va.index[lv] == #[trigger] self.va.index[lv],
531 decreases self.level - level,
532 {
533 if self.level > level {
534 self.zero_below_level_rec_preserves_above((level + 1) as u8);
535 }
536 }
537
538 pub proof fn zero_preserves_above(self)
539 ensures
540 forall |lv: int| lv >= self.level ==> self.zero_below_level().va.index[lv] == #[trigger] self.va.index[lv],
541 {
542 self.zero_below_level_rec_preserves_above(1u8);
543 }
544
545 pub axiom fn do_zero_below_level(tracked &mut self)
546 requires
547 old(self).inv(),
548 ensures
549 *self == old(self).zero_below_level();
550
551 pub proof fn do_inc_index(tracked &mut self)
552 requires
553 old(self).inv(),
554 old(self).continuations[old(self).level - 1].idx + 1 < NR_ENTRIES,
555 old(self).in_locked_range(),
556 ensures
557 self.inv(),
558 *self == old(self).inc_index(),
559 {
560 self.popped_too_high = false;
561 let tracked mut cont = self.continuations.tracked_remove(self.level - 1);
562 if self.level >= self.guard_level {
563 let ghost size = self.locked_range().end - self.locked_range().start;
564 let ghost new_va = AbstractVaddr {
565 offset: self.va.offset,
566 index: self.va.index.insert(self.level - 1, cont.idx + 1)
567 };
568 assert(new_va.to_vaddr() == self.va.to_vaddr() + size) by { admit() };
569 }
570
571 cont.do_inc_index();
572 self.va.index.tracked_insert(self.level - 1, cont.idx as int);
573 self.continuations.tracked_insert(self.level - 1, cont);
574 assert(self.continuations == old(self).continuations.insert(self.level - 1, cont));
575 }
576
577 pub proof fn inc_and_zero_increases_va(self)
578 requires
579 self.inv()
580 ensures
581 self.inc_index().zero_below_level().va.to_vaddr() > self.va.to_vaddr(),
582 {
583 admit()
584 }
585
586 pub proof fn zero_rec_preserves_all_but_va(self, level: PagingLevel)
587 ensures
588 self.zero_below_level_rec(level).level == self.level,
589 self.zero_below_level_rec(level).continuations == self.continuations,
590 self.zero_below_level_rec(level).guard_level == self.guard_level,
591 self.zero_below_level_rec(level).prefix == self.prefix,
592 self.zero_below_level_rec(level).popped_too_high == self.popped_too_high,
593 decreases self.level - level,
594 {
595 if self.level > level {
596 self.zero_rec_preserves_all_but_va((level + 1) as u8);
597 }
598 }
599
600 pub proof fn zero_preserves_all_but_va(self)
601 ensures
602 self.zero_below_level().level == self.level,
603 self.zero_below_level().continuations == self.continuations,
604 self.zero_below_level().guard_level == self.guard_level,
605 self.zero_below_level().prefix == self.prefix,
606 self.zero_below_level().popped_too_high == self.popped_too_high,
607 {
608 self.zero_rec_preserves_all_but_va(1u8);
609 }
610
611 pub open spec fn cur_va(self) -> Vaddr {
612 self.va.to_vaddr()
613 }
614
615 pub open spec fn cur_va_range(self) -> Range<AbstractVaddr> {
616 let start = self.va.align_down(self.level as int);
617 let end = self.va.align_up(self.level as int);
618 Range { start, end }
619 }
620
621 pub proof fn cur_va_range_reflects_view(self)
622 requires
623 self.inv(),
624 ensures
625 self.cur_va_range().start.reflect(self@.query_range().start),
626 self.cur_va_range().end.reflect(self@.query_range().end),
627 {
628 admit()
629 }
630
631 pub axiom fn cur_va_in_subtree_range(self)
634 requires
635 self.inv(),
636 ensures
637 vaddr(self.cur_subtree().value.path) <= self.cur_va() < vaddr(self.cur_subtree().value.path) + page_size((self.level - 1) as PagingLevel);
638
639 pub proof fn cur_subtree_eq_filtered_mappings(self)
644 requires
645 self.inv(),
646 ensures
647 PageTableOwner(self.cur_subtree())@.mappings ==
648 self@.mappings.filter(|m: Mapping| self@.cur_va <= m.va_range.start < self@.cur_va + page_size(self.level)),
649 {
650 let cur_subtree = self.cur_subtree();
651 let cur_path = cur_subtree.value.path;
652 let cur_va = self.cur_va();
653 let size = page_size(self.level);
654
655 let subtree_mappings = PageTableOwner(cur_subtree)@.mappings;
656 let filtered = self@.mappings.filter(|m: Mapping| cur_va <= m.va_range.start < cur_va + size);
657
658 assert forall |m: Mapping| subtree_mappings.contains(m) implies filtered.contains(m) by {
660 admit();
666 };
667
668 assert forall |m: Mapping| filtered.contains(m) implies subtree_mappings.contains(m) by {
670 assume(self.view_mappings().contains(m));
675
676 let i = choose|i: int| self.level - 1 <= i < NR_LEVELS - 1
678 && #[trigger] self.continuations[i].view_mappings().contains(m);
679 self.inv_continuation(i);
680
681 let cont_i = self.continuations[i];
682 let j = choose|j: int| #![auto] 0 <= j < NR_ENTRIES
683 && cont_i.children[j] is Some
684 && PageTableOwner(cont_i.children[j].unwrap())
685 .view_rec(cont_i.path().push_tail(j as usize)).contains(m);
686
687 admit();
692 };
693
694 assert(subtree_mappings =~= filtered);
695 }
696
697 pub axiom fn subtree_va_ranges_disjoint(self, j: int)
699 requires
700 self.inv(),
701 0 <= j < NR_ENTRIES,
702 j != self.index(),
703 self.continuations[self.level - 1].children[j] is Some,
704 ensures
705 vaddr(self.continuations[self.level - 1].path().push_tail(j as usize)) + page_size((self.level - 1) as PagingLevel) <= self.cur_va()
706 || self.cur_va() < vaddr(self.continuations[self.level - 1].path().push_tail(j as usize));
707
708 pub axiom fn higher_level_children_disjoint(self, i: int, j: int)
711 requires
712 self.inv(),
713 self.level - 1 < i < NR_LEVELS - 1,
714 0 <= j < NR_ENTRIES,
715 j != self.continuations[i].idx,
716 self.continuations[i].children[j] is Some,
717 ensures
718 vaddr(self.continuations[i].path().push_tail(j as usize)) + page_size(i as PagingLevel) <= self.cur_va()
719 || self.cur_va() < vaddr(self.continuations[i].path().push_tail(j as usize));
720
721 pub proof fn mapping_covering_cur_va_from_cur_subtree(self, m: Mapping)
725 requires
726 self.inv(),
727 self.view_mappings().contains(m),
728 m.va_range.start <= self.cur_va() < m.va_range.end,
729 ensures
730 PageTableOwner(self.cur_subtree()).view_rec(self.cur_subtree().value.path).contains(m),
731 {
732 let cur_va = self.cur_va();
733
734 let i = choose|i: int| self.level - 1 <= i < NR_LEVELS - 1
736 && #[trigger] self.continuations[i].view_mappings().contains(m);
737 self.inv_continuation(i);
738
739 let cont_i = self.continuations[i];
740
741 let j = choose|j: int| #![auto] 0 <= j < NR_ENTRIES
743 && cont_i.children[j] is Some
744 && PageTableOwner(cont_i.children[j].unwrap())
745 .view_rec(cont_i.path().push_tail(j as usize)).contains(m);
746
747 let child_j = cont_i.children[j].unwrap();
748 let path_j = cont_i.path().push_tail(j as usize);
749
750 PageTableOwner(child_j).view_rec_vaddr_range(path_j, m);
752
753 assert(vaddr(path_j) <= m.va_range.start);
757 assert(m.va_range.start <= cur_va);
758 assert(vaddr(path_j) <= cur_va);
759
760 if i == self.level - 1 {
762 if j as usize != self.index() {
764 self.subtree_va_ranges_disjoint(j);
766 assert(false) by { admit() };
775 }
776 assert(j as usize == self.index());
778 } else {
779 if j as usize != cont_i.idx as usize {
784 self.higher_level_children_disjoint(i, j);
786 assert(false) by { admit() };
790 } else {
791 assert(i >= self.level);
794 assert(self.continuations[i].all_but_index_some());
795 assert(false) by { admit() };
799 }
800 }
801 }
802
803 pub proof fn inv_continuation(self, i: int)
804 requires
805 self.inv(),
806 self.level - 1 <= i <= NR_LEVELS - 1,
807 ensures
808 self.continuations.contains_key(i),
809 self.continuations[i].inv(),
810 self.continuations[i].children.len() == NR_ENTRIES,
811 {
812 assert(self.continuations.contains_key(i));
813 }
814
815 pub open spec fn view_mappings(self) -> Set<Mapping>
816 {
817 Set::new(
818 |m: Mapping|
819 exists|i:int|
820 #![trigger self.continuations[i]]
821 self.level - 1 <= i < NR_LEVELS - 1 && self.continuations[i].view_mappings().contains(m)
822 )
823 }
824
825 pub proof fn view_mappings_take_lowest(self, new: Self)
826 requires
827 self.inv(),
828 new.continuations == self.continuations.remove(self.level - 1),
829 ensures
830 new.view_mappings() == self.view_mappings() - self.continuations[self.level - 1].view_mappings(),
831 {
832 admit()
833 }
834
835 pub proof fn view_mappings_put_lowest(self, new: Self, cont: CursorContinuation<C>)
836 requires
837 cont.inv(),
838 new.inv(),
839 new.continuations == self.continuations.insert(self.level - 1, cont),
840 ensures
841 new.view_mappings() == self.view_mappings() + cont.view_mappings(),
842 {
843 admit()
844 }
845
846 pub open spec fn as_page_table_owner(self) -> PageTableOwner<C> {
847 if self.level == 1 {
848 let l1 = self.continuations[0];
849 let l2 = self.continuations[1].restore_spec(l1).0;
850 let l3 = self.continuations[2].restore_spec(l2).0;
851 let l4 = self.continuations[3].restore_spec(l3).0;
852 l4.as_page_table_owner()
853 } else if self.level == 2 {
854 let l2 = self.continuations[1];
855 let l3 = self.continuations[2].restore_spec(l2).0;
856 let l4 = self.continuations[3].restore_spec(l3).0;
857 l4.as_page_table_owner()
858 } else if self.level == 3 {
859 let l3 = self.continuations[2];
860 let l4 = self.continuations[3].restore_spec(l3).0;
861 l4.as_page_table_owner()
862 } else {
863 let l4 = self.continuations[3];
864 l4.as_page_table_owner()
865 }
866 }
867
868 pub proof fn as_page_table_owner_preserves_view_mappings(self)
869 requires
870 self.inv(),
871 ensures
872 self.as_page_table_owner().view_rec(self.continuations[3].path()) == self.view_mappings(),
873 {
874 admit()
875 }
876
877 pub open spec fn cur_entry_owner(self) -> EntryOwner<C> {
878 self.cur_subtree().value
879 }
880
881 pub open spec fn cur_subtree(self) -> OwnerSubtree<C> {
882 self.continuations[self.level - 1].children[self.index() as int].unwrap()
883 }
884
885 pub open spec fn locked_range(self) -> Range<Vaddr> {
886 let start = self.prefix.align_down(self.guard_level as int).to_vaddr();
887 let end = self.prefix.align_up(self.guard_level as int).to_vaddr();
888 Range { start, end }
889 }
890
891 pub open spec fn in_locked_range(self) -> bool {
892 self.locked_range().start <= self.va.to_vaddr() < self.locked_range().end
893 }
894
895 pub open spec fn above_locked_range(self) -> bool {
896 self.va.to_vaddr() >= self.locked_range().end
897 }
898
899 pub proof fn prefix_in_locked_range(self)
900 requires
901 forall|i:int| i >= self.guard_level ==> self.va.index[i] == self.prefix.index[i],
902 ensures
903 self.in_locked_range(),
904 { admit() }
905
906 pub proof fn in_locked_range_level_lt_nr_levels(self)
908 requires
909 self.inv(),
910 self.in_locked_range(),
911 !self.popped_too_high,
912 ensures
913 self.level < NR_LEVELS,
914 {
915 assert(self.above_locked_range() ==> self.va.to_vaddr() >= self.locked_range().end);
916 assert(self.in_locked_range() ==> self.va.to_vaddr() < self.locked_range().end);
917 assert(self.in_locked_range() ==> !self.above_locked_range());
918 assert(!self.popped_too_high ==> self.level < self.guard_level || self.above_locked_range());
919 assert(self.level < self.guard_level);
920 assert(self.guard_level <= NR_LEVELS);
921 }
922
923 pub proof fn node_within_locked_range(self, level: PagingLevel)
931 requires
932 self.in_locked_range(),
933 1 <= level < self.guard_level,
934 self.va.inv(),
935 ensures
936 self.locked_range().start <= nat_align_down(self.va.to_vaddr() as nat, page_size((level + 1) as PagingLevel) as nat) as usize,
937 nat_align_down(self.va.to_vaddr() as nat, page_size((level + 1) as PagingLevel) as nat) as usize + page_size((level + 1) as PagingLevel) <= self.locked_range().end,
938 {
939 admit()
940 }
941
942 pub proof fn cur_entry_absent_not_present(self)
948 requires
949 self.inv(),
950 self.cur_entry_owner().is_absent(),
951 ensures
952 !self@.present(),
953 {
954 let cur_va = self.cur_va();
955 let cur_subtree = self.cur_subtree();
956 let cur_path = cur_subtree.value.path;
957
958 PageTableOwner(cur_subtree).view_rec_absent_empty(cur_path);
961 assert(PageTableOwner(cur_subtree).view_rec(cur_path) =~= set![]);
962
963 assert forall |m: Mapping| self.view_mappings().contains(m) implies
965 !(m.va_range.start <= cur_va < m.va_range.end) by {
966
967 if m.va_range.start <= cur_va < m.va_range.end {
968 self.mapping_covering_cur_va_from_cur_subtree(m);
969 assert(PageTableOwner(cur_subtree).view_rec(cur_path).contains(m));
970 assert(PageTableOwner(cur_subtree).view_rec(cur_path) =~= set![]);
971 assert(false);
972 }
973 };
974
975 let mappings = self@.mappings;
977 let filtered = mappings.filter(|m: Mapping| m.va_range.start <= self@.cur_va < m.va_range.end);
978
979 assert(filtered =~= set![]) by {
981 assert forall |m: Mapping| !filtered.contains(m) by {
982 if mappings.contains(m) && m.va_range.start <= self@.cur_va < m.va_range.end {
983 assert(self.view_mappings().contains(m));
984 assert(!(m.va_range.start <= cur_va < m.va_range.end));
985 }
986 };
987 };
988
989 assert(filtered.len() == 0);
991 assert(!self@.present());
992 }
993
994 pub proof fn cur_entry_frame_present(self)
995 requires
996 self.inv(),
997 self.cur_entry_owner().is_frame(),
998 ensures
999 self@.present(),
1000 self@.query(self.cur_entry_owner().frame.unwrap().mapped_pa,
1001 self.cur_entry_owner().frame.unwrap().size,
1002 self.cur_entry_owner().frame.unwrap().prop),
1003 {
1004 admit()
1005 }
1006
1007 pub open spec fn relate_region(self, regions: MetaRegionOwners) -> bool
1008 {
1009 &&& self.map_full_tree(|entry_owner: EntryOwner<C>, path: TreePath<NR_ENTRIES>|
1010 entry_owner.relate_region(regions))
1011 &&& self.map_full_tree(PageTableOwner::<C>::path_tracked_pred(regions))
1012 }
1013
1014 pub open spec fn not_in_tree(self, owner: EntryOwner<C>) -> bool {
1015 self.map_full_tree(|owner0: EntryOwner<C>, path: TreePath<NR_ENTRIES>|
1016 owner0.meta_slot_paddr_neq(owner))
1017 }
1018
1019 pub proof fn absent_not_in_tree(self, owner: EntryOwner<C>)
1020 requires
1021 self.inv(),
1022 owner.is_absent(),
1023 ensures
1024 self.not_in_tree(owner),
1025 {
1026 admit()
1027 }
1028
1029 pub proof fn relate_region_preserved(self, other: Self, regions0: MetaRegionOwners, regions1: MetaRegionOwners)
1030 requires
1031 self.inv(),
1032 self.relate_region(regions0),
1033 self.level == other.level,
1034 self.continuations =~= other.continuations,
1035 OwnerSubtree::implies(
1036 PageTableOwner::<C>::relate_region_pred(regions0),
1037 PageTableOwner::<C>::relate_region_pred(regions1)),
1038 OwnerSubtree::implies(
1039 PageTableOwner::<C>::path_tracked_pred(regions0),
1040 PageTableOwner::<C>::path_tracked_pred(regions1)),
1041 ensures
1042 other.relate_region(regions1),
1043 {
1044 let e = PageTableOwner::<C>::path_tracked_pred(regions0);
1045 let f = PageTableOwner::relate_region_pred(regions0);
1046 let g = PageTableOwner::relate_region_pred(regions1);
1047 let h = PageTableOwner::<C>::path_tracked_pred(regions1);
1048
1049 assert forall|i: int| #![auto] self.level - 1 <= i < NR_LEVELS implies {
1050 &&& other.continuations[i].map_children(g)
1051 &&& other.continuations[i].map_children(h)
1052 } by {
1053 let cont = self.continuations[i];
1054 assert(cont.inv());
1055 assert(cont.map_children(f));
1056 assert(cont.map_children(e));
1057 assert(cont == other.continuations[i]);
1058 assert forall |j: int| 0 <= j < NR_ENTRIES && #[trigger] cont.children[j] is Some implies
1059 cont.children[j].unwrap().tree_predicate_map(cont.path().push_tail(j as usize), g) by {
1060 cont.children[j].unwrap().map_implies(cont.path().push_tail(j as usize), f, g);
1061 };
1062 assert forall |j: int| 0 <= j < NR_ENTRIES && #[trigger] cont.children[j] is Some implies
1063 cont.children[j].unwrap().tree_predicate_map(cont.path().push_tail(j as usize), h) by {
1064 cont.children[j].unwrap().map_implies(cont.path().push_tail(j as usize), e, h);
1065 };
1066 };
1067 }
1068
1069 pub open spec fn set_va_spec(self, new_va: AbstractVaddr) -> Self {
1070 Self {
1071 va: new_va,
1072 ..self
1073 }
1074 }
1075
1076 pub axiom fn set_va(tracked &mut self, new_va: AbstractVaddr)
1077 requires
1078 forall |i: int| #![auto] old(self).level - 1 <= i < NR_LEVELS ==> new_va.index[i] == old(self).va.index[i],
1079 forall |i: int| #![auto] old(self).guard_level - 1 <= i < NR_LEVELS ==> new_va.index[i] == old(self).prefix.index[i],
1080 ensures
1081 *self == old(self).set_va_spec(new_va);
1082
1083}
1084
1085pub tracked struct CursorView<C: PageTableConfig> {
1086 pub cur_va: Vaddr,
1087 pub mappings: Set<Mapping>,
1088 pub phantom: PhantomData<C>,
1089}
1090
1091impl<'rcu, C: PageTableConfig> View for CursorOwner<'rcu, C> {
1092 type V = CursorView<C>;
1093
1094 open spec fn view(&self) -> Self::V {
1095 CursorView {
1096 cur_va: self.cur_va(),
1097 mappings: self.view_mappings(),
1098 phantom: PhantomData,
1099 }
1100 }
1101}
1102
1103impl<C: PageTableConfig> Inv for CursorView<C> {
1104 open spec fn inv(self) -> bool {
1105 &&& self.cur_va < MAX_USERSPACE_VADDR
1106 &&& forall|m: Mapping| #![auto] self.mappings.contains(m) ==> m.inv()
1107 &&& forall|m: Mapping, n: Mapping| #![auto]
1108 self.mappings.contains(m) ==>
1109 self.mappings.contains(n) ==>
1110 m != n ==>
1111 m.va_range.end <= n.va_range.start || n.va_range.end <= m.va_range.start
1112 }
1113}
1114
1115impl<'rcu, C: PageTableConfig> InvView for CursorOwner<'rcu, C> {
1116 proof fn view_preserves_inv(self) {
1117 assert(self@.inv()) by { admit() };
1118 }
1119}
1120
1121impl<'rcu, C: PageTableConfig, A: InAtomicMode> Inv for Cursor<'rcu, C, A> {
1122 open spec fn inv(self) -> bool {
1123 &&& 1 <= self.level <= NR_LEVELS
1124 &&& self.level <= self.guard_level <= NR_LEVELS
1125}
1127}
1128
1129impl<'rcu, C: PageTableConfig, A: InAtomicMode> OwnerOf for Cursor<'rcu, C, A> {
1130 type Owner = CursorOwner<'rcu, C>;
1131
1132 open spec fn wf(self, owner: Self::Owner) -> bool {
1133 &&& owner.va.reflect(self.va)
1134 &&& self.level == owner.level
1135 &&& owner.guard_level == self.guard_level
1136&&& self.level <= 4 ==> {
1138 &&& self.path[3] is Some
1139 &&& owner.continuations.contains_key(3)
1140 &&& owner.continuations[3].guard_perm.pptr() == self.path[3].unwrap()
1141 }
1142 &&& self.level <= 3 ==> {
1143 &&& self.path[2] is Some
1144 &&& owner.continuations.contains_key(2)
1145 &&& owner.continuations[2].guard_perm.pptr() == self.path[2].unwrap()
1146 }
1147 &&& self.level <= 2 ==> {
1148 &&& self.path[1] is Some
1149 &&& owner.continuations.contains_key(1)
1150 &&& owner.continuations[1].guard_perm.pptr() == self.path[1].unwrap()
1151 }
1152 &&& self.level == 1 ==> {
1153 &&& self.path[0] is Some
1154 &&& owner.continuations.contains_key(0)
1155 &&& owner.continuations[0].guard_perm.pptr() == self.path[0].unwrap()
1156 }
1157 &&& self.barrier_va.start == owner.locked_range().start
1158 &&& self.barrier_va.end == owner.locked_range().end
1159 }
1160}
1161
1162impl<'rcu, C: PageTableConfig, A: InAtomicMode> ModelOf for Cursor<'rcu, C, A> {
1163
1164}
1165
1166}