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,
226 res is None ==> forall|i: int|
227 #![trigger final(regions).slot_owners[i]]
228 final(regions).slot_owners[i] == old(regions).slot_owners[i],
229 res matches Some(paddr) ==> {
230 &&& valid_frame_paddr(paddr)
231 &&& old(regions).slot_owner(paddr).usage is Frame
232 &&& final(regions).slot_owner(paddr).ref_count() == (old(regions).slot_owner(
233 paddr,
234 ).ref_count() + 1) as nat
235 &&& final(regions).slot_owner(paddr).ref_count() <= REF_COUNT_MAX
236 &&& forall|i: int|
237 #![trigger final(regions).slot_owners[i]]
238 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
239 regions,
240 ).slot_owners[i]
241 &&& final(regions).slot_owner(paddr).slot_vaddr == old(regions).slot_owner(
242 paddr,
243 ).slot_vaddr
244 &&& final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage
245 &&& final(regions).slot_owner(paddr).paths_in_pt == old(regions).slot_owner(
246 paddr,
247 ).paths_in_pt
248 &&& final(regions).slot_owner(paddr).in_list_perm == old(regions).slot_owner(
249 paddr,
250 ).in_list_perm
251 &&& final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
252 paddr,
253 ).storage_perm()
254 &&& final(regions).slot_owner(paddr).vtable_ptr_perm() == old(regions).slot_owner(
255 paddr,
256 ).vtable_ptr_perm()
257 },
258 forall|c: CursorOwner<'rcu, UserPtConfig>|
259 #![auto]
260 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
261;
262
263pub proof fn lemma_cursor_jump_embedded<'rcu>(
275 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
276 tracked regions: &mut MetaRegionOwners,
277 tracked guards: &mut Guards<'rcu>,
278 va: Vaddr,
279)
280 requires
281 old(owner).inv(),
282 old(regions).inv(),
283 old(owner).children_not_locked(*old(guards)),
284 old(owner).nodes_locked(*old(guards)),
285 old(owner).metaregion_sound(*old(regions)),
286 !old(owner).popped_too_high,
287 ensures
288 final(owner).inv(),
289 final(regions).inv(),
290 final(owner).children_not_locked(*final(guards)),
291 final(owner).nodes_locked(*final(guards)),
292 final(owner).metaregion_sound(*final(regions)),
293 !final(owner).popped_too_high,
294 final(regions).slots == old(regions).slots,
298 forall|i: int|
299 #![trigger final(regions).slot_owners[i]]
300 final(regions).slot_owners[i] == old(regions).slot_owners[i],
301 forall|c: CursorOwner<'rcu, UserPtConfig>|
302 #![auto]
303 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
304{
305}
306
307pub axiom fn cursor_mut_map_embedded<'rcu>(
309 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
310 tracked regions: &mut MetaRegionOwners,
311 tracked guards: &mut Guards<'rcu>,
312 tracked tlb_model: &mut TlbModel,
313 paddr: Paddr,
314 prop: PageProperty,
315)
316 requires
317 old(owner).inv(),
318 old(regions).inv(),
319 old(owner).children_not_locked(*old(guards)),
320 old(owner).nodes_locked(*old(guards)),
321 old(owner).metaregion_sound(*old(regions)),
322 !old(owner).popped_too_high,
323 old(tlb_model).inv(),
324 valid_frame_paddr(
328 paddr,
329 ),
330ensures
335 final(owner).inv(),
336 final(regions).inv(),
337 final(owner).children_not_locked(*final(guards)),
338 final(owner).nodes_locked(*final(guards)),
339 final(owner).metaregion_sound(*final(regions)),
340 !final(owner).popped_too_high,
341 final(tlb_model).inv(),
342 final(regions).slots == old(regions).slots,
343 forall|i: int|
344 #![trigger final(regions).slot_owners[i]]
345 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
346 forall|i: int|
347 #![trigger final(regions).slot_owners[i]]
348 i != frame_to_index(paddr) && old(regions).slot_owners[i].ref_count()
349 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i] == old(
350 regions,
351 ).slot_owners[i],
352 forall|i: int|
353 #![trigger final(regions).slot_owners[i].ref_count()]
354 old(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
355 ==> final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED,
356 final(regions).slot_owner(paddr).ref_count() == old(regions).slot_owner(paddr).ref_count(),
358 final(regions).slot_owner(paddr).paths_in_pt.len() == old(regions).slot_owner(
360 paddr,
361 ).paths_in_pt.len() + 1,
362 final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage,
363 final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
364 paddr,
365 ).storage_perm(),
366 forall|i: int|
368 #![trigger final(regions).slot_owners[i]]
369 final(regions).slot_owners[i].ref_count() == REF_COUNT_UNUSED
370 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
371 forall|i: int|
372 #![trigger final(regions).slot_owners[i]]
373 i != frame_to_index(paddr) && old(regions).slot_owners[i].ref_count()
374 == REF_COUNT_UNUSED && final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
375 ==> final(regions).slot_owners[i].usage !is Frame,
376 forall|c: CursorOwner<'rcu, UserPtConfig>|
377 #![auto]
378 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
379;
380
381pub axiom fn cursor_mut_unmap_embedded<'rcu>(
383 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
384 tracked regions: &mut MetaRegionOwners,
385 tracked guards: &mut Guards<'rcu>,
386 tracked tlb_model: &mut TlbModel,
387 len: usize,
388)
389 requires
390 old(owner).inv(),
391 old(regions).inv(),
392 old(owner).children_not_locked(*old(guards)),
393 old(owner).nodes_locked(*old(guards)),
394 old(owner).metaregion_sound(*old(regions)),
395 !old(owner).popped_too_high,
396 old(tlb_model).inv(),
397 ensures
398 final(owner).inv(),
399 final(regions).inv(),
400 final(owner).children_not_locked(*final(guards)),
401 final(owner).nodes_locked(*final(guards)),
402 final(owner).metaregion_sound(*final(regions)),
403 !final(owner).popped_too_high,
404 final(tlb_model).inv(),
405 final(regions).slots == old(regions).slots,
406 forall|i: int|
407 #![trigger final(regions).slot_owners[i]]
408 {
409 &&& final(regions).slot_owners[i].slot_vaddr == old(
410 regions,
411 ).slot_owners[i].slot_vaddr
412 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
413 &&& final(regions).slot_owners[i].in_list_perm == old(
414 regions,
415 ).slot_owners[i].in_list_perm
416 &&& final(regions).slot_owners[i].vtable_ptr_perm() == old(
417 regions,
418 ).slot_owners[i].vtable_ptr_perm()
419 &&& old(regions).slot_owners[i].ref_count() != REF_COUNT_UNIQUE
421 ==> final(regions).slot_owners[i].ref_count()
422 != REF_COUNT_UNIQUE
423 &&& final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
425 ==> final(regions).slot_owners[i].storage_perm() == old(
426 regions,
427 ).slot_owners[i].storage_perm()
428 },
429 forall|i: int|
431 #![trigger final(regions).slot_owners[i]]
432 !old(regions).slots.contains_key(i) ==> final(regions).slot_owners[i] == old(
433 regions,
434 ).slot_owners[i],
435 forall|i: int|
436 #![trigger final(regions).slot_owners[i]]
437 old(regions).slot_owners[i].usage is Frame ==> {
438 &&& final(regions).slot_owners[i].ref_count() + old(
439 regions,
440 ).slot_owners[i].paths_in_pt.len() == old(regions).slot_owners[i].ref_count()
441 + final(regions).slot_owners[i].paths_in_pt.len()
442 &&& final(regions).slot_owners[i].ref_count() <= old(
443 regions,
444 ).slot_owners[i].ref_count()
445 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
446 regions,
447 ).slot_owners[i].paths_in_pt.len()
448 &&& final(regions).slot_owners[i].ref_count() != 0
449 },
450 forall|i: int|
452 #![trigger final(regions).slot_owners[i]]
453 old(regions).slot_owners[i].usage == PageUsage::MMIO ==> final(regions).slot_owners[i]
454 == old(regions).slot_owners[i],
455 forall|c: CursorOwner<'rcu, UserPtConfig>|
456 #![auto]
457 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
458;
459
460pub enum CursorMutRegionsMethod {
467 Unmap(usize),
468}
469
470pub(super) proof fn open_cursor_step<'a, 'rcu>(
472 tracked vm_space: &VmSpaceOwner,
473 tracked regions: &mut MetaRegionOwners,
474 vs: VmSpaceId,
475 va: Range<Vaddr>,
476) -> (tracked res: Option<CursorEntry<'rcu>>)
477 requires
478 vm_space.inv(),
479 old(regions).inv(),
480 ensures
481 final(regions).inv(),
482 final(regions).slots == old(regions).slots,
483 forall|i: int|
484 #![trigger final(regions).slot_owners[i]]
485 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
486 forall|i: int|
487 #![trigger final(regions).slot_owners[i]]
488 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
489 &&& old(regions).slot_owners[i].ref_count() == REF_COUNT_UNUSED
490 &&& final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
491 &&& final(regions).slot_owners[i].usage !is Frame
492 },
493 forall|c: CursorOwner<'rcu, UserPtConfig>|
494 #![auto]
495 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
496 res matches Some(e) ==> e.inv(),
497 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
498 res matches Some(e) ==> e.kind == CursorKind::ReadOnly,
499 res matches Some(e) ==> e.va == va,
500 res matches Some(e) ==> e.vm_space == vs,
501{
502 let tracked owner_opt = vm_space_cursor_embedded(vm_space, regions, va);
503 match owner_opt {
504 Option::Some((owner, guards)) => {
505 let tracked entry = tracked_cursor_entry_new(
506 vs,
507 CursorKind::ReadOnly,
508 va,
509 owner,
510 guards,
511 );
512 Option::Some(entry)
513 },
514 Option::None => Option::None,
515 }
516}
517
518pub(super) proof fn open_cursor_mut_step<'a, 'rcu>(
520 tracked vm_space: &VmSpaceOwner,
521 tracked regions: &mut MetaRegionOwners,
522 vs: VmSpaceId,
523 va: Range<Vaddr>,
524) -> (tracked res: Option<CursorEntry<'rcu>>)
525 requires
526 vm_space.inv(),
527 old(regions).inv(),
528 ensures
529 final(regions).inv(),
530 final(regions).slots == old(regions).slots,
531 forall|i: int|
532 #![trigger final(regions).slot_owners[i]]
533 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
534 forall|i: int|
535 #![trigger final(regions).slot_owners[i]]
536 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
537 &&& old(regions).slot_owners[i].ref_count() == REF_COUNT_UNUSED
538 &&& final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
539 &&& final(regions).slot_owners[i].usage !is Frame
540 },
541 forall|c: CursorOwner<'rcu, UserPtConfig>|
542 #![auto]
543 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
544 res matches Some(e) ==> e.inv(),
545 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
546 res matches Some(e) ==> e.kind == CursorKind::Mutable,
547 res matches Some(e) ==> e.va == va,
548 res matches Some(e) ==> e.vm_space == vs,
549{
550 let tracked owner_opt = vm_space_cursor_mut_embedded(vm_space, regions, va);
551 match owner_opt {
552 Option::Some((owner, guards)) => {
553 let tracked entry = tracked_cursor_entry_new(
554 vs,
555 CursorKind::Mutable,
556 va,
557 owner,
558 guards,
559 );
560 Option::Some(entry)
561 },
562 Option::None => Option::None,
563 }
564}
565
566pub(super) proof fn drop_cursor_step<'rcu>(tracked _entry: CursorEntry<'rcu>) {
569}
570
571pub(super) proof fn cursor_query_step<'rcu>(
572 tracked entry: &mut CursorEntry<'rcu>,
573 tracked regions: &mut MetaRegionOwners,
574) -> (res: Option<Paddr>)
575 requires
576 old(entry).inv(),
577 old(regions).inv(),
578 old(entry).owner.metaregion_sound(*old(regions)),
579 ensures
580 final(entry).vm_space == old(entry).vm_space,
581 final(entry).kind == old(entry).kind,
582 final(entry).va == old(entry).va,
583 final(entry).inv(),
584 final(regions).inv(),
585 final(entry).owner.metaregion_sound(*final(regions)),
586 final(regions).slots == old(regions).slots,
587 res is None ==> forall|i: int|
588 #![trigger final(regions).slot_owners[i]]
589 final(regions).slot_owners[i] == old(regions).slot_owners[i],
590 res matches Some(paddr) ==> {
591 &&& valid_frame_paddr(paddr)
592 &&& old(regions).slot_owner(paddr).usage is Frame
593 &&& final(regions).slot_owner(paddr).ref_count() == (old(regions).slot_owner(
594 paddr,
595 ).ref_count() + 1) as nat
596 &&& final(regions).slot_owner(paddr).ref_count() <= REF_COUNT_MAX
597 &&& forall|i: int|
598 #![trigger final(regions).slot_owners[i]]
599 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
600 regions,
601 ).slot_owners[i]
602 &&& final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage
603 &&& final(regions).slot_owner(paddr).paths_in_pt == old(regions).slot_owner(
604 paddr,
605 ).paths_in_pt
606 &&& final(regions).slot_owner(paddr).in_list_perm == old(regions).slot_owner(
607 paddr,
608 ).in_list_perm
609 &&& final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
610 paddr,
611 ).storage_perm()
612 },
613 forall|c: CursorOwner<'rcu, UserPtConfig>|
614 #![auto]
615 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
616{
617 cursor_query_embedded(&mut entry.owner, regions, &mut entry.guards)
618}
619
620pub(super) proof fn cursor_find_next_step<'rcu>(
623 tracked entry: &mut CursorEntry<'rcu>,
624 tracked regions: &mut MetaRegionOwners,
625 len: usize,
626)
627 requires
628 old(entry).inv(),
629 old(regions).inv(),
630 old(entry).owner.metaregion_sound(*old(regions)),
631 ensures
632 final(entry).vm_space == old(entry).vm_space,
633 final(entry).kind == old(entry).kind,
634 final(entry).va == old(entry).va,
635 final(entry).inv(),
636 final(regions).inv(),
637 final(entry).owner.metaregion_sound(*final(regions)),
638 final(regions).slots == old(regions).slots,
639 forall|i: int|
642 #![trigger final(regions).slot_owners[i]]
643 final(regions).slot_owners[i] == old(regions).slot_owners[i],
644 forall|c: CursorOwner<'rcu, UserPtConfig>|
645 #![auto]
646 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
647{
648}
649
650pub(super) proof fn cursor_jump_step<'rcu>(
653 tracked entry: &mut CursorEntry<'rcu>,
654 tracked regions: &mut MetaRegionOwners,
655 va: Vaddr,
656)
657 requires
658 old(entry).inv(),
659 old(regions).inv(),
660 old(entry).owner.metaregion_sound(*old(regions)),
661 ensures
662 final(entry).vm_space == old(entry).vm_space,
663 final(entry).kind == old(entry).kind,
664 final(entry).va == old(entry).va,
665 final(entry).inv(),
666 final(regions).inv(),
667 final(entry).owner.metaregion_sound(*final(regions)),
668 final(regions).slots == old(regions).slots,
669 forall|i: int|
670 #![trigger final(regions).slot_owners[i]]
671 final(regions).slot_owners[i] == old(regions).slot_owners[i],
672 forall|c: CursorOwner<'rcu, UserPtConfig>|
673 #![auto]
674 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
675{
676 lemma_cursor_jump_embedded(&mut entry.owner, regions, &mut entry.guards, va)
677}
678
679pub(super) proof fn cursor_protect_next_step<'rcu>(
683 tracked entry: &mut CursorEntry<'rcu>,
684 tracked regions: &mut MetaRegionOwners,
685 len: usize,
686)
687 requires
688 old(entry).inv(),
689 old(regions).inv(),
690 old(entry).owner.metaregion_sound(*old(regions)),
691 ensures
692 final(entry).vm_space == old(entry).vm_space,
693 final(entry).kind == old(entry).kind,
694 final(entry).va == old(entry).va,
695 final(entry).inv(),
696 final(regions).inv(),
697 final(entry).owner.metaregion_sound(*final(regions)),
698 final(regions).slots == old(regions).slots,
699 forall|i: int|
700 #![trigger final(regions).slot_owners[i]]
701 final(regions).slot_owners[i] == old(regions).slot_owners[i],
702 forall|c: CursorOwner<'rcu, UserPtConfig>|
703 #![auto]
704 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
705{
706}
707
708pub(super) proof fn cursor_mut_regions_step<'rcu>(
712 tracked entry: &mut CursorEntry<'rcu>,
713 tracked regions: &mut MetaRegionOwners,
714 tracked tlb_model: &mut TlbModel,
715 method: CursorMutRegionsMethod,
716)
717 requires
718 old(entry).inv(),
719 old(regions).inv(),
720 old(entry).owner.metaregion_sound(*old(regions)),
721 old(tlb_model).inv(),
722 ensures
723 final(entry).vm_space == old(entry).vm_space,
724 final(entry).kind == old(entry).kind,
725 final(entry).va == old(entry).va,
726 final(entry).inv(),
727 final(regions).inv(),
728 final(entry).owner.metaregion_sound(*final(regions)),
729 final(tlb_model).inv(),
730 final(regions).slots == old(regions).slots,
731 forall|i: int|
732 #![trigger final(regions).slot_owners[i]]
733 {
734 &&& final(regions).slot_owners[i].slot_vaddr == old(
735 regions,
736 ).slot_owners[i].slot_vaddr
737 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
738 &&& final(regions).slot_owners[i].in_list_perm == old(
739 regions,
740 ).slot_owners[i].in_list_perm
741 &&& final(regions).slot_owners[i].vtable_ptr_perm() == old(
742 regions,
743 ).slot_owners[i].vtable_ptr_perm()
744 &&& old(regions).slot_owners[i].ref_count() != REF_COUNT_UNIQUE
745 ==> final(regions).slot_owners[i].ref_count() != REF_COUNT_UNIQUE
746 &&& final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
747 ==> final(regions).slot_owners[i].storage_perm() == old(
748 regions,
749 ).slot_owners[i].storage_perm()
750 },
751 forall|i: int|
754 #![trigger final(regions).slot_owners[i]]
755 !old(regions).slots.contains_key(i) ==> final(regions).slot_owners[i] == old(
756 regions,
757 ).slot_owners[i],
758 forall|i: int|
759 #![trigger final(regions).slot_owners[i]]
760 old(regions).slot_owners[i].usage is Frame ==> {
761 &&& final(regions).slot_owners[i].ref_count() + old(
762 regions,
763 ).slot_owners[i].paths_in_pt.len() == old(regions).slot_owners[i].ref_count()
764 + final(regions).slot_owners[i].paths_in_pt.len()
765 &&& final(regions).slot_owners[i].ref_count() <= old(
766 regions,
767 ).slot_owners[i].ref_count()
768 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
769 regions,
770 ).slot_owners[i].paths_in_pt.len()
771 &&& final(regions).slot_owners[i].ref_count() != 0
772 },
773 forall|i: int|
774 #![trigger final(regions).slot_owners[i]]
775 old(regions).slot_owners[i].usage == PageUsage::MMIO ==> final(regions).slot_owners[i]
776 == old(regions).slot_owners[i],
777 forall|c: CursorOwner<'rcu, UserPtConfig>|
778 #![auto]
779 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
780{
781 match method {
782 CursorMutRegionsMethod::Unmap(len) => {
783 cursor_mut_unmap_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, len);
784 },
785 }
786}
787
788pub(super) proof fn map_step<'rcu>(
790 tracked entry: &mut CursorEntry<'rcu>,
791 tracked regions: &mut MetaRegionOwners,
792 tracked tlb_model: &mut TlbModel,
793 paddr: Paddr,
794 prop: PageProperty,
795)
796 requires
797 old(entry).inv(),
798 old(regions).inv(),
799 old(entry).owner.metaregion_sound(*old(regions)),
800 old(tlb_model).inv(),
801 valid_frame_paddr(paddr),
802 ensures
803 final(entry).vm_space == old(entry).vm_space,
804 final(entry).kind == old(entry).kind,
805 final(entry).va == old(entry).va,
806 final(entry).inv(),
807 final(regions).inv(),
808 final(entry).owner.metaregion_sound(*final(regions)),
809 final(tlb_model).inv(),
810 final(regions).slots == old(regions).slots,
811 forall|i: int|
813 #![trigger final(regions).slot_owners[i]]
814 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
815 forall|i: int|
816 #![trigger final(regions).slot_owners[i]]
817 i != frame_to_index(paddr) && old(regions).slot_owners[i].ref_count()
818 != REF_COUNT_UNUSED ==> final(regions).slot_owners[i] == old(
819 regions,
820 ).slot_owners[i],
821 forall|i: int|
822 #![trigger final(regions).slot_owners[i].ref_count()]
823 old(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
824 ==> final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED,
825 final(regions).slot_owner(paddr).ref_count() == old(regions).slot_owner(paddr).ref_count(),
826 final(regions).slot_owner(paddr).paths_in_pt.len() == old(regions).slot_owner(
827 paddr,
828 ).paths_in_pt.len() + 1,
829 final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage,
830 final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
831 paddr,
832 ).storage_perm(),
833 forall|i: int|
834 #![trigger final(regions).slot_owners[i]]
835 final(regions).slot_owners[i].ref_count() == REF_COUNT_UNUSED
836 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
837 forall|i: int|
838 #![trigger final(regions).slot_owners[i]]
839 i != frame_to_index(paddr) && old(regions).slot_owners[i].ref_count()
840 == REF_COUNT_UNUSED && final(regions).slot_owners[i].ref_count() != REF_COUNT_UNUSED
841 ==> final(regions).slot_owners[i].usage !is Frame,
842 forall|c: CursorOwner<'rcu, UserPtConfig>|
843 #![auto]
844 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
845{
846 cursor_mut_map_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, paddr, prop);
847}
848
849}