1use core::ops::Range;
47
48use vstd::prelude::*;
49use vstd_extra::ownership::*;
50
51use crate::specs::{
52 arch::*,
53 mm::{
54 frame::{
55 mapping::frame_to_index, meta_owners::PageUsage, meta_region_owners::MetaRegionOwners,
56 },
57 page_table::{cursor::owners::CursorOwner, node::Guards},
58 tlb::TlbModel,
59 },
60};
61
62use crate::mm::{
63 Paddr, Vaddr,
64 frame::{
65 UFrame,
66 meta::{REF_COUNT_MAX, REF_COUNT_UNIQUE, REF_COUNT_UNUSED},
67 },
68 page_prop::PageProperty,
69 vm_space::{UserPtConfig, vm_space_specs::VmSpaceOwner},
70};
71
72use super::{CursorEntry, CursorKind, VmSpaceId, tracked_cursor_entry_new};
73
74verus! {
75
76pub axiom fn vm_space_cursor_embedded<'a, 'rcu>(
93 tracked vm_space: &VmSpaceOwner,
94 tracked regions: &mut MetaRegionOwners,
95 va: Range<Vaddr>,
96) -> (tracked res: Option<(CursorOwner<'rcu, UserPtConfig>, Guards<'rcu>)>)
97 requires
98 vm_space.inv(),
99 old(regions).inv(),
100 ensures
101 final(regions).inv(),
102 final(regions).slots == old(regions).slots,
110 forall|i: int|
111 #![trigger final(regions).slot_owners[i]]
112 final(regions).slot_owners[i].inner_perms.in_list == old(
113 regions,
114 ).slot_owners[i].inner_perms.in_list,
115 forall|i: int|
120 #![trigger final(regions).slot_owners[i]]
121 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
122 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
123 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
124 &&& final(regions).slot_owners[i].usage !is Frame
125 },
126 forall|c: CursorOwner<'rcu, UserPtConfig>|
127 #![auto]
128 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
129 res matches Some((c, g)) ==> {
130 &&& c.inv()
131 &&& c.children_not_locked(g)
132 &&& c.nodes_locked(g)
133 &&& !c.popped_too_high
134 &&& c.metaregion_sound(*final(regions))
135 },
136;
137
138pub axiom fn vm_space_cursor_mut_embedded<'a, 'rcu>(
140 tracked vm_space: &VmSpaceOwner,
141 tracked regions: &mut MetaRegionOwners,
142 va: Range<Vaddr>,
143) -> (tracked res: Option<(CursorOwner<'rcu, UserPtConfig>, Guards<'rcu>)>)
144 requires
145 vm_space.inv(),
146 old(regions).inv(),
147 ensures
148 final(regions).inv(),
149 final(regions).slots == old(regions).slots,
157 forall|i: int|
158 #![trigger final(regions).slot_owners[i]]
159 final(regions).slot_owners[i].inner_perms.in_list == old(
160 regions,
161 ).slot_owners[i].inner_perms.in_list,
162 forall|i: int|
167 #![trigger final(regions).slot_owners[i]]
168 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
169 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
170 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
171 &&& final(regions).slot_owners[i].usage !is Frame
172 },
173 forall|c: CursorOwner<'rcu, UserPtConfig>|
174 #![auto]
175 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
176 res matches Some((c, g)) ==> {
177 &&& c.inv()
178 &&& c.children_not_locked(g)
179 &&& c.nodes_locked(g)
180 &&& !c.popped_too_high
181 &&& c.metaregion_sound(*final(regions))
182 },
183;
184
185pub axiom fn cursor_query_embedded<'rcu>(
211 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
212 tracked regions: &mut MetaRegionOwners,
213 tracked guards: &mut Guards<'rcu>,
214) -> (res: Option<Paddr>)
215 requires
216 old(owner).inv(),
217 old(regions).inv(),
218 old(owner).children_not_locked(*old(guards)),
219 old(owner).nodes_locked(*old(guards)),
220 old(owner).metaregion_sound(*old(regions)),
221 !old(owner).popped_too_high,
222 ensures
223 final(owner).inv(),
224 final(regions).inv(),
225 final(owner).children_not_locked(*final(guards)),
226 final(owner).nodes_locked(*final(guards)),
227 final(owner).metaregion_sound(*final(regions)),
228 !final(owner).popped_too_high,
229 final(regions).slots == old(regions).slots,
231 res is None ==> forall|i: int|
233 #![trigger final(regions).slot_owners[i]]
234 final(regions).slot_owners[i] == old(regions).slot_owners[i],
235 res matches Some(paddr) ==> {
239 &&& valid_frame_paddr(paddr)
240 &&& old(regions).slot_owners[frame_to_index(paddr)].usage is Frame
241 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == (
242 old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
243 + 1) as nat
244 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
245 <= REF_COUNT_MAX
246 &&& forall|i: int|
247 #![trigger final(regions).slot_owners[i]]
248 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
249 regions,
250 ).slot_owners[i]
251 &&& final(regions).slot_owners[frame_to_index(paddr)].slot_vaddr == old(
255 regions,
256 ).slot_owners[frame_to_index(paddr)].slot_vaddr
257 &&& final(regions).slot_owners[frame_to_index(paddr)].usage == old(
258 regions,
259 ).slot_owners[frame_to_index(paddr)].usage
260 &&& final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt == old(
261 regions,
262 ).slot_owners[frame_to_index(paddr)].paths_in_pt
263 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.in_list == old(
264 regions,
265 ).slot_owners[frame_to_index(paddr)].inner_perms.in_list
266 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage == old(
267 regions,
268 ).slot_owners[frame_to_index(paddr)].inner_perms.storage
269 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.vtable_ptr == old(
270 regions,
271 ).slot_owners[frame_to_index(paddr)].inner_perms.vtable_ptr
272 },
273 forall|c: CursorOwner<'rcu, UserPtConfig>|
274 #![auto]
275 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
276;
277
278pub proof fn lemma_cursor_jump_embedded<'rcu>(
290 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
291 tracked regions: &mut MetaRegionOwners,
292 tracked guards: &mut Guards<'rcu>,
293 va: Vaddr,
294)
295 requires
296 old(owner).inv(),
297 old(regions).inv(),
298 old(owner).children_not_locked(*old(guards)),
299 old(owner).nodes_locked(*old(guards)),
300 old(owner).metaregion_sound(*old(regions)),
301 !old(owner).popped_too_high,
302 ensures
303 final(owner).inv(),
304 final(regions).inv(),
305 final(owner).children_not_locked(*final(guards)),
306 final(owner).nodes_locked(*final(guards)),
307 final(owner).metaregion_sound(*final(regions)),
308 !final(owner).popped_too_high,
309 final(regions).slots == old(regions).slots,
313 forall|i: int|
314 #![trigger final(regions).slot_owners[i]]
315 final(regions).slot_owners[i] == old(regions).slot_owners[i],
316 forall|c: CursorOwner<'rcu, UserPtConfig>|
317 #![auto]
318 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
319{
320}
321
322pub axiom fn cursor_mut_map_embedded<'rcu>(
335 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
336 tracked regions: &mut MetaRegionOwners,
337 tracked guards: &mut Guards<'rcu>,
338 tracked tlb_model: &mut TlbModel,
339 paddr: Paddr,
340 prop: PageProperty,
341)
342 requires
343 old(owner).inv(),
344 old(regions).inv(),
345 old(owner).children_not_locked(*old(guards)),
346 old(owner).nodes_locked(*old(guards)),
347 old(owner).metaregion_sound(*old(regions)),
348 !old(owner).popped_too_high,
349 old(tlb_model).inv(),
350 valid_frame_paddr(
354 paddr,
355 ),
356ensures
361 final(owner).inv(),
362 final(regions).inv(),
363 final(owner).children_not_locked(*final(guards)),
364 final(owner).nodes_locked(*final(guards)),
365 final(owner).metaregion_sound(*final(regions)),
366 !final(owner).popped_too_high,
367 final(tlb_model).inv(),
368 final(regions).slots == old(regions).slots,
369 forall|i: int|
372 #![trigger final(regions).slot_owners[i]]
373 final(regions).slot_owners[i].inner_perms.in_list == old(
374 regions,
375 ).slot_owners[i].inner_perms.in_list,
376 forall|i: int|
382 #![trigger final(regions).slot_owners[i]]
383 i != frame_to_index(paddr) && old(regions).slot_owners[i].inner_perms.ref_count.value()
384 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i] == old(
385 regions,
386 ).slot_owners[i],
387 forall|i: int|
390 #![trigger final(regions).slot_owners[i].inner_perms.ref_count.value()]
391 old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
392 ==> final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED,
393 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == old(
406 regions,
407 ).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value(),
408 final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt.len() == old(
413 regions,
414 ).slot_owners[frame_to_index(paddr)].paths_in_pt.len() + 1,
415 final(regions).slot_owners[frame_to_index(paddr)].usage == old(
419 regions,
420 ).slot_owners[frame_to_index(paddr)].usage,
421 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage == old(
422 regions,
423 ).slot_owners[frame_to_index(paddr)].inner_perms.storage,
424 forall|i: int|
426 #![trigger final(regions).slot_owners[i]]
427 final(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
428 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
429 forall|i: int|
438 #![trigger final(regions).slot_owners[i]]
439 i != frame_to_index(paddr) && old(regions).slot_owners[i].inner_perms.ref_count.value()
440 == REF_COUNT_UNUSED && final(regions).slot_owners[i].inner_perms.ref_count.value()
441 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i].usage !is Frame,
442 forall|c: CursorOwner<'rcu, UserPtConfig>|
443 #![auto]
444 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
445;
446
447pub axiom fn cursor_mut_unmap_embedded<'rcu>(
456 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
457 tracked regions: &mut MetaRegionOwners,
458 tracked guards: &mut Guards<'rcu>,
459 tracked tlb_model: &mut TlbModel,
460 len: usize,
461)
462 requires
463 old(owner).inv(),
464 old(regions).inv(),
465 old(owner).children_not_locked(*old(guards)),
466 old(owner).nodes_locked(*old(guards)),
467 old(owner).metaregion_sound(*old(regions)),
468 !old(owner).popped_too_high,
469 old(tlb_model).inv(),
470 ensures
471 final(owner).inv(),
472 final(regions).inv(),
473 final(owner).children_not_locked(*final(guards)),
474 final(owner).nodes_locked(*final(guards)),
475 final(owner).metaregion_sound(*final(regions)),
476 !final(owner).popped_too_high,
477 final(tlb_model).inv(),
478 final(regions).slots == old(regions).slots,
480 forall|i: int|
486 #![trigger final(regions).slot_owners[i]]
487 {
488 &&& final(regions).slot_owners[i].slot_vaddr == old(
489 regions,
490 ).slot_owners[i].slot_vaddr
491 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
492 &&& final(regions).slot_owners[i].inner_perms.in_list == old(
493 regions,
494 ).slot_owners[i].inner_perms.in_list
495 &&& final(regions).slot_owners[i].inner_perms.vtable_ptr == old(
496 regions,
497 ).slot_owners[i].inner_perms.vtable_ptr
498 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNIQUE
500 ==> final(regions).slot_owners[i].inner_perms.ref_count.value()
501 != REF_COUNT_UNIQUE
502 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
504 ==> final(regions).slot_owners[i].inner_perms.storage == old(
505 regions,
506 ).slot_owners[i].inner_perms.storage
507 },
508 forall|i: int|
514 #![trigger final(regions).slot_owners[i]]
515 !old(regions).slots.contains_key(i) ==> final(regions).slot_owners[i] == old(
516 regions,
517 ).slot_owners[i],
518 forall|i: int|
530 #![trigger final(regions).slot_owners[i]]
531 old(regions).slot_owners[i].usage is Frame ==> {
532 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() + old(
533 regions,
534 ).slot_owners[i].paths_in_pt.len() == old(
535 regions,
536 ).slot_owners[i].inner_perms.ref_count.value()
537 + final(regions).slot_owners[i].paths_in_pt.len()
538 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() <= old(
539 regions,
540 ).slot_owners[i].inner_perms.ref_count.value()
541 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
542 regions,
543 ).slot_owners[i].paths_in_pt.len()
544 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != 0
545 },
546 forall|i: int|
554 #![trigger final(regions).slot_owners[i]]
555 old(regions).slot_owners[i].usage == PageUsage::MMIO ==> final(regions).slot_owners[i]
556 == old(regions).slot_owners[i],
557 forall|c: CursorOwner<'rcu, UserPtConfig>|
558 #![auto]
559 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
560;
561
562pub enum CursorMutRegionsMethod {
569 Unmap(usize),
570}
571
572pub(super) proof fn open_cursor_step<'a, 'rcu>(
585 tracked vm_space: &VmSpaceOwner,
586 tracked regions: &mut MetaRegionOwners,
587 vs: VmSpaceId,
588 va: Range<Vaddr>,
589) -> (tracked res: Option<CursorEntry<'rcu>>)
590 requires
591 vm_space.inv(),
592 old(regions).inv(),
593 ensures
594 final(regions).inv(),
595 final(regions).slots == old(regions).slots,
603 forall|i: int|
604 #![trigger final(regions).slot_owners[i]]
605 final(regions).slot_owners[i].inner_perms.in_list == old(
606 regions,
607 ).slot_owners[i].inner_perms.in_list,
608 forall|i: int|
613 #![trigger final(regions).slot_owners[i]]
614 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
615 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
616 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
617 &&& final(regions).slot_owners[i].usage !is Frame
618 },
619 forall|c: CursorOwner<'rcu, UserPtConfig>|
620 #![auto]
621 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
622 res matches Some(e) ==> e.inv(),
623 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
624 res matches Some(e) ==> e.kind == CursorKind::ReadOnly,
625 res matches Some(e) ==> e.va == va,
626 res matches Some(e) ==> e.vm_space == vs,
627{
628 let tracked owner_opt = vm_space_cursor_embedded(vm_space, regions, va);
629 match owner_opt {
630 Option::Some((owner, guards)) => {
631 let tracked entry = tracked_cursor_entry_new(
632 vs,
633 CursorKind::ReadOnly,
634 va,
635 owner,
636 guards,
637 );
638 Option::Some(entry)
639 },
640 Option::None => Option::None,
641 }
642}
643
644pub(super) proof fn open_cursor_mut_step<'a, 'rcu>(
648 tracked vm_space: &VmSpaceOwner,
649 tracked regions: &mut MetaRegionOwners,
650 vs: VmSpaceId,
651 va: Range<Vaddr>,
652) -> (tracked res: Option<CursorEntry<'rcu>>)
653 requires
654 vm_space.inv(),
655 old(regions).inv(),
656 ensures
657 final(regions).inv(),
658 final(regions).slots == old(regions).slots,
659 forall|i: int|
660 #![trigger final(regions).slot_owners[i]]
661 final(regions).slot_owners[i].inner_perms.in_list == old(
662 regions,
663 ).slot_owners[i].inner_perms.in_list,
664 forall|i: int|
665 #![trigger final(regions).slot_owners[i]]
666 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
667 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
668 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
669 &&& final(regions).slot_owners[i].usage !is Frame
670 },
671 forall|c: CursorOwner<'rcu, UserPtConfig>|
672 #![auto]
673 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
674 res matches Some(e) ==> e.inv(),
675 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
676 res matches Some(e) ==> e.kind == CursorKind::Mutable,
677 res matches Some(e) ==> e.va == va,
678 res matches Some(e) ==> e.vm_space == vs,
679{
680 let tracked owner_opt = vm_space_cursor_mut_embedded(vm_space, regions, va);
681 match owner_opt {
682 Option::Some((owner, guards)) => {
683 let tracked entry = tracked_cursor_entry_new(
684 vs,
685 CursorKind::Mutable,
686 va,
687 owner,
688 guards,
689 );
690 Option::Some(entry)
691 },
692 Option::None => Option::None,
693 }
694}
695
696pub(super) proof fn drop_cursor_step<'rcu>(tracked _entry: CursorEntry<'rcu>) {
699}
700
701pub(super) proof fn cursor_query_step<'rcu>(
716 tracked entry: &mut CursorEntry<'rcu>,
717 tracked regions: &mut MetaRegionOwners,
718) -> (res: Option<Paddr>)
719 requires
720 old(entry).inv(),
721 old(regions).inv(),
722 old(entry).owner.metaregion_sound(*old(regions)),
723 ensures
724 final(entry).vm_space == old(entry).vm_space,
725 final(entry).kind == old(entry).kind,
726 final(entry).va == old(entry).va,
727 final(entry).inv(),
728 final(regions).inv(),
729 final(entry).owner.metaregion_sound(*final(regions)),
730 final(regions).slots == old(regions).slots,
731 res is None ==> forall|i: int|
732 #![trigger final(regions).slot_owners[i]]
733 final(regions).slot_owners[i] == old(regions).slot_owners[i],
734 res matches Some(paddr) ==> {
735 &&& valid_frame_paddr(paddr)
736 &&& old(regions).slot_owners[frame_to_index(paddr)].usage is Frame
737 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == (
738 old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
739 + 1) as nat
740 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
741 <= REF_COUNT_MAX
742 &&& forall|i: int|
743 #![trigger final(regions).slot_owners[i]]
744 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
745 regions,
746 ).slot_owners[i]
747 &&& final(regions).slot_owners[frame_to_index(paddr)].usage == old(
748 regions,
749 ).slot_owners[frame_to_index(paddr)].usage
750 &&& final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt == old(
751 regions,
752 ).slot_owners[frame_to_index(paddr)].paths_in_pt
753 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.in_list == old(
754 regions,
755 ).slot_owners[frame_to_index(paddr)].inner_perms.in_list
756 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage == old(
757 regions,
758 ).slot_owners[frame_to_index(paddr)].inner_perms.storage
759 },
760 forall|c: CursorOwner<'rcu, UserPtConfig>|
761 #![auto]
762 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
763{
764 cursor_query_embedded(&mut entry.owner, regions, &mut entry.guards)
765}
766
767pub(super) proof fn cursor_find_next_step<'rcu>(
770 tracked entry: &mut CursorEntry<'rcu>,
771 tracked regions: &mut MetaRegionOwners,
772 len: usize,
773)
774 requires
775 old(entry).inv(),
776 old(regions).inv(),
777 old(entry).owner.metaregion_sound(*old(regions)),
778 ensures
779 final(entry).vm_space == old(entry).vm_space,
780 final(entry).kind == old(entry).kind,
781 final(entry).va == old(entry).va,
782 final(entry).inv(),
783 final(regions).inv(),
784 final(entry).owner.metaregion_sound(*final(regions)),
785 final(regions).slots == old(regions).slots,
786 forall|i: int|
789 #![trigger final(regions).slot_owners[i]]
790 final(regions).slot_owners[i] == old(regions).slot_owners[i],
791 forall|c: CursorOwner<'rcu, UserPtConfig>|
792 #![auto]
793 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
794{
795}
796
797pub(super) proof fn cursor_jump_step<'rcu>(
800 tracked entry: &mut CursorEntry<'rcu>,
801 tracked regions: &mut MetaRegionOwners,
802 va: Vaddr,
803)
804 requires
805 old(entry).inv(),
806 old(regions).inv(),
807 old(entry).owner.metaregion_sound(*old(regions)),
808 ensures
809 final(entry).vm_space == old(entry).vm_space,
810 final(entry).kind == old(entry).kind,
811 final(entry).va == old(entry).va,
812 final(entry).inv(),
813 final(regions).inv(),
814 final(entry).owner.metaregion_sound(*final(regions)),
815 final(regions).slots == old(regions).slots,
816 forall|i: int|
817 #![trigger final(regions).slot_owners[i]]
818 final(regions).slot_owners[i] == old(regions).slot_owners[i],
819 forall|c: CursorOwner<'rcu, UserPtConfig>|
820 #![auto]
821 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
822{
823 lemma_cursor_jump_embedded(&mut entry.owner, regions, &mut entry.guards, va)
824}
825
826pub(super) proof fn cursor_protect_next_step<'rcu>(
830 tracked entry: &mut CursorEntry<'rcu>,
831 tracked regions: &mut MetaRegionOwners,
832 len: usize,
833)
834 requires
835 old(entry).inv(),
836 old(regions).inv(),
837 old(entry).owner.metaregion_sound(*old(regions)),
838 ensures
839 final(entry).vm_space == old(entry).vm_space,
840 final(entry).kind == old(entry).kind,
841 final(entry).va == old(entry).va,
842 final(entry).inv(),
843 final(regions).inv(),
844 final(entry).owner.metaregion_sound(*final(regions)),
845 final(regions).slots == old(regions).slots,
846 forall|i: int|
847 #![trigger final(regions).slot_owners[i]]
848 final(regions).slot_owners[i] == old(regions).slot_owners[i],
849 forall|c: CursorOwner<'rcu, UserPtConfig>|
850 #![auto]
851 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
852{
853}
854
855pub(super) proof fn cursor_mut_regions_step<'rcu>(
859 tracked entry: &mut CursorEntry<'rcu>,
860 tracked regions: &mut MetaRegionOwners,
861 tracked tlb_model: &mut TlbModel,
862 method: CursorMutRegionsMethod,
863)
864 requires
865 old(entry).inv(),
866 old(regions).inv(),
867 old(entry).owner.metaregion_sound(*old(regions)),
868 old(tlb_model).inv(),
869 ensures
870 final(entry).vm_space == old(entry).vm_space,
871 final(entry).kind == old(entry).kind,
872 final(entry).va == old(entry).va,
873 final(entry).inv(),
874 final(regions).inv(),
875 final(entry).owner.metaregion_sound(*final(regions)),
876 final(tlb_model).inv(),
877 final(regions).slots == old(regions).slots,
884 forall|i: int|
885 #![trigger final(regions).slot_owners[i]]
886 {
887 &&& final(regions).slot_owners[i].slot_vaddr == old(
888 regions,
889 ).slot_owners[i].slot_vaddr
890 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
891 &&& final(regions).slot_owners[i].inner_perms.in_list == old(
892 regions,
893 ).slot_owners[i].inner_perms.in_list
894 &&& final(regions).slot_owners[i].inner_perms.vtable_ptr == old(
895 regions,
896 ).slot_owners[i].inner_perms.vtable_ptr
897 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNIQUE
898 ==> final(regions).slot_owners[i].inner_perms.ref_count.value()
899 != REF_COUNT_UNIQUE
900 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
901 ==> final(regions).slot_owners[i].inner_perms.storage == old(
902 regions,
903 ).slot_owners[i].inner_perms.storage
904 },
905 forall|i: int|
908 #![trigger final(regions).slot_owners[i]]
909 !old(regions).slots.contains_key(i) ==> final(regions).slot_owners[i] == old(
910 regions,
911 ).slot_owners[i],
912 forall|i: int|
913 #![trigger final(regions).slot_owners[i]]
914 old(regions).slot_owners[i].usage is Frame ==> {
915 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() + old(
916 regions,
917 ).slot_owners[i].paths_in_pt.len() == old(
918 regions,
919 ).slot_owners[i].inner_perms.ref_count.value()
920 + final(regions).slot_owners[i].paths_in_pt.len()
921 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() <= old(
922 regions,
923 ).slot_owners[i].inner_perms.ref_count.value()
924 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
925 regions,
926 ).slot_owners[i].paths_in_pt.len()
927 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != 0
928 },
929 forall|i: int|
930 #![trigger final(regions).slot_owners[i]]
931 old(regions).slot_owners[i].usage == PageUsage::MMIO ==> final(regions).slot_owners[i]
932 == old(regions).slot_owners[i],
933 forall|c: CursorOwner<'rcu, UserPtConfig>|
934 #![auto]
935 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
936{
937 match method {
938 CursorMutRegionsMethod::Unmap(len) => {
939 cursor_mut_unmap_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, len);
940 },
941 }
942}
943
944pub(super) proof fn map_step<'rcu>(
953 tracked entry: &mut CursorEntry<'rcu>,
954 tracked regions: &mut MetaRegionOwners,
955 tracked tlb_model: &mut TlbModel,
956 paddr: Paddr,
957 prop: PageProperty,
958)
959 requires
960 old(entry).inv(),
961 old(regions).inv(),
962 old(entry).owner.metaregion_sound(*old(regions)),
963 old(tlb_model).inv(),
964 valid_frame_paddr(paddr),
965 ensures
966 final(entry).vm_space == old(entry).vm_space,
967 final(entry).kind == old(entry).kind,
968 final(entry).va == old(entry).va,
969 final(entry).inv(),
970 final(regions).inv(),
971 final(entry).owner.metaregion_sound(*final(regions)),
972 final(tlb_model).inv(),
973 final(regions).slots == old(regions).slots,
974 forall|i: int|
976 #![trigger final(regions).slot_owners[i]]
977 final(regions).slot_owners[i].inner_perms.in_list == old(
978 regions,
979 ).slot_owners[i].inner_perms.in_list,
980 forall|i: int|
981 #![trigger final(regions).slot_owners[i]]
982 i != frame_to_index(paddr) && old(regions).slot_owners[i].inner_perms.ref_count.value()
983 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i] == old(
984 regions,
985 ).slot_owners[i],
986 forall|i: int|
987 #![trigger final(regions).slot_owners[i].inner_perms.ref_count.value()]
988 old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
989 ==> final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED,
990 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == old(
991 regions,
992 ).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value(),
993 final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt.len() == old(
994 regions,
995 ).slot_owners[frame_to_index(paddr)].paths_in_pt.len() + 1,
996 final(regions).slot_owners[frame_to_index(paddr)].usage == old(
997 regions,
998 ).slot_owners[frame_to_index(paddr)].usage,
999 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage == old(
1000 regions,
1001 ).slot_owners[frame_to_index(paddr)].inner_perms.storage,
1002 forall|i: int|
1003 #![trigger final(regions).slot_owners[i]]
1004 final(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
1005 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
1006 forall|i: int|
1007 #![trigger final(regions).slot_owners[i]]
1008 i != frame_to_index(paddr) && old(regions).slot_owners[i].inner_perms.ref_count.value()
1009 == REF_COUNT_UNUSED && final(regions).slot_owners[i].inner_perms.ref_count.value()
1010 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i].usage !is Frame,
1011 forall|c: CursorOwner<'rcu, UserPtConfig>|
1012 #![auto]
1013 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
1014{
1015 cursor_mut_map_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, paddr, prop);
1016}
1017
1018}