1use core::ops::Range;
47
48use vstd::prelude::*;
49use vstd_extra::ownership::*;
50
51use crate::mm::frame::UFrame;
52use crate::mm::frame::meta::{REF_COUNT_MAX, REF_COUNT_UNIQUE, REF_COUNT_UNUSED};
53use crate::mm::page_prop::PageProperty;
54use crate::mm::vm_space::UserPtConfig;
55use crate::mm::vm_space::vm_space_specs::VmSpaceOwner;
56use crate::mm::{Paddr, Vaddr};
57use crate::specs::arch::*;
58use crate::specs::mm::frame::mapping::frame_to_index;
59use crate::specs::mm::frame::meta_owners::PageUsage;
60use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
61use crate::specs::mm::page_table::cursor::owners::CursorOwner;
62use crate::specs::mm::page_table::node::Guards;
63use crate::specs::mm::tlb::TlbModel;
64
65use super::{CursorEntry, CursorKind, VmSpaceId, axiom_cursor_entry_new};
66
67verus! {
68
69pub axiom fn vm_space_cursor_embedded<'a, 'rcu>(
86 tracked vm_space: &VmSpaceOwner,
87 tracked regions: &mut MetaRegionOwners,
88 va: Range<Vaddr>,
89) -> (tracked res: Option<(CursorOwner<'rcu, UserPtConfig>, Guards<'rcu>)>)
90 requires
91 vm_space.inv(),
92 old(regions).inv(),
93 ensures
94 final(regions).inv(),
95 final(regions).slots == old(regions).slots,
103 forall|i: usize|
104 #![trigger final(regions).slot_owners[i]]
105 final(regions).slot_owners[i].inner_perms.in_list == old(
106 regions,
107 ).slot_owners[i].inner_perms.in_list,
108 forall|i: usize|
113 #![trigger final(regions).slot_owners[i]]
114 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
115 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
116 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
117 &&& final(regions).slot_owners[i].usage != PageUsage::Frame
118 },
119 forall|c: CursorOwner<'rcu, UserPtConfig>|
120 #![auto]
121 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
122 res matches Some((c, g)) ==> {
123 &&& c.inv()
124 &&& c.children_not_locked(g)
125 &&& c.nodes_locked(g)
126 &&& !c.popped_too_high
127 &&& c.metaregion_sound(*final(regions))
128 },
129;
130
131pub axiom fn vm_space_cursor_mut_embedded<'a, 'rcu>(
133 tracked vm_space: &VmSpaceOwner,
134 tracked regions: &mut MetaRegionOwners,
135 va: Range<Vaddr>,
136) -> (tracked res: Option<(CursorOwner<'rcu, UserPtConfig>, Guards<'rcu>)>)
137 requires
138 vm_space.inv(),
139 old(regions).inv(),
140 ensures
141 final(regions).inv(),
142 final(regions).slots == old(regions).slots,
150 forall|i: usize|
151 #![trigger final(regions).slot_owners[i]]
152 final(regions).slot_owners[i].inner_perms.in_list == old(
153 regions,
154 ).slot_owners[i].inner_perms.in_list,
155 forall|i: usize|
160 #![trigger final(regions).slot_owners[i]]
161 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
162 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
163 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
164 &&& final(regions).slot_owners[i].usage != PageUsage::Frame
165 },
166 forall|c: CursorOwner<'rcu, UserPtConfig>|
167 #![auto]
168 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
169 res matches Some((c, g)) ==> {
170 &&& c.inv()
171 &&& c.children_not_locked(g)
172 &&& c.nodes_locked(g)
173 &&& !c.popped_too_high
174 &&& c.metaregion_sound(*final(regions))
175 },
176;
177
178pub axiom fn cursor_query_embedded<'rcu>(
204 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
205 tracked regions: &mut MetaRegionOwners,
206 tracked guards: &mut Guards<'rcu>,
207) -> (res: Option<Paddr>)
208 requires
209 old(owner).inv(),
210 old(regions).inv(),
211 old(owner).children_not_locked(*old(guards)),
212 old(owner).nodes_locked(*old(guards)),
213 old(owner).metaregion_sound(*old(regions)),
214 !old(owner).popped_too_high,
215 ensures
216 final(owner).inv(),
217 final(regions).inv(),
218 final(owner).children_not_locked(*final(guards)),
219 final(owner).nodes_locked(*final(guards)),
220 final(owner).metaregion_sound(*final(regions)),
221 !final(owner).popped_too_high,
222 final(regions).slots == old(regions).slots,
224 res is None ==> forall|i: usize|
226 #![trigger final(regions).slot_owners[i]]
227 final(regions).slot_owners[i] == old(regions).slot_owners[i],
228 res matches Some(paddr) ==> {
232 &&& has_safe_slot(paddr)
233 &&& old(regions).slot_owners[frame_to_index(paddr)].usage == PageUsage::Frame
234 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == (
235 old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
236 + 1) as nat
237 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
238 <= REF_COUNT_MAX
239 &&& forall|i: usize|
240 #![trigger final(regions).slot_owners[i]]
241 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
242 regions,
243 ).slot_owners[i]
244 &&& final(regions).slot_owners[frame_to_index(paddr)].slot_vaddr == old(
248 regions,
249 ).slot_owners[frame_to_index(paddr)].slot_vaddr
250 &&& final(regions).slot_owners[frame_to_index(paddr)].usage == old(
251 regions,
252 ).slot_owners[frame_to_index(paddr)].usage
253 &&& final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt == old(
254 regions,
255 ).slot_owners[frame_to_index(paddr)].paths_in_pt
256 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.in_list == old(
257 regions,
258 ).slot_owners[frame_to_index(paddr)].inner_perms.in_list
259 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage == old(
260 regions,
261 ).slot_owners[frame_to_index(paddr)].inner_perms.storage
262 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.vtable_ptr == old(
263 regions,
264 ).slot_owners[frame_to_index(paddr)].inner_perms.vtable_ptr
265 },
266 forall|c: CursorOwner<'rcu, UserPtConfig>|
267 #![auto]
268 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
269;
270
271pub axiom fn cursor_find_next_embedded<'rcu>(
278 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
279 tracked regions: &mut MetaRegionOwners,
280 tracked guards: &mut Guards<'rcu>,
281 len: usize,
282)
283 requires
284 old(owner).inv(),
285 old(regions).inv(),
286 old(owner).children_not_locked(*old(guards)),
287 old(owner).nodes_locked(*old(guards)),
288 old(owner).metaregion_sound(*old(regions)),
289 !old(owner).popped_too_high,
290 ensures
291 final(owner).inv(),
292 final(regions).inv(),
293 final(owner).children_not_locked(*final(guards)),
294 final(owner).nodes_locked(*final(guards)),
295 final(owner).metaregion_sound(*final(regions)),
296 !final(owner).popped_too_high,
297 final(regions).slots == old(regions).slots,
304 forall|i: usize|
305 #![trigger final(regions).slot_owners[i]]
306 final(regions).slot_owners[i] == old(regions).slot_owners[i],
307 forall|c: CursorOwner<'rcu, UserPtConfig>|
308 #![auto]
309 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
310;
311
312pub axiom fn cursor_jump_embedded<'rcu>(
324 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
325 tracked regions: &mut MetaRegionOwners,
326 tracked guards: &mut Guards<'rcu>,
327 va: Vaddr,
328)
329 requires
330 old(owner).inv(),
331 old(regions).inv(),
332 old(owner).children_not_locked(*old(guards)),
333 old(owner).nodes_locked(*old(guards)),
334 old(owner).metaregion_sound(*old(regions)),
335 !old(owner).popped_too_high,
336 ensures
337 final(owner).inv(),
338 final(regions).inv(),
339 final(owner).children_not_locked(*final(guards)),
340 final(owner).nodes_locked(*final(guards)),
341 final(owner).metaregion_sound(*final(regions)),
342 !final(owner).popped_too_high,
343 final(regions).slots == old(regions).slots,
347 forall|i: usize|
348 #![trigger final(regions).slot_owners[i]]
349 final(regions).slot_owners[i] == old(regions).slot_owners[i],
350 forall|c: CursorOwner<'rcu, UserPtConfig>|
351 #![auto]
352 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
353;
354
355pub axiom fn cursor_mut_map_embedded<'rcu>(
368 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
369 tracked regions: &mut MetaRegionOwners,
370 tracked guards: &mut Guards<'rcu>,
371 tracked tlb_model: &mut TlbModel,
372 paddr: Paddr,
373 prop: PageProperty,
374)
375 requires
376 old(owner).inv(),
377 old(regions).inv(),
378 old(owner).children_not_locked(*old(guards)),
379 old(owner).nodes_locked(*old(guards)),
380 old(owner).metaregion_sound(*old(regions)),
381 !old(owner).popped_too_high,
382 old(tlb_model).inv(),
383 has_safe_slot(
387 paddr,
388 ),
389ensures
394 final(owner).inv(),
395 final(regions).inv(),
396 final(owner).children_not_locked(*final(guards)),
397 final(owner).nodes_locked(*final(guards)),
398 final(owner).metaregion_sound(*final(regions)),
399 !final(owner).popped_too_high,
400 final(tlb_model).inv(),
401 final(regions).slots == old(regions).slots,
402 forall|i: usize|
405 #![trigger final(regions).slot_owners[i]]
406 final(regions).slot_owners[i].inner_perms.in_list == old(
407 regions,
408 ).slot_owners[i].inner_perms.in_list,
409 forall|i: usize|
415 #![trigger final(regions).slot_owners[i]]
416 i != frame_to_index(paddr) && old(regions).slot_owners[i].inner_perms.ref_count.value()
417 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i] == old(
418 regions,
419 ).slot_owners[i],
420 forall|i: usize|
423 #![trigger final(regions).slot_owners[i].inner_perms.ref_count.value()]
424 old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
425 ==> final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED,
426 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == old(
439 regions,
440 ).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value(),
441 final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt.len() == old(
446 regions,
447 ).slot_owners[frame_to_index(paddr)].paths_in_pt.len() + 1,
448 final(regions).slot_owners[frame_to_index(paddr)].usage == old(
452 regions,
453 ).slot_owners[frame_to_index(paddr)].usage,
454 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage == old(
455 regions,
456 ).slot_owners[frame_to_index(paddr)].inner_perms.storage,
457 forall|i: usize|
459 #![trigger final(regions).slot_owners[i]]
460 final(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
461 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
462 forall|i: usize|
471 #![trigger final(regions).slot_owners[i]]
472 i != frame_to_index(paddr) && old(regions).slot_owners[i].inner_perms.ref_count.value()
473 == REF_COUNT_UNUSED && final(regions).slot_owners[i].inner_perms.ref_count.value()
474 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i].usage != PageUsage::Frame,
475 forall|c: CursorOwner<'rcu, UserPtConfig>|
476 #![auto]
477 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
478;
479
480pub axiom fn cursor_mut_unmap_embedded<'rcu>(
489 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
490 tracked regions: &mut MetaRegionOwners,
491 tracked guards: &mut Guards<'rcu>,
492 tracked tlb_model: &mut TlbModel,
493 len: usize,
494)
495 requires
496 old(owner).inv(),
497 old(regions).inv(),
498 old(owner).children_not_locked(*old(guards)),
499 old(owner).nodes_locked(*old(guards)),
500 old(owner).metaregion_sound(*old(regions)),
501 !old(owner).popped_too_high,
502 old(tlb_model).inv(),
503 ensures
504 final(owner).inv(),
505 final(regions).inv(),
506 final(owner).children_not_locked(*final(guards)),
507 final(owner).nodes_locked(*final(guards)),
508 final(owner).metaregion_sound(*final(regions)),
509 !final(owner).popped_too_high,
510 final(tlb_model).inv(),
511 final(regions).slots == old(regions).slots,
513 forall|i: usize|
519 #![trigger final(regions).slot_owners[i]]
520 {
521 &&& final(regions).slot_owners[i].slot_vaddr == old(
522 regions,
523 ).slot_owners[i].slot_vaddr
524 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
525 &&& final(regions).slot_owners[i].inner_perms.in_list == old(
526 regions,
527 ).slot_owners[i].inner_perms.in_list
528 &&& final(regions).slot_owners[i].inner_perms.vtable_ptr == old(
529 regions,
530 ).slot_owners[i].inner_perms.vtable_ptr
531 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNIQUE
533 ==> final(regions).slot_owners[i].inner_perms.ref_count.value()
534 != REF_COUNT_UNIQUE
535 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
537 ==> final(regions).slot_owners[i].inner_perms.storage == old(
538 regions,
539 ).slot_owners[i].inner_perms.storage
540 },
541 forall|i: usize|
547 #![trigger final(regions).slot_owners[i]]
548 !old(regions).slots.contains_key(i) ==> final(regions).slot_owners[i] == old(
549 regions,
550 ).slot_owners[i],
551 forall|i: usize|
563 #![trigger final(regions).slot_owners[i]]
564 old(regions).slot_owners[i].usage == PageUsage::Frame ==> {
565 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() + old(
566 regions,
567 ).slot_owners[i].paths_in_pt.len() == old(
568 regions,
569 ).slot_owners[i].inner_perms.ref_count.value()
570 + final(regions).slot_owners[i].paths_in_pt.len()
571 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() <= old(
572 regions,
573 ).slot_owners[i].inner_perms.ref_count.value()
574 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
575 regions,
576 ).slot_owners[i].paths_in_pt.len()
577 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != 0
578 },
579 forall|i: usize|
587 #![trigger final(regions).slot_owners[i]]
588 old(regions).slot_owners[i].usage == PageUsage::MMIO ==> final(regions).slot_owners[i]
589 == old(regions).slot_owners[i],
590 forall|c: CursorOwner<'rcu, UserPtConfig>|
591 #![auto]
592 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
593;
594
595pub axiom fn cursor_mut_protect_next_embedded<'rcu>(
604 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
605 tracked regions: &mut MetaRegionOwners,
606 tracked guards: &mut Guards<'rcu>,
607 len: usize,
608)
609 requires
610 old(owner).inv(),
611 old(regions).inv(),
612 old(owner).children_not_locked(*old(guards)),
613 old(owner).nodes_locked(*old(guards)),
614 old(owner).metaregion_sound(*old(regions)),
615 !old(
616 owner,
617 ).popped_too_high,
618ensures
621 final(owner).inv(),
622 final(regions).inv(),
623 final(owner).children_not_locked(*final(guards)),
624 final(owner).nodes_locked(*final(guards)),
625 final(owner).metaregion_sound(*final(regions)),
626 !final(owner).popped_too_high,
627 final(regions).slots == old(regions).slots,
632 forall|i: usize|
633 #![trigger final(regions).slot_owners[i]]
634 final(regions).slot_owners[i] == old(regions).slot_owners[i],
635 forall|c: CursorOwner<'rcu, UserPtConfig>|
636 #![auto]
637 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
638;
639
640pub enum CursorMutRegionsMethod {
647 Unmap(usize),
648}
649
650pub(super) proof fn open_cursor_step<'a, 'rcu>(
663 tracked vm_space: &VmSpaceOwner,
664 tracked regions: &mut MetaRegionOwners,
665 vs: VmSpaceId,
666 va: Range<Vaddr>,
667) -> (tracked res: Option<CursorEntry<'rcu>>)
668 requires
669 vm_space.inv(),
670 old(regions).inv(),
671 ensures
672 final(regions).inv(),
673 final(regions).slots == old(regions).slots,
681 forall|i: usize|
682 #![trigger final(regions).slot_owners[i]]
683 final(regions).slot_owners[i].inner_perms.in_list == old(
684 regions,
685 ).slot_owners[i].inner_perms.in_list,
686 forall|i: usize|
691 #![trigger final(regions).slot_owners[i]]
692 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
693 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
694 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
695 &&& final(regions).slot_owners[i].usage != PageUsage::Frame
696 },
697 forall|c: CursorOwner<'rcu, UserPtConfig>|
698 #![auto]
699 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
700 res matches Some(e) ==> e.inv(),
701 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
702 res matches Some(e) ==> e.kind == CursorKind::ReadOnly,
703 res matches Some(e) ==> e.va == va,
704 res matches Some(e) ==> e.vm_space == vs,
705{
706 let tracked owner_opt = vm_space_cursor_embedded(vm_space, regions, va);
707 match owner_opt {
708 Option::Some((owner, guards)) => {
709 let tracked entry = axiom_cursor_entry_new(vs, CursorKind::ReadOnly, va, owner, guards);
710 Option::Some(entry)
711 },
712 Option::None => Option::None,
713 }
714}
715
716pub(super) proof fn open_cursor_mut_step<'a, 'rcu>(
720 tracked vm_space: &VmSpaceOwner,
721 tracked regions: &mut MetaRegionOwners,
722 vs: VmSpaceId,
723 va: Range<Vaddr>,
724) -> (tracked res: Option<CursorEntry<'rcu>>)
725 requires
726 vm_space.inv(),
727 old(regions).inv(),
728 ensures
729 final(regions).inv(),
730 final(regions).slots == old(regions).slots,
731 forall|i: usize|
732 #![trigger final(regions).slot_owners[i]]
733 final(regions).slot_owners[i].inner_perms.in_list == old(
734 regions,
735 ).slot_owners[i].inner_perms.in_list,
736 forall|i: usize|
737 #![trigger final(regions).slot_owners[i]]
738 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
739 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
740 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
741 &&& final(regions).slot_owners[i].usage != PageUsage::Frame
742 },
743 forall|c: CursorOwner<'rcu, UserPtConfig>|
744 #![auto]
745 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
746 res matches Some(e) ==> e.inv(),
747 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
748 res matches Some(e) ==> e.kind == CursorKind::Mutable,
749 res matches Some(e) ==> e.va == va,
750 res matches Some(e) ==> e.vm_space == vs,
751{
752 let tracked owner_opt = vm_space_cursor_mut_embedded(vm_space, regions, va);
753 match owner_opt {
754 Option::Some((owner, guards)) => {
755 let tracked entry = axiom_cursor_entry_new(vs, CursorKind::Mutable, va, owner, guards);
756 Option::Some(entry)
757 },
758 Option::None => Option::None,
759 }
760}
761
762pub(super) proof fn drop_cursor_step<'rcu>(tracked _entry: CursorEntry<'rcu>) {
765}
766
767pub(super) proof fn cursor_query_step<'rcu>(
782 tracked entry: &mut CursorEntry<'rcu>,
783 tracked regions: &mut MetaRegionOwners,
784) -> (res: Option<Paddr>)
785 requires
786 old(entry).inv(),
787 old(regions).inv(),
788 old(entry).owner.metaregion_sound(*old(regions)),
789 ensures
790 final(entry).vm_space == old(entry).vm_space,
791 final(entry).kind == old(entry).kind,
792 final(entry).va == old(entry).va,
793 final(entry).inv(),
794 final(regions).inv(),
795 final(entry).owner.metaregion_sound(*final(regions)),
796 final(regions).slots == old(regions).slots,
797 res is None ==> forall|i: usize|
798 #![trigger final(regions).slot_owners[i]]
799 final(regions).slot_owners[i] == old(regions).slot_owners[i],
800 res matches Some(paddr) ==> {
801 &&& has_safe_slot(paddr)
802 &&& old(regions).slot_owners[frame_to_index(paddr)].usage == PageUsage::Frame
803 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == (
804 old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
805 + 1) as nat
806 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
807 <= REF_COUNT_MAX
808 &&& forall|i: usize|
809 #![trigger final(regions).slot_owners[i]]
810 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
811 regions,
812 ).slot_owners[i]
813 &&& final(regions).slot_owners[frame_to_index(paddr)].usage == old(
814 regions,
815 ).slot_owners[frame_to_index(paddr)].usage
816 &&& final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt == old(
817 regions,
818 ).slot_owners[frame_to_index(paddr)].paths_in_pt
819 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.in_list == old(
820 regions,
821 ).slot_owners[frame_to_index(paddr)].inner_perms.in_list
822 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage == old(
823 regions,
824 ).slot_owners[frame_to_index(paddr)].inner_perms.storage
825 },
826 forall|c: CursorOwner<'rcu, UserPtConfig>|
827 #![auto]
828 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
829{
830 cursor_query_embedded(&mut entry.owner, regions, &mut entry.guards)
831}
832
833pub(super) proof fn cursor_find_next_step<'rcu>(
836 tracked entry: &mut CursorEntry<'rcu>,
837 tracked regions: &mut MetaRegionOwners,
838 len: usize,
839)
840 requires
841 old(entry).inv(),
842 old(regions).inv(),
843 old(entry).owner.metaregion_sound(*old(regions)),
844 ensures
845 final(entry).vm_space == old(entry).vm_space,
846 final(entry).kind == old(entry).kind,
847 final(entry).va == old(entry).va,
848 final(entry).inv(),
849 final(regions).inv(),
850 final(entry).owner.metaregion_sound(*final(regions)),
851 final(regions).slots == old(regions).slots,
852 forall|i: usize|
855 #![trigger final(regions).slot_owners[i]]
856 final(regions).slot_owners[i] == old(regions).slot_owners[i],
857 forall|c: CursorOwner<'rcu, UserPtConfig>|
858 #![auto]
859 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
860{
861 cursor_find_next_embedded(&mut entry.owner, regions, &mut entry.guards, len)
862}
863
864pub(super) proof fn cursor_jump_step<'rcu>(
867 tracked entry: &mut CursorEntry<'rcu>,
868 tracked regions: &mut MetaRegionOwners,
869 va: Vaddr,
870)
871 requires
872 old(entry).inv(),
873 old(regions).inv(),
874 old(entry).owner.metaregion_sound(*old(regions)),
875 ensures
876 final(entry).vm_space == old(entry).vm_space,
877 final(entry).kind == old(entry).kind,
878 final(entry).va == old(entry).va,
879 final(entry).inv(),
880 final(regions).inv(),
881 final(entry).owner.metaregion_sound(*final(regions)),
882 final(regions).slots == old(regions).slots,
883 forall|i: usize|
884 #![trigger final(regions).slot_owners[i]]
885 final(regions).slot_owners[i] == old(regions).slot_owners[i],
886 forall|c: CursorOwner<'rcu, UserPtConfig>|
887 #![auto]
888 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
889{
890 cursor_jump_embedded(&mut entry.owner, regions, &mut entry.guards, va)
891}
892
893pub(super) proof fn cursor_protect_next_step<'rcu>(
897 tracked entry: &mut CursorEntry<'rcu>,
898 tracked regions: &mut MetaRegionOwners,
899 len: usize,
900)
901 requires
902 old(entry).inv(),
903 old(regions).inv(),
904 old(entry).owner.metaregion_sound(*old(regions)),
905 ensures
906 final(entry).vm_space == old(entry).vm_space,
907 final(entry).kind == old(entry).kind,
908 final(entry).va == old(entry).va,
909 final(entry).inv(),
910 final(regions).inv(),
911 final(entry).owner.metaregion_sound(*final(regions)),
912 final(regions).slots == old(regions).slots,
913 forall|i: usize|
914 #![trigger final(regions).slot_owners[i]]
915 final(regions).slot_owners[i] == old(regions).slot_owners[i],
916 forall|c: CursorOwner<'rcu, UserPtConfig>|
917 #![auto]
918 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
919{
920 cursor_mut_protect_next_embedded(&mut entry.owner, regions, &mut entry.guards, len)
921}
922
923pub(super) proof fn cursor_mut_regions_step<'rcu>(
927 tracked entry: &mut CursorEntry<'rcu>,
928 tracked regions: &mut MetaRegionOwners,
929 tracked tlb_model: &mut TlbModel,
930 method: CursorMutRegionsMethod,
931)
932 requires
933 old(entry).inv(),
934 old(regions).inv(),
935 old(entry).owner.metaregion_sound(*old(regions)),
936 old(tlb_model).inv(),
937 ensures
938 final(entry).vm_space == old(entry).vm_space,
939 final(entry).kind == old(entry).kind,
940 final(entry).va == old(entry).va,
941 final(entry).inv(),
942 final(regions).inv(),
943 final(entry).owner.metaregion_sound(*final(regions)),
944 final(tlb_model).inv(),
945 final(regions).slots == old(regions).slots,
952 forall|i: usize|
953 #![trigger final(regions).slot_owners[i]]
954 {
955 &&& final(regions).slot_owners[i].slot_vaddr == old(
956 regions,
957 ).slot_owners[i].slot_vaddr
958 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
959 &&& final(regions).slot_owners[i].inner_perms.in_list == old(
960 regions,
961 ).slot_owners[i].inner_perms.in_list
962 &&& final(regions).slot_owners[i].inner_perms.vtable_ptr == old(
963 regions,
964 ).slot_owners[i].inner_perms.vtable_ptr
965 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNIQUE
966 ==> final(regions).slot_owners[i].inner_perms.ref_count.value()
967 != REF_COUNT_UNIQUE
968 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
969 ==> final(regions).slot_owners[i].inner_perms.storage == old(
970 regions,
971 ).slot_owners[i].inner_perms.storage
972 },
973 forall|i: usize|
976 #![trigger final(regions).slot_owners[i]]
977 !old(regions).slots.contains_key(i) ==> final(regions).slot_owners[i] == old(
978 regions,
979 ).slot_owners[i],
980 forall|i: usize|
981 #![trigger final(regions).slot_owners[i]]
982 old(regions).slot_owners[i].usage == PageUsage::Frame ==> {
983 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() + old(
984 regions,
985 ).slot_owners[i].paths_in_pt.len() == old(
986 regions,
987 ).slot_owners[i].inner_perms.ref_count.value()
988 + final(regions).slot_owners[i].paths_in_pt.len()
989 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() <= old(
990 regions,
991 ).slot_owners[i].inner_perms.ref_count.value()
992 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
993 regions,
994 ).slot_owners[i].paths_in_pt.len()
995 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != 0
996 },
997 forall|i: usize|
998 #![trigger final(regions).slot_owners[i]]
999 old(regions).slot_owners[i].usage == PageUsage::MMIO ==> final(regions).slot_owners[i]
1000 == old(regions).slot_owners[i],
1001 forall|c: CursorOwner<'rcu, UserPtConfig>|
1002 #![auto]
1003 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
1004{
1005 match method {
1006 CursorMutRegionsMethod::Unmap(len) => {
1007 cursor_mut_unmap_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, len);
1008 },
1009 }
1010}
1011
1012pub(super) proof fn map_step<'rcu>(
1021 tracked entry: &mut CursorEntry<'rcu>,
1022 tracked regions: &mut MetaRegionOwners,
1023 tracked tlb_model: &mut TlbModel,
1024 paddr: Paddr,
1025 prop: PageProperty,
1026)
1027 requires
1028 old(entry).inv(),
1029 old(regions).inv(),
1030 old(entry).owner.metaregion_sound(*old(regions)),
1031 old(tlb_model).inv(),
1032 has_safe_slot(paddr),
1033 ensures
1034 final(entry).vm_space == old(entry).vm_space,
1035 final(entry).kind == old(entry).kind,
1036 final(entry).va == old(entry).va,
1037 final(entry).inv(),
1038 final(regions).inv(),
1039 final(entry).owner.metaregion_sound(*final(regions)),
1040 final(tlb_model).inv(),
1041 final(regions).slots == old(regions).slots,
1042 forall|i: usize|
1044 #![trigger final(regions).slot_owners[i]]
1045 final(regions).slot_owners[i].inner_perms.in_list == old(
1046 regions,
1047 ).slot_owners[i].inner_perms.in_list,
1048 forall|i: usize|
1049 #![trigger final(regions).slot_owners[i]]
1050 i != frame_to_index(paddr) && old(regions).slot_owners[i].inner_perms.ref_count.value()
1051 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i] == old(
1052 regions,
1053 ).slot_owners[i],
1054 forall|i: usize|
1055 #![trigger final(regions).slot_owners[i].inner_perms.ref_count.value()]
1056 old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
1057 ==> final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED,
1058 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == old(
1059 regions,
1060 ).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value(),
1061 final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt.len() == old(
1062 regions,
1063 ).slot_owners[frame_to_index(paddr)].paths_in_pt.len() + 1,
1064 final(regions).slot_owners[frame_to_index(paddr)].usage == old(
1065 regions,
1066 ).slot_owners[frame_to_index(paddr)].usage,
1067 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage == old(
1068 regions,
1069 ).slot_owners[frame_to_index(paddr)].inner_perms.storage,
1070 forall|i: usize|
1071 #![trigger final(regions).slot_owners[i]]
1072 final(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
1073 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
1074 forall|i: usize|
1075 #![trigger final(regions).slot_owners[i]]
1076 i != frame_to_index(paddr) && old(regions).slot_owners[i].inner_perms.ref_count.value()
1077 == REF_COUNT_UNUSED && final(regions).slot_owners[i].inner_perms.ref_count.value()
1078 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i].usage != PageUsage::Frame,
1079 forall|c: CursorOwner<'rcu, UserPtConfig>|
1080 #![auto]
1081 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
1082{
1083 cursor_mut_map_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, paddr, prop);
1084}
1085
1086}