1use vstd::prelude::*;
47use vstd_extra::ownership::*;
48
49use crate::specs::{
50 arch::*,
51 mm::{
52 frame::{
53 mapping::frame_to_index, meta_owners::PageUsage, meta_region_owners::MetaRegionOwners,
54 },
55 page_table::{cursor::owners::CursorOwner, node::Guards},
56 tlb::TlbModel,
57 },
58};
59
60use super::{CursorEntry, CursorKind, VmSpaceId, tracked_cursor_entry_new};
61use crate::mm::{
62 Paddr, Vaddr,
63 frame::{
64 UFrame,
65 meta::{REF_COUNT_MAX, REF_COUNT_UNIQUE, REF_COUNT_UNUSED},
66 },
67 page_prop::PageProperty,
68 vm_space::{UserPtConfig, vm_space_specs::VmSpaceOwner},
69};
70use core::ops::Range;
71
72verus! {
73
74pub axiom fn vm_space_cursor_embedded<'a, 'rcu>(
91 tracked vm_space: &VmSpaceOwner,
92 tracked regions: &mut MetaRegionOwners,
93 va: Range<Vaddr>,
94) -> (tracked res: Option<(CursorOwner<'rcu, UserPtConfig>, Guards)>)
95 requires
96 vm_space.inv(),
97 old(regions).inv(),
98 ensures
99 final(regions).inv(),
100 final(regions).slots == old(regions).slots,
108 forall|i: int|
109 #![trigger final(regions).slot_owners[i]]
110 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
111 forall|i: int|
112 #![trigger final(regions).slot_owners[i]]
113 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
114 &&& old(regions).ref_count(i) == REF_COUNT_UNUSED
115 &&& final(regions).ref_count(i) != REF_COUNT_UNUSED
116 &&& final(regions).slot_owners[i].usage !is Frame
117 },
118 forall|c: CursorOwner<'rcu, UserPtConfig>|
119 #![auto]
120 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
121 res matches Some((c, g)) ==> {
122 &&& c.barrier_va == va
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)>)
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: int|
151 #![trigger final(regions).slot_owners[i]]
152 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
153 forall|i: int|
154 #![trigger final(regions).slot_owners[i]]
155 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
156 &&& old(regions).ref_count(i) == REF_COUNT_UNUSED
157 &&& final(regions).ref_count(i) != REF_COUNT_UNUSED
158 &&& final(regions).slot_owners[i].usage !is Frame
159 },
160 forall|c: CursorOwner<'rcu, UserPtConfig>|
161 #![auto]
162 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
163 res matches Some((c, g)) ==> {
164 &&& c.barrier_va == va
165 &&& c.inv()
166 &&& c.children_not_locked(g)
167 &&& c.nodes_locked(g)
168 &&& !c.popped_too_high
169 &&& c.metaregion_sound(*final(regions))
170 },
171;
172
173pub axiom fn cursor_query_embedded<'rcu>(
199 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
200 tracked regions: &mut MetaRegionOwners,
201 tracked guards: &mut Guards,
202) -> (res: Option<Paddr>)
203 requires
204 old(owner).inv(),
205 old(regions).inv(),
206 old(owner).children_not_locked(*old(guards)),
207 old(owner).nodes_locked(*old(guards)),
208 old(owner).metaregion_sound(*old(regions)),
209 !old(owner).popped_too_high,
210 ensures
211 final(owner).inv(),
212 final(owner).barrier_va == old(owner).barrier_va,
213 final(regions).inv(),
214 final(owner).children_not_locked(*final(guards)),
215 final(owner).nodes_locked(*final(guards)),
216 final(owner).metaregion_sound(*final(regions)),
217 !final(owner).popped_too_high,
218 final(regions).slots == old(regions).slots,
219 res is None ==> forall|i: int|
220 #![trigger final(regions).slot_owners[i]]
221 final(regions).slot_owners[i] == old(regions).slot_owners[i],
222 res matches Some(paddr) ==> {
223 &&& old(owner).in_barrier_va()
224 &&& valid_frame_paddr(paddr)
225 &&& old(regions).slot_owner(paddr).usage is Frame
226 &&& final(regions).slot_owner(paddr).ref_count() == (old(regions).slot_owner(
227 paddr,
228 ).ref_count() + 1) as nat
229 &&& final(regions).slot_owner(paddr).ref_count() <= REF_COUNT_MAX
230 &&& forall|i: int|
231 #![trigger final(regions).slot_owners[i]]
232 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
233 regions,
234 ).slot_owners[i]
235 &&& final(regions).slot_owner(paddr).slot_vaddr == old(regions).slot_owner(
236 paddr,
237 ).slot_vaddr
238 &&& final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage
239 &&& final(regions).slot_owner(paddr).paths_in_pt == old(regions).slot_owner(
240 paddr,
241 ).paths_in_pt
242 &&& final(regions).slot_owner(paddr).in_list_perm == old(regions).slot_owner(
243 paddr,
244 ).in_list_perm
245 &&& final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
246 paddr,
247 ).storage_perm()
248 &&& final(regions).slot_owner(paddr).vtable_ptr_perm() == old(regions).slot_owner(
249 paddr,
250 ).vtable_ptr_perm()
251 },
252 forall|c: CursorOwner<'rcu, UserPtConfig>|
253 #![auto]
254 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
255;
256
257pub proof fn lemma_cursor_jump_embedded<'rcu>(
269 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
270 tracked regions: &mut MetaRegionOwners,
271 tracked guards: &mut Guards,
272 va: Vaddr,
273)
274 requires
275 old(owner).inv(),
276 old(regions).inv(),
277 old(owner).children_not_locked(*old(guards)),
278 old(owner).nodes_locked(*old(guards)),
279 old(owner).metaregion_sound(*old(regions)),
280 !old(owner).popped_too_high,
281 ensures
282 final(owner).inv(),
283 final(owner).barrier_va == old(owner).barrier_va,
284 final(regions).inv(),
285 final(owner).children_not_locked(*final(guards)),
286 final(owner).nodes_locked(*final(guards)),
287 final(owner).metaregion_sound(*final(regions)),
288 !final(owner).popped_too_high,
289 final(regions).slots == old(regions).slots,
293 forall|i: int|
294 #![trigger final(regions).slot_owners[i]]
295 final(regions).slot_owners[i] == old(regions).slot_owners[i],
296 forall|c: CursorOwner<'rcu, UserPtConfig>|
297 #![auto]
298 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
299{
300}
301
302pub axiom fn cursor_mut_map_embedded<'rcu>(
304 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
305 tracked regions: &mut MetaRegionOwners,
306 tracked guards: &mut Guards,
307 tracked tlb_model: &mut TlbModel,
308 paddr: Paddr,
309 prop: PageProperty,
310)
311 requires
312 old(owner).inv(),
313 old(regions).inv(),
314 old(owner).children_not_locked(*old(guards)),
315 old(owner).nodes_locked(*old(guards)),
316 old(owner).metaregion_sound(*old(regions)),
317 !old(owner).popped_too_high,
318 old(tlb_model).inv(),
319 valid_frame_paddr(
323 paddr,
324 ),
325ensures
330 final(owner).inv(),
331 final(owner).barrier_va == old(owner).barrier_va,
332 final(regions).inv(),
333 final(owner).children_not_locked(*final(guards)),
334 final(owner).nodes_locked(*final(guards)),
335 final(owner).metaregion_sound(*final(regions)),
336 !final(owner).popped_too_high,
337 final(tlb_model).inv(),
338 final(regions).slots == old(regions).slots,
339 forall|i: int|
340 #![trigger final(regions).slot_owners[i]]
341 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
342 forall|i: int|
343 #![trigger final(regions).slot_owners[i]]
344 i != frame_to_index(paddr) && old(regions).ref_count(i) != REF_COUNT_UNUSED
345 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
346 forall|i: int|
347 #![trigger final(regions).slot_owners[i].ref_count()]
348 old(regions).ref_count(i) != REF_COUNT_UNUSED ==> final(regions).ref_count(i)
349 != REF_COUNT_UNUSED,
350 final(regions).slot_owner(paddr).ref_count() == old(regions).slot_owner(paddr).ref_count(),
352 final(regions).slot_owner(paddr).paths_in_pt.len() == old(regions).slot_owner(
354 paddr,
355 ).paths_in_pt.len() + 1,
356 final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage,
357 final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
358 paddr,
359 ).storage_perm(),
360 forall|i: int|
362 #![trigger final(regions).slot_owners[i]]
363 final(regions).ref_count(i) == REF_COUNT_UNUSED ==> final(regions).slot_owners[i]
364 == old(regions).slot_owners[i],
365 forall|i: int|
366 #![trigger final(regions).slot_owners[i]]
367 i != frame_to_index(paddr) && old(regions).ref_count(i) == REF_COUNT_UNUSED
368 && final(regions).ref_count(i) != REF_COUNT_UNUSED
369 ==> final(regions).slot_owners[i].usage !is Frame,
370 forall|c: CursorOwner<'rcu, UserPtConfig>|
371 #![auto]
372 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
373;
374
375pub axiom fn cursor_mut_unmap_embedded<'rcu>(
377 tracked owner: &mut CursorOwner<'rcu, UserPtConfig>,
378 tracked regions: &mut MetaRegionOwners,
379 tracked guards: &mut Guards,
380 tracked tlb_model: &mut TlbModel,
381 len: usize,
382)
383 requires
384 old(owner).inv(),
385 old(regions).inv(),
386 old(owner).children_not_locked(*old(guards)),
387 old(owner).nodes_locked(*old(guards)),
388 old(owner).metaregion_sound(*old(regions)),
389 !old(owner).popped_too_high,
390 old(tlb_model).inv(),
391 ensures
392 final(owner).inv(),
393 final(owner).barrier_va == old(owner).barrier_va,
394 final(regions).inv(),
395 final(owner).children_not_locked(*final(guards)),
396 final(owner).nodes_locked(*final(guards)),
397 final(owner).metaregion_sound(*final(regions)),
398 !final(owner).popped_too_high,
399 final(tlb_model).inv(),
400 final(regions).slots == old(regions).slots,
401 forall|i: int|
402 #![trigger final(regions).slot_owners[i]]
403 {
404 &&& final(regions).slot_owners[i].slot_vaddr == old(
405 regions,
406 ).slot_owners[i].slot_vaddr
407 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
408 &&& final(regions).slot_owners[i].in_list_perm == old(
409 regions,
410 ).slot_owners[i].in_list_perm
411 &&& final(regions).slot_owners[i].vtable_ptr_perm() == old(
412 regions,
413 ).slot_owners[i].vtable_ptr_perm()
414 &&& old(regions).ref_count(i) != REF_COUNT_UNIQUE ==> final(regions).ref_count(i)
416 != REF_COUNT_UNIQUE
417 &&& final(regions).ref_count(i) != REF_COUNT_UNUSED
419 ==> final(regions).slot_owners[i].storage_perm() == old(
420 regions,
421 ).slot_owners[i].storage_perm()
422 },
423 forall|i: int|
425 #![trigger final(regions).slot_owners[i]]
426 !old(regions).slots.contains_key(i) ==> final(regions).slot_owners[i] == old(
427 regions,
428 ).slot_owners[i],
429 forall|i: int|
430 #![trigger final(regions).slot_owners[i]]
431 old(regions).slot_owners[i].usage is Frame ==> {
432 &&& final(regions).ref_count(i) + old(regions).slot_owners[i].paths_in_pt.len()
433 == old(regions).ref_count(i) + final(regions).slot_owners[i].paths_in_pt.len()
434 &&& final(regions).ref_count(i) <= old(regions).ref_count(i)
435 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
436 regions,
437 ).slot_owners[i].paths_in_pt.len()
438 &&& final(regions).ref_count(i) != 0
439 },
440 forall|c: CursorOwner<'rcu, UserPtConfig>|
441 #![auto]
442 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
443;
444
445pub enum CursorMutRegionsMethod {
452 Unmap(usize),
453}
454
455pub(super) proof fn open_cursor_step<'a, 'rcu>(
457 tracked vm_space: &VmSpaceOwner,
458 tracked regions: &mut MetaRegionOwners,
459 vs: VmSpaceId,
460 va: Range<Vaddr>,
461) -> (tracked res: Option<CursorEntry<'rcu>>)
462 requires
463 vm_space.inv(),
464 old(regions).inv(),
465 ensures
466 final(regions).inv(),
467 final(regions).slots == old(regions).slots,
468 forall|i: int|
469 #![trigger final(regions).slot_owners[i]]
470 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
471 forall|i: int|
472 #![trigger final(regions).slot_owners[i]]
473 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
474 &&& old(regions).ref_count(i) == REF_COUNT_UNUSED
475 &&& final(regions).ref_count(i) != REF_COUNT_UNUSED
476 &&& final(regions).slot_owners[i].usage !is Frame
477 },
478 forall|c: CursorOwner<'rcu, UserPtConfig>|
479 #![auto]
480 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
481 res matches Some(e) ==> e.inv(),
482 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
483 res matches Some(e) ==> e.kind == CursorKind::ReadOnly,
484 res matches Some(e) ==> e.va == va,
485 res matches Some(e) ==> e.vm_space == vs,
486{
487 let tracked owner_opt = vm_space_cursor_embedded(vm_space, regions, va);
488 match owner_opt {
489 Option::Some((owner, guards)) => {
490 let tracked entry = tracked_cursor_entry_new(
491 vs,
492 CursorKind::ReadOnly,
493 va,
494 owner,
495 guards,
496 );
497 Option::Some(entry)
498 },
499 Option::None => Option::None,
500 }
501}
502
503pub(super) proof fn open_cursor_mut_step<'a, 'rcu>(
505 tracked vm_space: &VmSpaceOwner,
506 tracked regions: &mut MetaRegionOwners,
507 vs: VmSpaceId,
508 va: Range<Vaddr>,
509) -> (tracked res: Option<CursorEntry<'rcu>>)
510 requires
511 vm_space.inv(),
512 old(regions).inv(),
513 ensures
514 final(regions).inv(),
515 final(regions).slots == old(regions).slots,
516 forall|i: int|
517 #![trigger final(regions).slot_owners[i]]
518 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
519 forall|i: int|
520 #![trigger final(regions).slot_owners[i]]
521 final(regions).slot_owners[i] != old(regions).slot_owners[i] ==> {
522 &&& old(regions).ref_count(i) == REF_COUNT_UNUSED
523 &&& final(regions).ref_count(i) != REF_COUNT_UNUSED
524 &&& final(regions).slot_owners[i].usage !is Frame
525 },
526 forall|c: CursorOwner<'rcu, UserPtConfig>|
527 #![auto]
528 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
529 res matches Some(e) ==> e.inv(),
530 res matches Some(e) ==> e.owner.metaregion_sound(*final(regions)),
531 res matches Some(e) ==> e.kind == CursorKind::Mutable,
532 res matches Some(e) ==> e.va == va,
533 res matches Some(e) ==> e.vm_space == vs,
534{
535 let tracked owner_opt = vm_space_cursor_mut_embedded(vm_space, regions, va);
536 match owner_opt {
537 Option::Some((owner, guards)) => {
538 let tracked entry = tracked_cursor_entry_new(
539 vs,
540 CursorKind::Mutable,
541 va,
542 owner,
543 guards,
544 );
545 Option::Some(entry)
546 },
547 Option::None => Option::None,
548 }
549}
550
551pub(super) proof fn drop_cursor_step<'rcu>(tracked _entry: CursorEntry<'rcu>) {
554}
555
556pub(super) proof fn cursor_query_step<'rcu>(
557 tracked entry: &mut CursorEntry<'rcu>,
558 tracked regions: &mut MetaRegionOwners,
559) -> (res: Option<Paddr>)
560 requires
561 old(entry).inv(),
562 old(regions).inv(),
563 old(entry).owner.metaregion_sound(*old(regions)),
564 ensures
565 final(entry).vm_space == old(entry).vm_space,
566 final(entry).kind == old(entry).kind,
567 final(entry).va == old(entry).va,
568 final(entry).inv(),
569 final(regions).inv(),
570 final(entry).owner.metaregion_sound(*final(regions)),
571 final(regions).slots == old(regions).slots,
572 res is None ==> forall|i: int|
573 #![trigger final(regions).slot_owners[i]]
574 final(regions).slot_owners[i] == old(regions).slot_owners[i],
575 res matches Some(paddr) ==> {
576 &&& old(entry).owner.in_barrier_va()
577 &&& valid_frame_paddr(paddr)
578 &&& old(regions).slot_owner(paddr).usage is Frame
579 &&& final(regions).slot_owner(paddr).ref_count() == (old(regions).slot_owner(
580 paddr,
581 ).ref_count() + 1) as nat
582 &&& final(regions).slot_owner(paddr).ref_count() <= REF_COUNT_MAX
583 &&& forall|i: int|
584 #![trigger final(regions).slot_owners[i]]
585 i != frame_to_index(paddr) ==> final(regions).slot_owners[i] == old(
586 regions,
587 ).slot_owners[i]
588 &&& final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage
589 &&& final(regions).slot_owner(paddr).paths_in_pt == old(regions).slot_owner(
590 paddr,
591 ).paths_in_pt
592 &&& final(regions).slot_owner(paddr).in_list_perm == old(regions).slot_owner(
593 paddr,
594 ).in_list_perm
595 &&& final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
596 paddr,
597 ).storage_perm()
598 },
599 forall|c: CursorOwner<'rcu, UserPtConfig>|
600 #![auto]
601 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
602{
603 cursor_query_embedded(&mut entry.owner, regions, &mut entry.guards)
604}
605
606pub(super) proof fn cursor_find_next_step<'rcu>(
609 tracked entry: &mut CursorEntry<'rcu>,
610 tracked regions: &mut MetaRegionOwners,
611 len: usize,
612)
613 requires
614 old(entry).inv(),
615 old(regions).inv(),
616 old(entry).owner.metaregion_sound(*old(regions)),
617 ensures
618 final(entry).vm_space == old(entry).vm_space,
619 final(entry).kind == old(entry).kind,
620 final(entry).va == old(entry).va,
621 final(entry).inv(),
622 final(regions).inv(),
623 final(entry).owner.metaregion_sound(*final(regions)),
624 final(regions).slots == old(regions).slots,
625 forall|i: int|
628 #![trigger final(regions).slot_owners[i]]
629 final(regions).slot_owners[i] == old(regions).slot_owners[i],
630 forall|c: CursorOwner<'rcu, UserPtConfig>|
631 #![auto]
632 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
633{
634}
635
636pub(super) proof fn cursor_jump_step<'rcu>(
639 tracked entry: &mut CursorEntry<'rcu>,
640 tracked regions: &mut MetaRegionOwners,
641 va: Vaddr,
642)
643 requires
644 old(entry).inv(),
645 old(regions).inv(),
646 old(entry).owner.metaregion_sound(*old(regions)),
647 ensures
648 final(entry).vm_space == old(entry).vm_space,
649 final(entry).kind == old(entry).kind,
650 final(entry).va == old(entry).va,
651 final(entry).inv(),
652 final(regions).inv(),
653 final(entry).owner.metaregion_sound(*final(regions)),
654 final(regions).slots == old(regions).slots,
655 forall|i: int|
656 #![trigger final(regions).slot_owners[i]]
657 final(regions).slot_owners[i] == old(regions).slot_owners[i],
658 forall|c: CursorOwner<'rcu, UserPtConfig>|
659 #![auto]
660 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
661{
662 lemma_cursor_jump_embedded(&mut entry.owner, regions, &mut entry.guards, va)
663}
664
665pub(super) proof fn cursor_protect_next_step<'rcu>(
669 tracked entry: &mut CursorEntry<'rcu>,
670 tracked regions: &mut MetaRegionOwners,
671 len: usize,
672)
673 requires
674 old(entry).inv(),
675 old(regions).inv(),
676 old(entry).owner.metaregion_sound(*old(regions)),
677 ensures
678 final(entry).vm_space == old(entry).vm_space,
679 final(entry).kind == old(entry).kind,
680 final(entry).va == old(entry).va,
681 final(entry).inv(),
682 final(regions).inv(),
683 final(entry).owner.metaregion_sound(*final(regions)),
684 final(regions).slots == old(regions).slots,
685 forall|i: int|
686 #![trigger final(regions).slot_owners[i]]
687 final(regions).slot_owners[i] == old(regions).slot_owners[i],
688 forall|c: CursorOwner<'rcu, UserPtConfig>|
689 #![auto]
690 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
691{
692}
693
694pub(super) proof fn cursor_mut_regions_step<'rcu>(
698 tracked entry: &mut CursorEntry<'rcu>,
699 tracked regions: &mut MetaRegionOwners,
700 tracked tlb_model: &mut TlbModel,
701 method: CursorMutRegionsMethod,
702)
703 requires
704 old(entry).inv(),
705 old(regions).inv(),
706 old(entry).owner.metaregion_sound(*old(regions)),
707 old(tlb_model).inv(),
708 ensures
709 final(entry).vm_space == old(entry).vm_space,
710 final(entry).kind == old(entry).kind,
711 final(entry).va == old(entry).va,
712 final(entry).inv(),
713 final(regions).inv(),
714 final(entry).owner.metaregion_sound(*final(regions)),
715 final(tlb_model).inv(),
716 final(regions).slots == old(regions).slots,
717 forall|i: int|
718 #![trigger final(regions).slot_owners[i]]
719 {
720 &&& final(regions).slot_owners[i].slot_vaddr == old(
721 regions,
722 ).slot_owners[i].slot_vaddr
723 &&& final(regions).slot_owners[i].usage == old(regions).slot_owners[i].usage
724 &&& final(regions).slot_owners[i].in_list_perm == old(
725 regions,
726 ).slot_owners[i].in_list_perm
727 &&& final(regions).slot_owners[i].vtable_ptr_perm() == old(
728 regions,
729 ).slot_owners[i].vtable_ptr_perm()
730 &&& old(regions).ref_count(i) != REF_COUNT_UNIQUE ==> final(regions).ref_count(i)
731 != REF_COUNT_UNIQUE
732 &&& final(regions).ref_count(i) != REF_COUNT_UNUSED
733 ==> final(regions).slot_owners[i].storage_perm() == old(
734 regions,
735 ).slot_owners[i].storage_perm()
736 },
737 forall|i: int|
740 #![trigger final(regions).slot_owners[i]]
741 !old(regions).slots.contains_key(i) ==> final(regions).slot_owners[i] == old(
742 regions,
743 ).slot_owners[i],
744 forall|i: int|
745 #![trigger final(regions).slot_owners[i]]
746 old(regions).slot_owners[i].usage is Frame ==> {
747 &&& final(regions).ref_count(i) + old(regions).slot_owners[i].paths_in_pt.len()
748 == old(regions).ref_count(i) + final(regions).slot_owners[i].paths_in_pt.len()
749 &&& final(regions).ref_count(i) <= old(regions).ref_count(i)
750 &&& final(regions).slot_owners[i].paths_in_pt.len() <= old(
751 regions,
752 ).slot_owners[i].paths_in_pt.len()
753 &&& final(regions).ref_count(i) != 0
754 },
755 forall|c: CursorOwner<'rcu, UserPtConfig>|
756 #![auto]
757 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
758{
759 match method {
760 CursorMutRegionsMethod::Unmap(len) => {
761 cursor_mut_unmap_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, len);
762 },
763 }
764}
765
766pub(super) proof fn map_step<'rcu>(
768 tracked entry: &mut CursorEntry<'rcu>,
769 tracked regions: &mut MetaRegionOwners,
770 tracked tlb_model: &mut TlbModel,
771 paddr: Paddr,
772 prop: PageProperty,
773)
774 requires
775 old(entry).inv(),
776 old(regions).inv(),
777 old(entry).owner.metaregion_sound(*old(regions)),
778 old(tlb_model).inv(),
779 valid_frame_paddr(paddr),
780 ensures
781 final(entry).vm_space == old(entry).vm_space,
782 final(entry).kind == old(entry).kind,
783 final(entry).va == old(entry).va,
784 final(entry).inv(),
785 final(regions).inv(),
786 final(entry).owner.metaregion_sound(*final(regions)),
787 final(tlb_model).inv(),
788 final(regions).slots == old(regions).slots,
789 forall|i: int|
791 #![trigger final(regions).slot_owners[i]]
792 final(regions).slot_owners[i].in_list_perm == old(regions).slot_owners[i].in_list_perm,
793 forall|i: int|
794 #![trigger final(regions).slot_owners[i]]
795 i != frame_to_index(paddr) && old(regions).ref_count(i) != REF_COUNT_UNUSED
796 ==> final(regions).slot_owners[i] == old(regions).slot_owners[i],
797 forall|i: int|
798 #![trigger final(regions).slot_owners[i].ref_count()]
799 old(regions).ref_count(i) != REF_COUNT_UNUSED ==> final(regions).ref_count(i)
800 != REF_COUNT_UNUSED,
801 final(regions).slot_owner(paddr).ref_count() == old(regions).slot_owner(paddr).ref_count(),
802 final(regions).slot_owner(paddr).paths_in_pt.len() == old(regions).slot_owner(
803 paddr,
804 ).paths_in_pt.len() + 1,
805 final(regions).slot_owner(paddr).usage == old(regions).slot_owner(paddr).usage,
806 final(regions).slot_owner(paddr).storage_perm() == old(regions).slot_owner(
807 paddr,
808 ).storage_perm(),
809 forall|i: int|
810 #![trigger final(regions).slot_owners[i]]
811 final(regions).ref_count(i) == REF_COUNT_UNUSED ==> final(regions).slot_owners[i]
812 == old(regions).slot_owners[i],
813 forall|i: int|
814 #![trigger final(regions).slot_owners[i]]
815 i != frame_to_index(paddr) && old(regions).ref_count(i) == REF_COUNT_UNUSED
816 && final(regions).ref_count(i) != REF_COUNT_UNUSED
817 ==> final(regions).slot_owners[i].usage !is Frame,
818 forall|c: CursorOwner<'rcu, UserPtConfig>|
819 #![auto]
820 c.metaregion_sound(*old(regions)) ==> c.metaregion_sound(*final(regions)),
821{
822 cursor_mut_map_embedded(&mut entry.owner, regions, &mut entry.guards, tlb_model, paddr, prop);
823}
824
825}