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].in_list_perm == old(regions).slot_owners[i].in_list_perm,
113 forall|i: int|
118 #![trigger final(regions).slot_owners[i]]
119 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
120 &&& old(regions).slot_owners[i].ref_count() == REF_COUNT_UNUSED
121 &&& final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
122 &&& final(regions).slot_owners[i].usage !is Frame
123 },
124 forall|c: CursorOwner<'rcu, UserPtConfig>|
125 #![auto]
126 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
127 res matches Some((c, g)) ==> {
128 &&& c.inv()
129 &&& c.children_not_locked(g)
130 &&& c.nodes_locked(g)
131 &&& !c.popped_too_high
132 &&& c.metaregion_sound(*final(regions))
133 },
134;
135
136pub axiom fn vm_space_cursor_mut_embedded<'a, 'rcu>(
138 tracked vm_space: &VmSpaceOwner,
139 tracked regions: &mut MetaRegionOwners,
140 va: Range<Vaddr>,
141) -> (tracked res: Option<(CursorOwner<'rcu, UserPtConfig>, Guards<'rcu>)>)
142 requires
143 vm_space.inv(),
144 old(regions).inv(),
145 ensures
146 final(regions).inv(),
147 final(regions).slots == old(regions).slots,
155 forall|i: int|
156 #![trigger final(regions).slot_owners[i]]
157 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
158 forall|i: int|
163 #![trigger final(regions).slot_owners[i]]
164 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
165 &&& old(regions).slot_owners[i].ref_count() == REF_COUNT_UNUSED
166 &&& final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
167 &&& final(regions).slot_owners[i].usage !is Frame
168 },
169 forall|c: CursorOwner<'rcu, UserPtConfig>|
170 #![auto]
171 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
172 res matches Some((c, g)) ==> {
173 &&& c.inv()
174 &&& c.children_not_locked(g)
175 &&& c.nodes_locked(g)
176 &&& !c.popped_too_high
177 &&& c.metaregion_sound(*final(regions))
178 },
179;
180
181pub axiom fn cursor_query_embedded<'rcu>(
207 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
208 tracked regions: &mut MetaRegionOwners,
209 tracked guards: &mut Guards<'rcu>,
210) -> (res: Option<Paddr>)
211 requires
212 old(owner).inv(),
213 old(regions).inv(),
214 old(owner).children_not_locked(*old(guards)),
215 old(owner).nodes_locked(*old(guards)),
216 old(owner).metaregion_sound(*old(regions)),
217 !old(owner).popped_too_high,
218 ensures
219 final(owner).inv(),
220 final(regions).inv(),
221 final(owner).children_not_locked(*final(guards)),
222 final(owner).nodes_locked(*final(guards)),
223 final(owner).metaregion_sound(*final(regions)),
224 !final(owner).popped_too_high,
225 final(regions).slots == old(regions).slots,
227 res is None ==> forall|i: int|
229 #![trigger final(regions).slot_owners[i]]
230 final(regions).slot_owners[i] == old(regions).slot_owners[i],
231 res matches Some(paddr) ==> {
235 &&& valid_frame_paddr(paddr)
236 &&& old(regions).slot_owner(paddr).usage is Frame
237 &&& final(regions).slot_owner(paddr).ref_count() == (old(regions).slot_owner(
238 paddr,
239 ).ref_count() + 1) as nat
240 &&& final(regions).slot_owner(paddr).ref_count() <= REF_COUNT_MAX
241 &&& forall|i: int|
242 #![trigger final(regions).slot_owners[i]]
243 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
244 regions,
245 ).slot_owners[i]
246 &&& final(regions).slot_owner(paddr).slot_vaddr == old(regions).slot_owner(
250 paddr,
251 ).slot_vaddr
252 &&& final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage
253 &&& final(regions).slot_owner(paddr).paths_in_pt == old(regions).slot_owner(
254 paddr,
255 ).paths_in_pt
256 &&& final(regions).slot_owner(paddr).in_list_perm == old(regions).slot_owner(
257 paddr,
258 ).in_list_perm
259 &&& final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
260 paddr,
261 ).storage_perm()
262 &&& final(regions).slot_owner(paddr).vtable_ptr_perm() == old(regions).slot_owner(
263 paddr,
264 ).vtable_ptr_perm()
265 },
266 forall|c: CursorOwner<'rcu, UserPtConfig>|
267 #![auto]
268 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
269;
270
271pub proof fn lemma_cursor_jump_embedded<'rcu>(
283 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
284 tracked regions: &mut MetaRegionOwners,
285 tracked guards: &mut Guards<'rcu>,
286 va: Vaddr,
287)
288 requires
289 old(owner).inv(),
290 old(regions).inv(),
291 old(owner).children_not_locked(*old(guards)),
292 old(owner).nodes_locked(*old(guards)),
293 old(owner).metaregion_sound(*old(regions)),
294 !old(owner).popped_too_high,
295 ensures
296 final(owner).inv(),
297 final(regions).inv(),
298 final(owner).children_not_locked(*final(guards)),
299 final(owner).nodes_locked(*final(guards)),
300 final(owner).metaregion_sound(*final(regions)),
301 !final(owner).popped_too_high,
302 final(regions).slots == old(regions).slots,
306 forall|i: int|
307 #![trigger final(regions).slot_owners[i]]
308 final(regions).slot_owners[i] == old(regions).slot_owners[i],
309 forall|c: CursorOwner<'rcu, UserPtConfig>|
310 #![auto]
311 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
312{
313}
314
315pub axiom fn cursor_mut_map_embedded<'rcu>(
328 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
329 tracked regions: &mut MetaRegionOwners,
330 tracked guards: &mut Guards<'rcu>,
331 tracked tlb_model: &mut TlbModel,
332 paddr: Paddr,
333 prop: PageProperty,
334)
335 requires
336 old(owner).inv(),
337 old(regions).inv(),
338 old(owner).children_not_locked(*old(guards)),
339 old(owner).nodes_locked(*old(guards)),
340 old(owner).metaregion_sound(*old(regions)),
341 !old(owner).popped_too_high,
342 old(tlb_model).inv(),
343 valid_frame_paddr(
347 paddr,
348 ),
349ensures
354 final(owner).inv(),
355 final(regions).inv(),
356 final(owner).children_not_locked(*final(guards)),
357 final(owner).nodes_locked(*final(guards)),
358 final(owner).metaregion_sound(*final(regions)),
359 !final(owner).popped_too_high,
360 final(tlb_model).inv(),
361 final(regions).slots == old(regions).slots,
362 forall|i: int|
365 #![trigger final(regions).slot_owners[i]]
366 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
367 forall|i: int|
373 #![trigger final(regions).slot_owners[i]]
374 i != frame_to_index(paddr) && old(regions).slot_owners[i].ref_count()
375 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i] == old(
376 regions,
377 ).slot_owners[i],
378 forall|i: int|
381 #![trigger final(regions).slot_owners[i].ref_count()]
382 old(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
383 ==> final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED,
384 final(regions).slot_owner(paddr).ref_count() == old(regions).slot_owner(paddr).ref_count(),
397 final(regions).slot_owner(paddr).paths_in_pt.len() == old(regions).slot_owner(
402 paddr,
403 ).paths_in_pt.len() + 1,
404 final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage,
408 final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
409 paddr,
410 ).storage_perm(),
411 forall|i: int|
413 #![trigger final(regions).slot_owners[i]]
414 final(regions).slot_owners[i].ref_count() == REF_COUNT_UNUSED
415 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
416 forall|i: int|
425 #![trigger final(regions).slot_owners[i]]
426 i != frame_to_index(paddr) && old(regions).slot_owners[i].ref_count()
427 == REF_COUNT_UNUSED && final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
428 ==> final(regions).slot_owners[i].usage !is Frame,
429 forall|c: CursorOwner<'rcu, UserPtConfig>|
430 #![auto]
431 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
432;
433
434pub axiom fn cursor_mut_unmap_embedded<'rcu>(
443 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
444 tracked regions: &mut MetaRegionOwners,
445 tracked guards: &mut Guards<'rcu>,
446 tracked tlb_model: &mut TlbModel,
447 len: usize,
448)
449 requires
450 old(owner).inv(),
451 old(regions).inv(),
452 old(owner).children_not_locked(*old(guards)),
453 old(owner).nodes_locked(*old(guards)),
454 old(owner).metaregion_sound(*old(regions)),
455 !old(owner).popped_too_high,
456 old(tlb_model).inv(),
457 ensures
458 final(owner).inv(),
459 final(regions).inv(),
460 final(owner).children_not_locked(*final(guards)),
461 final(owner).nodes_locked(*final(guards)),
462 final(owner).metaregion_sound(*final(regions)),
463 !final(owner).popped_too_high,
464 final(tlb_model).inv(),
465 final(regions).slots == old(regions).slots,
467 forall|i: int|
473 #![trigger final(regions).slot_owners[i]]
474 {
475 &&& final(regions).slot_owners[i].slot_vaddr == old(
476 regions,
477 ).slot_owners[i].slot_vaddr
478 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
479 &&& final(regions).slot_owners[i].in_list_perm == old(
480 regions,
481 ).slot_owners[i].in_list_perm
482 &&& final(regions).slot_owners[i].vtable_ptr_perm() == old(
483 regions,
484 ).slot_owners[i].vtable_ptr_perm()
485 &&& old(regions).slot_owners[i].ref_count() != REF_COUNT_UNIQUE
487 ==> final(regions).slot_owners[i].ref_count()
488 != REF_COUNT_UNIQUE
489 &&& final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
491 ==> final(regions).slot_owners[i].storage_perm() == old(
492 regions,
493 ).slot_owners[i].storage_perm()
494 },
495 forall|i: int|
501 #![trigger final(regions).slot_owners[i]]
502 !old(regions).slots.contains_key(i) ==> final(regions).slot_owners[i] == old(
503 regions,
504 ).slot_owners[i],
505 forall|i: int|
517 #![trigger final(regions).slot_owners[i]]
518 old(regions).slot_owners[i].usage is Frame ==> {
519 &&& final(regions).slot_owners[i].ref_count() + old(
520 regions,
521 ).slot_owners[i].paths_in_pt.len() == old(regions).slot_owners[i].ref_count()
522 + final(regions).slot_owners[i].paths_in_pt.len()
523 &&& final(regions).slot_owners[i].ref_count() <= old(
524 regions,
525 ).slot_owners[i].ref_count()
526 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
527 regions,
528 ).slot_owners[i].paths_in_pt.len()
529 &&& final(regions).slot_owners[i].ref_count() != 0
530 },
531 forall|i: int|
539 #![trigger final(regions).slot_owners[i]]
540 old(regions).slot_owners[i].usage == PageUsage::MMIO ==> final(regions).slot_owners[i]
541 == old(regions).slot_owners[i],
542 forall|c: CursorOwner<'rcu, UserPtConfig>|
543 #![auto]
544 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
545;
546
547pub enum CursorMutRegionsMethod {
554 Unmap(usize),
555}
556
557pub(super) proof fn open_cursor_step<'a, 'rcu>(
570 tracked vm_space: &VmSpaceOwner,
571 tracked regions: &mut MetaRegionOwners,
572 vs: VmSpaceId,
573 va: Range<Vaddr>,
574) -> (tracked res: Option<CursorEntry<'rcu>>)
575 requires
576 vm_space.inv(),
577 old(regions).inv(),
578 ensures
579 final(regions).inv(),
580 final(regions).slots == old(regions).slots,
588 forall|i: int|
589 #![trigger final(regions).slot_owners[i]]
590 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
591 forall|i: int|
596 #![trigger final(regions).slot_owners[i]]
597 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
598 &&& old(regions).slot_owners[i].ref_count() == REF_COUNT_UNUSED
599 &&& final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
600 &&& final(regions).slot_owners[i].usage !is Frame
601 },
602 forall|c: CursorOwner<'rcu, UserPtConfig>|
603 #![auto]
604 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
605 res matches Some(e) ==> e.inv(),
606 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
607 res matches Some(e) ==> e.kind == CursorKind::ReadOnly,
608 res matches Some(e) ==> e.va == va,
609 res matches Some(e) ==> e.vm_space == vs,
610{
611 let tracked owner_opt = vm_space_cursor_embedded(vm_space, regions, va);
612 match owner_opt {
613 Option::Some((owner, guards)) => {
614 let tracked entry = tracked_cursor_entry_new(
615 vs,
616 CursorKind::ReadOnly,
617 va,
618 owner,
619 guards,
620 );
621 Option::Some(entry)
622 },
623 Option::None => Option::None,
624 }
625}
626
627pub(super) proof fn open_cursor_mut_step<'a, 'rcu>(
631 tracked vm_space: &VmSpaceOwner,
632 tracked regions: &mut MetaRegionOwners,
633 vs: VmSpaceId,
634 va: Range<Vaddr>,
635) -> (tracked res: Option<CursorEntry<'rcu>>)
636 requires
637 vm_space.inv(),
638 old(regions).inv(),
639 ensures
640 final(regions).inv(),
641 final(regions).slots == old(regions).slots,
642 forall|i: int|
643 #![trigger final(regions).slot_owners[i]]
644 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
645 forall|i: int|
646 #![trigger final(regions).slot_owners[i]]
647 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
648 &&& old(regions).slot_owners[i].ref_count() == REF_COUNT_UNUSED
649 &&& final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
650 &&& final(regions).slot_owners[i].usage !is Frame
651 },
652 forall|c: CursorOwner<'rcu, UserPtConfig>|
653 #![auto]
654 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
655 res matches Some(e) ==> e.inv(),
656 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
657 res matches Some(e) ==> e.kind == CursorKind::Mutable,
658 res matches Some(e) ==> e.va == va,
659 res matches Some(e) ==> e.vm_space == vs,
660{
661 let tracked owner_opt = vm_space_cursor_mut_embedded(vm_space, regions, va);
662 match owner_opt {
663 Option::Some((owner, guards)) => {
664 let tracked entry = tracked_cursor_entry_new(
665 vs,
666 CursorKind::Mutable,
667 va,
668 owner,
669 guards,
670 );
671 Option::Some(entry)
672 },
673 Option::None => Option::None,
674 }
675}
676
677pub(super) proof fn drop_cursor_step<'rcu>(tracked _entry: CursorEntry<'rcu>) {
680}
681
682pub(super) proof fn cursor_query_step<'rcu>(
697 tracked entry: &mut CursorEntry<'rcu>,
698 tracked regions: &mut MetaRegionOwners,
699) -> (res: Option<Paddr>)
700 requires
701 old(entry).inv(),
702 old(regions).inv(),
703 old(entry).owner.metaregion_sound(*old(regions)),
704 ensures
705 final(entry).vm_space == old(entry).vm_space,
706 final(entry).kind == old(entry).kind,
707 final(entry).va == old(entry).va,
708 final(entry).inv(),
709 final(regions).inv(),
710 final(entry).owner.metaregion_sound(*final(regions)),
711 final(regions).slots == old(regions).slots,
712 res is None ==> forall|i: int|
713 #![trigger final(regions).slot_owners[i]]
714 final(regions).slot_owners[i] == old(regions).slot_owners[i],
715 res matches Some(paddr) ==> {
716 &&& valid_frame_paddr(paddr)
717 &&& old(regions).slot_owner(paddr).usage is Frame
718 &&& final(regions).slot_owner(paddr).ref_count() == (old(regions).slot_owner(
719 paddr,
720 ).ref_count() + 1) as nat
721 &&& final(regions).slot_owner(paddr).ref_count() <= REF_COUNT_MAX
722 &&& forall|i: int|
723 #![trigger final(regions).slot_owners[i]]
724 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
725 regions,
726 ).slot_owners[i]
727 &&& final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage
728 &&& final(regions).slot_owner(paddr).paths_in_pt == old(regions).slot_owner(
729 paddr,
730 ).paths_in_pt
731 &&& final(regions).slot_owner(paddr).in_list_perm == old(regions).slot_owner(
732 paddr,
733 ).in_list_perm
734 &&& final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
735 paddr,
736 ).storage_perm()
737 },
738 forall|c: CursorOwner<'rcu, UserPtConfig>|
739 #![auto]
740 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
741{
742 cursor_query_embedded(&mut entry.owner, regions, &mut entry.guards)
743}
744
745pub(super) proof fn cursor_find_next_step<'rcu>(
748 tracked entry: &mut CursorEntry<'rcu>,
749 tracked regions: &mut MetaRegionOwners,
750 len: usize,
751)
752 requires
753 old(entry).inv(),
754 old(regions).inv(),
755 old(entry).owner.metaregion_sound(*old(regions)),
756 ensures
757 final(entry).vm_space == old(entry).vm_space,
758 final(entry).kind == old(entry).kind,
759 final(entry).va == old(entry).va,
760 final(entry).inv(),
761 final(regions).inv(),
762 final(entry).owner.metaregion_sound(*final(regions)),
763 final(regions).slots == old(regions).slots,
764 forall|i: int|
767 #![trigger final(regions).slot_owners[i]]
768 final(regions).slot_owners[i] == old(regions).slot_owners[i],
769 forall|c: CursorOwner<'rcu, UserPtConfig>|
770 #![auto]
771 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
772{
773}
774
775pub(super) proof fn cursor_jump_step<'rcu>(
778 tracked entry: &mut CursorEntry<'rcu>,
779 tracked regions: &mut MetaRegionOwners,
780 va: Vaddr,
781)
782 requires
783 old(entry).inv(),
784 old(regions).inv(),
785 old(entry).owner.metaregion_sound(*old(regions)),
786 ensures
787 final(entry).vm_space == old(entry).vm_space,
788 final(entry).kind == old(entry).kind,
789 final(entry).va == old(entry).va,
790 final(entry).inv(),
791 final(regions).inv(),
792 final(entry).owner.metaregion_sound(*final(regions)),
793 final(regions).slots == old(regions).slots,
794 forall|i: int|
795 #![trigger final(regions).slot_owners[i]]
796 final(regions).slot_owners[i] == old(regions).slot_owners[i],
797 forall|c: CursorOwner<'rcu, UserPtConfig>|
798 #![auto]
799 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
800{
801 lemma_cursor_jump_embedded(&mut entry.owner, regions, &mut entry.guards, va)
802}
803
804pub(super) proof fn cursor_protect_next_step<'rcu>(
808 tracked entry: &mut CursorEntry<'rcu>,
809 tracked regions: &mut MetaRegionOwners,
810 len: usize,
811)
812 requires
813 old(entry).inv(),
814 old(regions).inv(),
815 old(entry).owner.metaregion_sound(*old(regions)),
816 ensures
817 final(entry).vm_space == old(entry).vm_space,
818 final(entry).kind == old(entry).kind,
819 final(entry).va == old(entry).va,
820 final(entry).inv(),
821 final(regions).inv(),
822 final(entry).owner.metaregion_sound(*final(regions)),
823 final(regions).slots == old(regions).slots,
824 forall|i: int|
825 #![trigger final(regions).slot_owners[i]]
826 final(regions).slot_owners[i] == old(regions).slot_owners[i],
827 forall|c: CursorOwner<'rcu, UserPtConfig>|
828 #![auto]
829 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
830{
831}
832
833pub(super) proof fn cursor_mut_regions_step<'rcu>(
837 tracked entry: &mut CursorEntry<'rcu>,
838 tracked regions: &mut MetaRegionOwners,
839 tracked tlb_model: &mut TlbModel,
840 method: CursorMutRegionsMethod,
841)
842 requires
843 old(entry).inv(),
844 old(regions).inv(),
845 old(entry).owner.metaregion_sound(*old(regions)),
846 old(tlb_model).inv(),
847 ensures
848 final(entry).vm_space == old(entry).vm_space,
849 final(entry).kind == old(entry).kind,
850 final(entry).va == old(entry).va,
851 final(entry).inv(),
852 final(regions).inv(),
853 final(entry).owner.metaregion_sound(*final(regions)),
854 final(tlb_model).inv(),
855 final(regions).slots == old(regions).slots,
862 forall|i: int|
863 #![trigger final(regions).slot_owners[i]]
864 {
865 &&& final(regions).slot_owners[i].slot_vaddr == old(
866 regions,
867 ).slot_owners[i].slot_vaddr
868 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
869 &&& final(regions).slot_owners[i].in_list_perm == old(
870 regions,
871 ).slot_owners[i].in_list_perm
872 &&& final(regions).slot_owners[i].vtable_ptr_perm() == old(
873 regions,
874 ).slot_owners[i].vtable_ptr_perm()
875 &&& old(regions).slot_owners[i].ref_count() != REF_COUNT_UNIQUE
876 ==> final(regions).slot_owners[i].ref_count() != REF_COUNT_UNIQUE
877 &&& final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
878 ==> final(regions).slot_owners[i].storage_perm() == old(
879 regions,
880 ).slot_owners[i].storage_perm()
881 },
882 forall|i: int|
885 #![trigger final(regions).slot_owners[i]]
886 !old(regions).slots.contains_key(i) ==> final(regions).slot_owners[i] == old(
887 regions,
888 ).slot_owners[i],
889 forall|i: int|
890 #![trigger final(regions).slot_owners[i]]
891 old(regions).slot_owners[i].usage is Frame ==> {
892 &&& final(regions).slot_owners[i].ref_count() + old(
893 regions,
894 ).slot_owners[i].paths_in_pt.len() == old(regions).slot_owners[i].ref_count()
895 + final(regions).slot_owners[i].paths_in_pt.len()
896 &&& final(regions).slot_owners[i].ref_count() <= old(
897 regions,
898 ).slot_owners[i].ref_count()
899 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
900 regions,
901 ).slot_owners[i].paths_in_pt.len()
902 &&& final(regions).slot_owners[i].ref_count() != 0
903 },
904 forall|i: int|
905 #![trigger final(regions).slot_owners[i]]
906 old(regions).slot_owners[i].usage == PageUsage::MMIO ==> final(regions).slot_owners[i]
907 == old(regions).slot_owners[i],
908 forall|c: CursorOwner<'rcu, UserPtConfig>|
909 #![auto]
910 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
911{
912 match method {
913 CursorMutRegionsMethod::Unmap(len) => {
914 cursor_mut_unmap_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, len);
915 },
916 }
917}
918
919pub(super) proof fn map_step<'rcu>(
928 tracked entry: &mut CursorEntry<'rcu>,
929 tracked regions: &mut MetaRegionOwners,
930 tracked tlb_model: &mut TlbModel,
931 paddr: Paddr,
932 prop: PageProperty,
933)
934 requires
935 old(entry).inv(),
936 old(regions).inv(),
937 old(entry).owner.metaregion_sound(*old(regions)),
938 old(tlb_model).inv(),
939 valid_frame_paddr(paddr),
940 ensures
941 final(entry).vm_space == old(entry).vm_space,
942 final(entry).kind == old(entry).kind,
943 final(entry).va == old(entry).va,
944 final(entry).inv(),
945 final(regions).inv(),
946 final(entry).owner.metaregion_sound(*final(regions)),
947 final(tlb_model).inv(),
948 final(regions).slots == old(regions).slots,
949 forall|i: int|
951 #![trigger final(regions).slot_owners[i]]
952 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
953 forall|i: int|
954 #![trigger final(regions).slot_owners[i]]
955 i != frame_to_index(paddr) && old(regions).slot_owners[i].ref_count()
956 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i] == old(
957 regions,
958 ).slot_owners[i],
959 forall|i: int|
960 #![trigger final(regions).slot_owners[i].ref_count()]
961 old(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
962 ==> final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED,
963 final(regions).slot_owner(paddr).ref_count() == old(regions).slot_owner(paddr).ref_count(),
964 final(regions).slot_owner(paddr).paths_in_pt.len() == old(regions).slot_owner(
965 paddr,
966 ).paths_in_pt.len() + 1,
967 final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage,
968 final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
969 paddr,
970 ).storage_perm(),
971 forall|i: int|
972 #![trigger final(regions).slot_owners[i]]
973 final(regions).slot_owners[i].ref_count() == REF_COUNT_UNUSED
974 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
975 forall|i: int|
976 #![trigger final(regions).slot_owners[i]]
977 i != frame_to_index(paddr) && old(regions).slot_owners[i].ref_count()
978 == REF_COUNT_UNUSED && final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
979 ==> final(regions).slot_owners[i].usage !is Frame,
980 forall|c: CursorOwner<'rcu, UserPtConfig>|
981 #![auto]
982 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
983{
984 cursor_mut_map_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, paddr, prop);
985}
986
987}