1use core::ops::Range;
47
48use vstd::prelude::*;
49use vstd_extra::ownership::*;
50
51use crate::mm::frame::{UFrame, has_safe_slot};
52use crate::mm::page_prop::PageProperty;
53use crate::mm::vm_space::UserPtConfig;
54use crate::mm::vm_space::vm_space_specs::VmSpaceOwner;
55use crate::mm::{Paddr, Vaddr};
56use crate::specs::mm::frame::mapping::frame_to_index;
57use crate::specs::mm::frame::meta_owners::{
58 PageUsage, REF_COUNT_MAX, REF_COUNT_UNIQUE, REF_COUNT_UNUSED,
59};
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)].self_addr == old(
248 regions,
249 ).slot_owners[frame_to_index(paddr)].self_addr
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].self_addr == old(regions).slot_owners[i].self_addr
522 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
523 &&& final(regions).slot_owners[i].inner_perms.in_list == old(
524 regions,
525 ).slot_owners[i].inner_perms.in_list
526 &&& final(regions).slot_owners[i].inner_perms.vtable_ptr == old(
527 regions,
528 ).slot_owners[i].inner_perms.vtable_ptr
529 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNIQUE
531 ==> final(regions).slot_owners[i].inner_perms.ref_count.value()
532 != REF_COUNT_UNIQUE
533 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
535 ==> final(regions).slot_owners[i].inner_perms.storage == old(
536 regions,
537 ).slot_owners[i].inner_perms.storage
538 },
539 forall|i: usize|
551 #![trigger final(regions).slot_owners[i]]
552 old(regions).slot_owners[i].usage == PageUsage::Frame ==> {
553 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() + old(
554 regions,
555 ).slot_owners[i].paths_in_pt.len() == old(
556 regions,
557 ).slot_owners[i].inner_perms.ref_count.value()
558 + final(regions).slot_owners[i].paths_in_pt.len()
559 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() <= old(
560 regions,
561 ).slot_owners[i].inner_perms.ref_count.value()
562 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
563 regions,
564 ).slot_owners[i].paths_in_pt.len()
565 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != 0
566 },
567 forall|i: usize|
575 #![trigger final(regions).slot_owners[i]]
576 old(regions).slot_owners[i].usage == PageUsage::MMIO ==> final(regions).slot_owners[i]
577 == old(regions).slot_owners[i],
578 forall|c: CursorOwner<'rcu, UserPtConfig>|
579 #![auto]
580 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
581;
582
583pub axiom fn cursor_mut_protect_next_embedded<'rcu>(
592 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
593 tracked regions: &mut MetaRegionOwners,
594 tracked guards: &mut Guards<'rcu>,
595 len: usize,
596)
597 requires
598 old(owner).inv(),
599 old(regions).inv(),
600 old(owner).children_not_locked(*old(guards)),
601 old(owner).nodes_locked(*old(guards)),
602 old(owner).metaregion_sound(*old(regions)),
603 !old(
604 owner,
605 ).popped_too_high,
606ensures
609 final(owner).inv(),
610 final(regions).inv(),
611 final(owner).children_not_locked(*final(guards)),
612 final(owner).nodes_locked(*final(guards)),
613 final(owner).metaregion_sound(*final(regions)),
614 !final(owner).popped_too_high,
615 final(regions).slots =~= old(regions).slots,
620 forall|i: usize|
621 #![trigger final(regions).slot_owners[i]]
622 final(regions).slot_owners[i] == old(regions).slot_owners[i],
623 forall|c: CursorOwner<'rcu, UserPtConfig>|
624 #![auto]
625 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
626;
627
628pub enum CursorMutRegionsMethod {
635 Unmap(usize),
636}
637
638pub(super) proof fn open_cursor_step<'a, 'rcu>(
651 tracked vm_space: &VmSpaceOwner,
652 tracked regions: &mut MetaRegionOwners,
653 vs: VmSpaceId,
654 va: Range<Vaddr>,
655) -> (tracked res: Option<CursorEntry<'rcu>>)
656 requires
657 vm_space.inv(),
658 old(regions).inv(),
659 ensures
660 final(regions).inv(),
661 final(regions).slots =~= old(regions).slots,
669 forall|i: usize|
670 #![trigger final(regions).slot_owners[i]]
671 final(regions).slot_owners[i].inner_perms.in_list == old(
672 regions,
673 ).slot_owners[i].inner_perms.in_list,
674 forall|i: usize|
679 #![trigger final(regions).slot_owners[i]]
680 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
681 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
682 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
683 &&& final(regions).slot_owners[i].usage != PageUsage::Frame
684 },
685 forall|c: CursorOwner<'rcu, UserPtConfig>|
686 #![auto]
687 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
688 res matches Some(e) ==> e.inv(),
689 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
690 res matches Some(e) ==> e.kind == CursorKind::ReadOnly,
691 res matches Some(e) ==> e.va == va,
692 res matches Some(e) ==> e.vm_space == vs,
693{
694 let tracked owner_opt = vm_space_cursor_embedded(vm_space, regions, va);
695 match owner_opt {
696 Option::Some((owner, guards)) => {
697 let tracked entry = axiom_cursor_entry_new(vs, CursorKind::ReadOnly, va, owner, guards);
698 Option::Some(entry)
699 },
700 Option::None => Option::None,
701 }
702}
703
704pub(super) proof fn open_cursor_mut_step<'a, 'rcu>(
708 tracked vm_space: &VmSpaceOwner,
709 tracked regions: &mut MetaRegionOwners,
710 vs: VmSpaceId,
711 va: Range<Vaddr>,
712) -> (tracked res: Option<CursorEntry<'rcu>>)
713 requires
714 vm_space.inv(),
715 old(regions).inv(),
716 ensures
717 final(regions).inv(),
718 final(regions).slots =~= old(regions).slots,
719 forall|i: usize|
720 #![trigger final(regions).slot_owners[i]]
721 final(regions).slot_owners[i].inner_perms.in_list == old(
722 regions,
723 ).slot_owners[i].inner_perms.in_list,
724 forall|i: usize|
725 #![trigger final(regions).slot_owners[i]]
726 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
727 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
728 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
729 &&& final(regions).slot_owners[i].usage != PageUsage::Frame
730 },
731 forall|c: CursorOwner<'rcu, UserPtConfig>|
732 #![auto]
733 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
734 res matches Some(e) ==> e.inv(),
735 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
736 res matches Some(e) ==> e.kind == CursorKind::Mutable,
737 res matches Some(e) ==> e.va == va,
738 res matches Some(e) ==> e.vm_space == vs,
739{
740 let tracked owner_opt = vm_space_cursor_mut_embedded(vm_space, regions, va);
741 match owner_opt {
742 Option::Some((owner, guards)) => {
743 let tracked entry = axiom_cursor_entry_new(vs, CursorKind::Mutable, va, owner, guards);
744 Option::Some(entry)
745 },
746 Option::None => Option::None,
747 }
748}
749
750pub(super) proof fn drop_cursor_step<'rcu>(tracked _entry: CursorEntry<'rcu>) {
753}
754
755pub(super) proof fn cursor_query_step<'rcu>(
770 tracked entry: &mut CursorEntry<'rcu>,
771 tracked regions: &mut MetaRegionOwners,
772) -> (res: Option<Paddr>)
773 requires
774 old(entry).inv(),
775 old(regions).inv(),
776 old(entry).owner.metaregion_sound(*old(regions)),
777 ensures
778 final(entry).vm_space == old(entry).vm_space,
779 final(entry).kind == old(entry).kind,
780 final(entry).va == old(entry).va,
781 final(entry).inv(),
782 final(regions).inv(),
783 final(entry).owner.metaregion_sound(*final(regions)),
784 final(regions).slots =~= old(regions).slots,
785 res is None ==> forall|i: usize|
786 #![trigger final(regions).slot_owners[i]]
787 final(regions).slot_owners[i] == old(regions).slot_owners[i],
788 res matches Some(paddr) ==> {
789 &&& has_safe_slot(paddr)
790 &&& old(regions).slot_owners[frame_to_index(paddr)].usage == PageUsage::Frame
791 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == (
792 old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
793 + 1) as nat
794 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value()
795 <= REF_COUNT_MAX
796 &&& forall|i: usize|
797 #![trigger final(regions).slot_owners[i]]
798 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
799 regions,
800 ).slot_owners[i]
801 &&& final(regions).slot_owners[frame_to_index(paddr)].usage == old(
802 regions,
803 ).slot_owners[frame_to_index(paddr)].usage
804 &&& final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt == old(
805 regions,
806 ).slot_owners[frame_to_index(paddr)].paths_in_pt
807 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.in_list == old(
808 regions,
809 ).slot_owners[frame_to_index(paddr)].inner_perms.in_list
810 &&& final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage == old(
811 regions,
812 ).slot_owners[frame_to_index(paddr)].inner_perms.storage
813 },
814 forall|c: CursorOwner<'rcu, UserPtConfig>|
815 #![auto]
816 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
817{
818 cursor_query_embedded(&mut entry.owner, regions, &mut entry.guards)
819}
820
821pub(super) proof fn cursor_find_next_step<'rcu>(
824 tracked entry: &mut CursorEntry<'rcu>,
825 tracked regions: &mut MetaRegionOwners,
826 len: usize,
827)
828 requires
829 old(entry).inv(),
830 old(regions).inv(),
831 old(entry).owner.metaregion_sound(*old(regions)),
832 ensures
833 final(entry).vm_space == old(entry).vm_space,
834 final(entry).kind == old(entry).kind,
835 final(entry).va == old(entry).va,
836 final(entry).inv(),
837 final(regions).inv(),
838 final(entry).owner.metaregion_sound(*final(regions)),
839 final(regions).slots =~= old(regions).slots,
840 forall|i: usize|
843 #![trigger final(regions).slot_owners[i]]
844 final(regions).slot_owners[i] == old(regions).slot_owners[i],
845 forall|c: CursorOwner<'rcu, UserPtConfig>|
846 #![auto]
847 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
848{
849 cursor_find_next_embedded(&mut entry.owner, regions, &mut entry.guards, len)
850}
851
852pub(super) proof fn cursor_jump_step<'rcu>(
855 tracked entry: &mut CursorEntry<'rcu>,
856 tracked regions: &mut MetaRegionOwners,
857 va: Vaddr,
858)
859 requires
860 old(entry).inv(),
861 old(regions).inv(),
862 old(entry).owner.metaregion_sound(*old(regions)),
863 ensures
864 final(entry).vm_space == old(entry).vm_space,
865 final(entry).kind == old(entry).kind,
866 final(entry).va == old(entry).va,
867 final(entry).inv(),
868 final(regions).inv(),
869 final(entry).owner.metaregion_sound(*final(regions)),
870 final(regions).slots =~= old(regions).slots,
871 forall|i: usize|
872 #![trigger final(regions).slot_owners[i]]
873 final(regions).slot_owners[i] == old(regions).slot_owners[i],
874 forall|c: CursorOwner<'rcu, UserPtConfig>|
875 #![auto]
876 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
877{
878 cursor_jump_embedded(&mut entry.owner, regions, &mut entry.guards, va)
879}
880
881pub(super) proof fn cursor_protect_next_step<'rcu>(
885 tracked entry: &mut CursorEntry<'rcu>,
886 tracked regions: &mut MetaRegionOwners,
887 len: usize,
888)
889 requires
890 old(entry).inv(),
891 old(regions).inv(),
892 old(entry).owner.metaregion_sound(*old(regions)),
893 ensures
894 final(entry).vm_space == old(entry).vm_space,
895 final(entry).kind == old(entry).kind,
896 final(entry).va == old(entry).va,
897 final(entry).inv(),
898 final(regions).inv(),
899 final(entry).owner.metaregion_sound(*final(regions)),
900 final(regions).slots =~= old(regions).slots,
901 forall|i: usize|
902 #![trigger final(regions).slot_owners[i]]
903 final(regions).slot_owners[i] == old(regions).slot_owners[i],
904 forall|c: CursorOwner<'rcu, UserPtConfig>|
905 #![auto]
906 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
907{
908 cursor_mut_protect_next_embedded(&mut entry.owner, regions, &mut entry.guards, len)
909}
910
911pub(super) proof fn cursor_mut_regions_step<'rcu>(
915 tracked entry: &mut CursorEntry<'rcu>,
916 tracked regions: &mut MetaRegionOwners,
917 tracked tlb_model: &mut TlbModel,
918 method: CursorMutRegionsMethod,
919)
920 requires
921 old(entry).inv(),
922 old(regions).inv(),
923 old(entry).owner.metaregion_sound(*old(regions)),
924 old(tlb_model).inv(),
925 ensures
926 final(entry).vm_space == old(entry).vm_space,
927 final(entry).kind == old(entry).kind,
928 final(entry).va == old(entry).va,
929 final(entry).inv(),
930 final(regions).inv(),
931 final(entry).owner.metaregion_sound(*final(regions)),
932 final(tlb_model).inv(),
933 final(regions).slots =~= old(regions).slots,
940 forall|i: usize|
941 #![trigger final(regions).slot_owners[i]]
942 {
943 &&& final(regions).slot_owners[i].self_addr == old(regions).slot_owners[i].self_addr
944 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
945 &&& final(regions).slot_owners[i].inner_perms.in_list == old(
946 regions,
947 ).slot_owners[i].inner_perms.in_list
948 &&& final(regions).slot_owners[i].inner_perms.vtable_ptr == old(
949 regions,
950 ).slot_owners[i].inner_perms.vtable_ptr
951 &&& old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNIQUE
952 ==> final(regions).slot_owners[i].inner_perms.ref_count.value()
953 != REF_COUNT_UNIQUE
954 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
955 ==> final(regions).slot_owners[i].inner_perms.storage == old(
956 regions,
957 ).slot_owners[i].inner_perms.storage
958 },
959 forall|i: usize|
960 #![trigger final(regions).slot_owners[i]]
961 old(regions).slot_owners[i].usage == PageUsage::Frame ==> {
962 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() + old(
963 regions,
964 ).slot_owners[i].paths_in_pt.len() == old(
965 regions,
966 ).slot_owners[i].inner_perms.ref_count.value()
967 + final(regions).slot_owners[i].paths_in_pt.len()
968 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() <= old(
969 regions,
970 ).slot_owners[i].inner_perms.ref_count.value()
971 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
972 regions,
973 ).slot_owners[i].paths_in_pt.len()
974 &&& final(regions).slot_owners[i].inner_perms.ref_count.value() != 0
975 },
976 forall|i: usize|
977 #![trigger final(regions).slot_owners[i]]
978 old(regions).slot_owners[i].usage == PageUsage::MMIO ==> final(regions).slot_owners[i]
979 == old(regions).slot_owners[i],
980 forall|c: CursorOwner<'rcu, UserPtConfig>|
981 #![auto]
982 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
983{
984 match method {
985 CursorMutRegionsMethod::Unmap(len) => {
986 cursor_mut_unmap_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, len);
987 },
988 }
989}
990
991pub(super) proof fn map_step<'rcu>(
1000 tracked entry: &mut CursorEntry<'rcu>,
1001 tracked regions: &mut MetaRegionOwners,
1002 tracked tlb_model: &mut TlbModel,
1003 paddr: Paddr,
1004 prop: PageProperty,
1005)
1006 requires
1007 old(entry).inv(),
1008 old(regions).inv(),
1009 old(entry).owner.metaregion_sound(*old(regions)),
1010 old(tlb_model).inv(),
1011 has_safe_slot(paddr),
1012 ensures
1013 final(entry).vm_space == old(entry).vm_space,
1014 final(entry).kind == old(entry).kind,
1015 final(entry).va == old(entry).va,
1016 final(entry).inv(),
1017 final(regions).inv(),
1018 final(entry).owner.metaregion_sound(*final(regions)),
1019 final(tlb_model).inv(),
1020 final(regions).slots =~= old(regions).slots,
1021 forall|i: usize|
1023 #![trigger final(regions).slot_owners[i]]
1024 final(regions).slot_owners[i].inner_perms.in_list == old(
1025 regions,
1026 ).slot_owners[i].inner_perms.in_list,
1027 forall|i: usize|
1028 #![trigger final(regions).slot_owners[i]]
1029 i != frame_to_index(paddr) && old(regions).slot_owners[i].inner_perms.ref_count.value()
1030 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i] == old(
1031 regions,
1032 ).slot_owners[i],
1033 forall|i: usize|
1034 #![trigger final(regions).slot_owners[i].inner_perms.ref_count.value()]
1035 old(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED
1036 ==> final(regions).slot_owners[i].inner_perms.ref_count.value() != REF_COUNT_UNUSED,
1037 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == old(
1038 regions,
1039 ).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value(),
1040 final(regions).slot_owners[frame_to_index(paddr)].paths_in_pt.len() == old(
1041 regions,
1042 ).slot_owners[frame_to_index(paddr)].paths_in_pt.len() + 1,
1043 final(regions).slot_owners[frame_to_index(paddr)].usage == old(
1044 regions,
1045 ).slot_owners[frame_to_index(paddr)].usage,
1046 final(regions).slot_owners[frame_to_index(paddr)].inner_perms.storage == old(
1047 regions,
1048 ).slot_owners[frame_to_index(paddr)].inner_perms.storage,
1049 forall|i: usize|
1050 #![trigger final(regions).slot_owners[i]]
1051 final(regions).slot_owners[i].inner_perms.ref_count.value() == REF_COUNT_UNUSED
1052 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
1053 forall|i: usize|
1054 #![trigger final(regions).slot_owners[i]]
1055 i != frame_to_index(paddr) && old(regions).slot_owners[i].inner_perms.ref_count.value()
1056 == REF_COUNT_UNUSED && final(regions).slot_owners[i].inner_perms.ref_count.value()
1057 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i].usage != PageUsage::Frame,
1058 forall|c: CursorOwner<'rcu, UserPtConfig>|
1059 #![auto]
1060 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
1061{
1062 cursor_mut_map_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, paddr, prop);
1063}
1064
1065}