1use vstd::prelude::*;
4use vstd::simple_pptr::{self, PPtr};
5
6use vstd_extra::cast_ptr::*;
7use vstd_extra::drop_tracking::*;
8use vstd_extra::ownership::*;
9
10use crate::specs::arch::*;
11use crate::specs::mm::frame::{
12 mapping::{frame_to_index, group_page_meta, index_to_meta, max_meta_slots, meta_to_index},
13 meta_owners::{MetaSlotStorage, borrow_meta, borrow_meta_mut},
14 meta_region_owners::MetaRegionOwners,
15 unique::UniqueFrameOwner,
16};
17
18use core::{marker::PhantomData, sync::atomic::Ordering};
19
20use super::{
21 AnyFrameMeta, Frame, MetaSlot,
22 mapping::{frame_to_meta, meta_to_frame},
23 meta::{GetFrameError, META_SLOT_SIZE, REF_COUNT_UNIQUE, REF_COUNT_UNUSED},
24};
25use crate::mm::{Paddr, PagingConsts, PagingLevel};
26
27verus! {
28
29pub struct UniqueFrame<M: AnyFrameMeta + ?Sized + Repr<MetaSlotStorage> + OwnerOf> {
30 pub ptr: PPtr<MetaSlot>,
31 pub _marker: PhantomData<M>,
32}
33
34#[verifier::external]
35unsafe impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + Send> Send for UniqueFrame<M> {
36
37}
38
39#[verifier::external]
40unsafe impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + Sync> Sync for UniqueFrame<M> {
41
42}
43
44#[verus_verify]
52impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> UniqueFrame<M> {
53 #[verus_spec(res =>
66 with
67 Tracked(regions): Tracked<&mut MetaRegionOwners>,
68 Tracked(meta_own_in): Tracked<M::Owner>,
69 Tracked(repr_perm_in): Tracked<M::ReprPerm>,
70 -> owner: Tracked<Option<UniqueFrameOwner<M>>>,
71 requires
72 old(regions).contains(frame_to_index(paddr)),
73 old(regions).slot_owner(paddr).usage is Unused,
74 old(regions).inv(),
75 <M as OwnerOf>::wf(metadata, meta_own_in),
76 ensures
77 !valid_frame_paddr(paddr) ==> res is Err,
78 res is Ok ==> {
79 &&& owner@ is Some
80 &&& res.unwrap().wf(owner@->0)
81 &&& owner@->0.meta_own == meta_own_in
82 &&& owner@->0.meta_value(*final(regions)) == metadata
83 &&& final(regions).frame_obligations == old(regions).frame_obligations.insert(frame_to_index(paddr))
84 },
85 res is Err ==> {
86 &&& owner@ is None
87 &&& final(regions).frame_obligations == old(regions).frame_obligations
88 },
89 final(regions).inv(),
90 )]
91 pub fn from_unused(paddr: Paddr, metadata: M) -> Result<Self, GetFrameError> {
92 let tracked mut repr_perm = repr_perm_in;
93 #[verus_spec(with Tracked(regions), Tracked(&mut repr_perm))]
94 let from_unused = MetaSlot::get_from_unused(paddr, metadata, true);
95
96 if let Err(err) = from_unused {
97 proof_with!(|= Tracked(None));
98 Err(err)
99 } else {
100 let ptr = from_unused.unwrap();
101
102 proof_decl! {
103 let tracked owner = UniqueFrameOwner::<M>::tracked_from_unused_owner(
104 meta_own_in,
105 repr_perm,
106 frame_to_index(paddr),
107 );
108 let ghost idx = frame_to_index(paddr);
109 }
110 proof {
111 let tracked _ = regions.tracked_mint_frame_obligation(idx);
113 }
114
115 proof_with!(|= Tracked(Some(owner)));
116 Ok(Self { ptr, _marker: PhantomData })
117 }
118 }
119
120 pub open spec fn transmute_spec<M1: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf>(
121 self,
122 transmuted: UniqueFrame<M1>,
123 ) -> bool {
124 &&& transmuted.ptr.addr() == self.ptr.addr()
125 &&& transmuted._marker == PhantomData::<M1>
126 }
127
128 #[verifier::external_body]
129 #[verus_spec(res =>
130 ensures
131 Self::transmute_spec(self, res),
132 )]
133 pub fn transmute<M1: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf>(self) -> UniqueFrame<M1> {
134 unimplemented!()
135 }
136
137 #[verus_spec(res =>
149 with
150 Tracked(owner): Tracked<UniqueFrameOwner<M>>,
151 Tracked(regions): Tracked<&mut MetaRegionOwners>,
152 Tracked(meta_own_in): Tracked<M1::Owner>,
153 Tracked(repr_perm_in): Tracked<M1::ReprPerm>,
154 -> new_owner: Tracked<UniqueFrameOwner<M1>>,
155 requires
156 self.wf(owner),
157 owner.inv(),
158 owner.global_inv(*old(regions)),
159 old(regions).slot_owners[self.index()].in_list_perm.value() == 0,
160 old(regions).inv(),
161 <M1 as OwnerOf>::wf(metadata, meta_own_in),
162 ensures
163 res.wf(new_owner@),
164 new_owner@.meta_own == meta_own_in,
165 new_owner@.meta_value(*final(regions)) == metadata,
166 final(regions).inv(),
167 )]
168 pub fn repurpose<M1: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf>(
169 self,
170 metadata: M1,
171 ) -> UniqueFrame<M1> {
172 let tracked mut repr_perm = repr_perm_in;
173 let ghost idx = self.index();
174 proof {
175 broadcast use group_page_meta;
176
177 assert(idx == owner.slot_index);
178 }
179 let tracked slot_own = regions.slot_owners.tracked_borrow_mut(idx);
180 let tracked perm_ref = regions.slots.tracked_borrow(idx);
181
182 #[verus_spec(with Tracked(perm_ref))]
183 let slot = self.slot();
184
185 assert(slot_own.inv()) by {
186 assert(old(regions).contains(idx));
187 assert(old(regions).slot_owners[idx].inv());
188 }
189
190 unsafe {
192 #[verus_spec(with Tracked(&mut slot_own))]
193 slot.drop_meta_in_place()
194 };
195
196 let tracked mut metadata_perms = slot_own.tracked_borrow_mut_metadata_perms();
197
198 proof {
199 assert(metadata_perms.storage_perm.id() == perm_ref.value().storage.id());
200 }
201
202 let slot = self.ptr.borrow(Tracked(perm_ref));
203
204 unsafe {
205 #[verus_spec(with
206 Tracked(&mut metadata_perms.storage_perm),
207 Tracked(&mut repr_perm),
208 Tracked(&mut metadata_perms.vtable_ptr_perm)
209 )]
210 slot.write_meta(metadata)
211 };
212
213 let tracked mut new_owner = UniqueFrameOwner::<M1>::tracked_from_unused_owner(
214 meta_own_in,
215 repr_perm,
216 meta_to_index(self.ptr.addr()),
217 );
218
219 proof_with!(|= Tracked(new_owner));
221 self.transmute()
222 }
223
224 #[verus_spec(l =>
234 with
235 Tracked(owner): Tracked<&'a UniqueFrameOwner<M>>,
236 Tracked(regions): Tracked<&'a MetaRegionOwners>,
237 requires
238 owner.inv(),
239 self.wf(*owner),
240 owner.global_inv(*regions),
241 ensures
242 owner.meta_value(*regions) == l,
243 )]
244 pub fn meta<'a>(&self) -> &'a M {
245 let tracked points_to = regions.slots.tracked_borrow(owner.slot_index);
248 let tracked slot_owner = regions.slot_owners.tracked_borrow(owner.slot_index);
249 borrow_meta(
250 ReprPtr::<MetaSlotStorage, M>::from_pptr(PPtr::from_addr(self.ptr.addr())),
251 Tracked(points_to),
252 Tracked(&slot_owner.metadata_perm),
253 Tracked(owner.tracked_borrow_repr_perm()),
254 )
255 }
256
257 #[verus_spec(res =>
267 with
268 Tracked(owner): Tracked<&'a mut UniqueFrameOwner<M>>,
269 Tracked(regions): Tracked<&'a mut MetaRegionOwners>,
270 requires
271 owner.inv(),
272 old(self).wf(*owner),
273 old(regions).inv(),
274 owner.global_inv(*old(regions)),
275 ensures
276 *res == old(owner).meta_value(*old(regions)),
277 *final(res) == final(owner).meta_value(*final(regions)),
278 *final(self) == *old(self),
279 final(owner).meta_own == old(owner).meta_own,
280 final(owner).slot_index == old(owner).slot_index,
281 final(owner).inv(),
282 final(owner).meta_wf(*final(regions)),
283 (*final(self)).wf(*final(owner)),
284 final(regions).inv(),
285 final(regions).slots == old(regions).slots,
286 final(regions).slots.dom() == old(regions).slots.dom(),
287 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
288 forall|j: int|
289 #![trigger final(regions).slot_owners[j]]
290 j != old(owner).slot_index
291 ==> final(regions).slot_owners[j] == old(regions).slot_owners[j],
292 final(regions).slot_owners[final(owner).slot_index].slot_vaddr
293 == old(regions).slot_owners[old(owner).slot_index].slot_vaddr,
294 final(regions).slot_owners[final(owner).slot_index].usage
295 == old(regions).slot_owners[old(owner).slot_index].usage,
296 final(regions).slot_owners[final(owner).slot_index].ref_count_perm
297 == old(regions).slot_owners[old(owner).slot_index].ref_count_perm,
298 final(regions).slot_owners[final(owner).slot_index].in_list_perm
299 == old(regions).slot_owners[old(owner).slot_index].in_list_perm,
300 final(regions).slot_owners[final(owner).slot_index].paths_in_pt
301 == old(regions).slot_owners[old(owner).slot_index].paths_in_pt,
302 final(regions).frame_obligations == old(regions).frame_obligations,
303 <M as OwnerOf>::wf(final(owner).meta_value(*final(regions)), final(owner).meta_own)
304 ==> final(owner).global_inv(*final(regions)),
305 )]
306 pub fn meta_mut<'a>(&'a mut self) -> &'a mut M {
307 let tracked points_to = regions.slots.tracked_borrow(owner.slot_index);
308 let tracked slot_owner = regions.slot_owners.tracked_borrow_mut(owner.slot_index);
309 borrow_meta_mut(
310 ReprPtr::<MetaSlotStorage, M>::from_pptr(PPtr::from_addr(self.ptr.addr())),
311 Tracked(points_to),
312 Tracked(slot_owner),
313 Tracked(owner.tracked_borrow_mut_repr_perm()),
314 )
315 }
316}
317
318impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + ?Sized> UniqueFrame<M> {
319 pub const fn size(&self) -> usize
321 returns
322 PAGE_SIZE,
323 {
324 PAGE_SIZE
325 }
326
327 pub const fn level(&self) -> PagingLevel
335 returns
336 1u8,
337 {
338 1
339 }
340}
341
342#[verus_verify]
343impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + ?Sized> UniqueFrame<M> {
344 #[verus_spec(
346 with
347 Tracked(owner): Tracked<&UniqueFrameOwner<M>>,
348 Tracked(regions): Tracked<&MetaRegionOwners>,
349 requires
350 owner.inv(),
351 self.wf(*owner),
352 regions.inv(),
353 returns
354 meta_to_frame(self.ptr.addr()),
355 )]
356 pub fn start_paddr(&self) -> Paddr {
357 proof {
358 assert(regions.contains(owner.slot_index));
359 }
360 let tracked outer = regions.slots.tracked_borrow(owner.slot_index);
361 #[verus_spec(with Tracked(outer))]
362 let slot = self.slot();
363
364 #[verus_spec(with Tracked(outer))]
365 slot.frame_paddr()
366 }
367
368 #[verus_spec(
400 with
401 Tracked(owner): Tracked<UniqueFrameOwner<M>>,
402 Tracked(regions): Tracked<&mut MetaRegionOwners>,
403 requires
404 self.wf_with_region(owner, *old(regions)),
405 ensures
406 final(regions).inv(),
407 )]
408 pub fn reset_as_unused(self) {
409 let ghost idx = owner.slot_index;
410
411 proof {
412 assert(regions.slot_owners.contains_key(idx));
413 }
414
415 let tracked slot_own = regions.slot_owners.tracked_borrow_mut(idx);
416 let tracked perm_ref = regions.slots.tracked_borrow(idx);
417
418 #[verus_spec(with Tracked(perm_ref))]
419 let slot = self.slot();
420 slot.ref_count.store(Tracked(&mut slot_own.ref_count_perm), 0);
421
422 unsafe {
425 #[verus_spec(with Tracked(slot_own))]
426 slot.drop_last_in_place()
427 };
428 }
429
430 pub open spec fn into_raw_requires(self, regions: MetaRegionOwners) -> bool {
431 &&& regions.contains(
432 self.index(),
433 )
434 &&& regions.frame_obligations.count(self.index()) > 0
437 &&& regions.inv()
438 }
439
440 pub open spec fn into_raw_ensures(
441 self,
442 old_regions: MetaRegionOwners,
443 regions: MetaRegionOwners,
444 r: Paddr,
445 ) -> bool {
446 &&& r == meta_to_frame(self.ptr.addr())
447 &&& regions.inv()
448 &&& regions.slots == old_regions.slots
449 &&& regions.slot_owners == old_regions.slot_owners
450 &&& regions.frame_obligations == old_regions.frame_obligations.remove(self.index())
451 }
452
453 #[verus_spec(r =>
455 with
456 Tracked(owner): Tracked<&UniqueFrameOwner<M>>,
457 Tracked(regions): Tracked<&mut MetaRegionOwners>,
458 requires
459 Self::into_raw_requires(self, *old(regions)),
460 self.wf(*owner),
461 owner.inv(),
462 old(regions).inv(),
463 old(regions).slot_owners[self.index()].ref_count() != REF_COUNT_UNUSED,
464 ensures
465 Self::into_raw_ensures(self, *old(regions), *final(regions), r),
466 final(regions).inv(),
467 )]
468 pub(crate) fn into_raw(self) -> Paddr {
469 #[verus_spec(with Tracked(owner), Tracked(&*regions))]
470 let paddr = self.start_paddr();
471
472 proof_decl! {
473 let ghost idx = self.index();
474 let tracked redeem_obl = DropObligation::tracked_mint(idx);
475 regions.tracked_redeem_frame_obligation(redeem_obl);
476 let tracked md_obl = DropObligation::tracked_mint(idx);
477 }
478 proof_with!(Tracked(md_obl));
479 let _ = ManuallyDrop::new(self);
480
481 paddr
482 }
483
484 #[verus_spec(res =>
491 with
492 Tracked(regions): Tracked<&mut MetaRegionOwners>,
493 Tracked(meta_own): Tracked<M::Owner>,
494 Tracked(repr_perm): Tracked<M::ReprPerm>,
495 requires
496 valid_frame_paddr(paddr),
497 old(regions).inv(),
498 old(regions).contains(frame_to_index(paddr)),
499 old(regions).slot_owner(paddr).ref_count() == REF_COUNT_UNIQUE,
500 ensures
501 res.0.ptr.addr() == frame_to_meta(paddr),
502 res.0.wf(res.1@),
503 res.1@.meta_own == meta_own,
504 res.1@.repr_perm == Some(repr_perm),
505 res.1@.slot_index == frame_to_index(paddr),
506 final(regions).inv(),
507 final(regions).slots == old(regions).slots,
508 final(regions).slot_owners == old(regions).slot_owners,
511 final(regions).frame_obligations == old(regions).frame_obligations.insert(
512 frame_to_index(paddr),
513 ),
514 )]
515 pub(crate) unsafe fn from_raw(paddr: Paddr) -> (Self, Tracked<UniqueFrameOwner<M>>) {
516 let vaddr = frame_to_meta(paddr);
517 let ptr = vstd::simple_pptr::PPtr::<MetaSlot>::from_addr(vaddr);
518
519 proof {
520 let tracked _ = regions.tracked_mint_frame_obligation(frame_to_index(paddr));
522 }
523
524 let tracked owner = UniqueFrameOwner {
525 meta_own,
526 repr_perm: Some(repr_perm),
527 slot_index: frame_to_index(paddr),
528 };
529
530 (Self { ptr, _marker: PhantomData }, Tracked(owner))
531 }
532
533 #[verus_spec(
534 with
535 Tracked(slot_perm): Tracked<&'a vstd::simple_pptr::PointsTo<MetaSlot>>,
536 requires
537 slot_perm.pptr() == self.ptr,
538 slot_perm.is_init(),
539 returns
540 slot_perm.value(),
541 )]
542 pub fn slot<'a>(&self) -> &'a MetaSlot {
543 self.ptr.borrow(Tracked(slot_perm))
546 }
547}
548
549impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + ?Sized> UniqueFrame<M> {
562 #[verus_spec(
563 with
564 Tracked(owner): Tracked<UniqueFrameOwner<M>>,
565 Tracked(regions): Tracked<&mut MetaRegionOwners>,
566 requires
567 old(self).wf_with_region(owner, *old(regions)),
568 old(regions).frame_obligations.count(owner.slot_index) > 0,
569 ensures
570 final(regions).inv(),
571 final(regions).slots == old(regions).slots,
572 forall|i: int| #![trigger final(regions).slot_owners[i]]
573 i != owner.slot_index ==> final(regions).slot_owners[i]
574 == old(regions).slot_owners[i],
575 final(regions).frame_obligations == old(regions).frame_obligations.remove(
576 owner.slot_index,
577 ),
578 )]
579 pub(crate) fn drop(&mut self) {
580 let ghost idx = owner.slot_index;
581
582 proof {
583 assert(regions.slot_owners.contains_key(idx));
589 assert(regions.slot_owners[idx].slot_vaddr == index_to_meta(idx));
590 assert(regions.slot_owners[idx].storage_perm().is_init());
591 assert(regions.slot_owners[idx].vtable_ptr_perm().is_init());
592
593 let tracked redeem_tok = vstd_extra::drop_tracking::DropObligation::tracked_mint(idx);
595 regions.tracked_redeem_frame_obligation(redeem_tok);
596 }
597
598 let tracked slot_own = regions.slot_owners.tracked_borrow_mut(idx);
599 let tracked perm_ref = regions.slots.tracked_borrow(idx);
600
601 #[verus_spec(with Tracked(perm_ref))]
604 let slot = self.slot();
605
606 unsafe {
607 #[verus_spec(with Tracked(&mut slot_own))]
608 slot.drop_last_in_place()
609 };
610
611 }
613}
614
615#[verus_verify]
616impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Frame<M> {
617 #[verus_spec(res =>
622 with
623 Tracked(owner): Tracked<UniqueFrameOwner<M>>,
624 Tracked(regions): Tracked<&mut MetaRegionOwners>,
625 requires
626 unique.wf(owner),
627 owner.inv(),
628 old(regions).inv(),
629 ensures
630 final(regions).slots == old(regions).slots,
631 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
632 )]
633 pub fn from_unique(unique: UniqueFrame<M>) -> Self {
634 let ghost idx = meta_to_index(unique.ptr.addr());
635 proof {
636 broadcast use group_page_meta;
637
638 regions.lemma_contains_valid_frame_paddr(meta_to_frame(unique.ptr.addr()));
639 assert(idx == owner.slot_index);
640 assert(regions.slots[idx].addr() == unique.ptr.addr());
641 assert(regions.slots[idx].pptr() == unique.ptr);
642 }
643 let tracked slot_own = regions.slot_owners.tracked_borrow_mut(idx);
644 let tracked slot_perm = regions.slots.tracked_borrow(idx);
645
646 #[verus_spec(with Tracked(&slot_perm))]
647 let slot = unique.slot();
648 slot.ref_count.store(Tracked(&mut slot_own.ref_count_perm), 1);
649
650 Frame { ptr: unique.ptr, _marker: PhantomData }
653 }
654}
655
656#[verus_verify]
657impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> UniqueFrame<M> {
658 #[verus_spec(res =>
662 with
663 Tracked(regions): Tracked<&mut MetaRegionOwners>,
664 requires
665 frame.inv(),
666 old(regions).inv(),
667 ensures
668 final(regions).slots == old(regions).slots,
669 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
670 )]
671 pub fn try_from_shared(frame: Frame<M>) -> Result<Self, Frame<M>> {
672 let ghost idx = meta_to_index(frame.ptr.addr());
673 proof {
674 broadcast use group_page_meta;
675
676 regions.lemma_contains_valid_frame_paddr(meta_to_frame(frame.ptr.addr()));
677 }
678 let tracked mut slot_own = regions.slot_owners.tracked_borrow_mut(idx);
679 let tracked slot_perm = regions.slots.tracked_borrow(idx);
680
681 #[verus_spec(with Tracked(&slot_perm))]
682 let slot = frame.slot();
683 let res = slot.ref_count.compare_exchange(
684 Tracked(&mut slot_own.ref_count_perm),
685 1,
686 REF_COUNT_UNIQUE,
687 );
688
689 match res {
690 Ok(_) => Ok(UniqueFrame { ptr: frame.ptr, _marker: PhantomData }),
692 Err(_) => Err(frame),
693 }
694 }
695}
696
697impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> From<UniqueFrame<M>> for Frame<M> {
698 #[verifier::external_body]
699 fn from(unique: UniqueFrame<M>) -> Self {
700 Frame::from_unique(unique)
701 }
702}
703
704impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> TryFrom<Frame<M>> for UniqueFrame<M> {
705 type Error = Frame<M>;
706
707 #[verifier::external_body]
711 fn try_from(frame: Frame<M>) -> Result<Self, Self::Error> {
712 UniqueFrame::try_from_shared(frame)
713 }
714}
715
716}