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},
13 meta_owners::{MetaSlotStorage, Metadata},
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 -> owner: Tracked<Option<UniqueFrameOwner<M>>>,
69 requires
70 old(regions).slot_owners.contains_key(frame_to_index(paddr)),
71 old(regions).slot_owners[frame_to_index(paddr)].usage is Unused,
72 old(regions).inv(),
73 ensures
74 !valid_frame_paddr(paddr) ==> res is Err,
75 res is Ok ==> {
76 &&& res.unwrap().wf(owner@->0)
77 &&& final(regions).frame_obligations == old(regions).frame_obligations.insert(frame_to_index(paddr))
78 },
79 res is Err ==> final(regions).frame_obligations == old(regions).frame_obligations,
80 final(regions).inv(),
81 )]
82 pub fn from_unused(paddr: Paddr, metadata: M) -> Result<Self, GetFrameError> {
83 #[verus_spec(with Tracked(regions))]
84 let from_unused = MetaSlot::get_from_unused(paddr, metadata, true);
85
86 if let Err(err) = from_unused {
87 proof_with!(|= Tracked(None));
88 Err(err)
89 } else {
90 let ptr = from_unused.unwrap();
91
92 proof_decl! {
93 let tracked owner = UniqueFrameOwner::<M>::tracked_from_unused_owner(regions, paddr);
94 let ghost idx = frame_to_index(paddr);
95 }
96 proof {
97 let tracked _ = regions.tracked_mint_frame_obligation(idx);
99 }
100
101 proof_with!(|= Tracked(Some(owner)));
102 Ok(Self { ptr, _marker: PhantomData })
103 }
104 }
105
106 pub open spec fn transmute_spec<M1: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf>(
107 self,
108 transmuted: UniqueFrame<M1>,
109 ) -> bool {
110 &&& transmuted.ptr.addr() == self.ptr.addr()
111 &&& transmuted._marker == PhantomData::<M1>
112 }
113
114 #[verifier::external_body]
115 #[verus_spec(res =>
116 ensures
117 Self::transmute_spec(self, res),
118 )]
119 pub fn transmute<M1: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf>(self) -> UniqueFrame<M1> {
120 unimplemented!()
121 }
122
123 #[verus_spec(res =>
135 with
136 Tracked(owner): Tracked<UniqueFrameOwner<M>>,
137 Tracked(regions): Tracked<&mut MetaRegionOwners>,
138 -> new_owner: Tracked<UniqueFrameOwner<M1>>,
139 requires
140 self.wf(owner),
141 owner.inv(),
142 owner.global_inv(*old(regions)),
143 old(regions).slot_owners[self.index()].inner_perms.in_list.value() == 0,
144 old(regions).inv(),
145 ensures
146 res.wf(new_owner@),
147 new_owner@.meta_perm_of(*final(regions)).value().metadata == metadata,
148 final(regions).inv(),
149 )]
150 pub fn repurpose<M1: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf>(
151 self,
152 metadata: M1,
153 ) -> UniqueFrame<M1> {
154 let ghost idx = self.index();
155 proof {
156 broadcast use group_page_meta;
157
158 assert(idx == owner.slot_index);
159 }
160 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
161 let tracked perm_ref = regions.slots.tracked_borrow(idx);
162
163 #[verus_spec(with Tracked(perm_ref))]
164 let slot = self.slot();
165
166 assert(slot_own.inv()) by {
167 assert(old(regions).slot_owners.contains_key(idx));
168 assert(old(regions).slot_owners[idx].inv());
169 }
170
171 unsafe {
173 #[verus_spec(with Tracked(&mut slot_own))]
174 slot.drop_meta_in_place()
175 };
176
177 let tracked mut inner_perms = slot_own.tracked_borrow_mut_inner_perms();
178
179 proof {
180 assert(inner_perms.storage.id() == perm_ref.value().storage.id());
181 }
182
183 let slot = self.ptr.borrow(Tracked(perm_ref));
184
185 unsafe {
186 #[verus_spec(with
187 Tracked(&mut inner_perms.storage),
188 Tracked(&mut inner_perms.vtable_ptr)
189 )]
190 slot.write_meta(metadata)
191 };
192
193 proof {
194 regions.slot_owners.tracked_insert(idx, slot_own);
195 }
196
197 let tracked mut new_owner = UniqueFrameOwner::<M1>::tracked_from_unused_owner(
198 regions,
199 meta_to_frame(self.ptr.addr()),
200 );
201
202 proof_with!(|= Tracked(new_owner));
204 self.transmute()
205 }
206
207 #[verus_spec(l =>
220 with
221 Tracked(owner): Tracked<&'a UniqueFrameOwner<M>>,
222 Tracked(regions): Tracked<&'a MetaRegionOwners>,
223 requires
224 owner.inv(),
225 self.wf(*owner),
226 owner.global_inv(*regions),
227 ensures
228 owner.meta_perm_of(*regions).mem_contents().value().metadata == l,
229 )]
230 pub fn meta<'a>(&self) -> &'a M {
231 let tracked outer = regions.slots.tracked_borrow(owner.slot_index);
232 #[verus_spec(with Tracked(outer))]
234 let slot = self.slot();
235
236 #[verus_spec(with Tracked(outer))]
237 let ptr = slot.as_meta_ptr();
238
239 let tracked tp = regions.borrow_typed_perm::<M>(owner.slot_index);
240 &ptr.borrow(Tracked(tp)).metadata
241 }
242
243 #[verus_spec(res =>
253 with
254 Tracked(owner): Tracked<&'a UniqueFrameOwner<M>>,
255 Tracked(regions): Tracked<&'a mut MetaRegionOwners>,
256 requires
257 owner.inv(),
258 old(self).wf(*owner),
259 owner.global_inv(*old(regions)),
260 ensures
261 *final(self) == *old(self),
262 final(regions).slots.dom() == old(regions).slots.dom(),
263 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
264 )]
265 pub fn meta_mut<'a>(&'a mut self) -> &'a mut M {
266 let ptr = {
267 let tracked outer = regions.slots.tracked_borrow(owner.slot_index);
268 #[verus_spec(with Tracked(outer))]
271 let slot = self.slot();
272
273 #[verus_spec(with Tracked(outer))]
274 slot.as_meta_ptr()
275 };
276
277 let tracked perm = regions.borrow_mut_typed_perm::<M>(owner.slot_index);
278 let metadata = ptr.borrow_mut(Tracked(perm));
279 &mut metadata.metadata
280 }
281}
282
283impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + ?Sized> UniqueFrame<M> {
284 pub const fn size(&self) -> usize
286 returns
287 PAGE_SIZE,
288 {
289 PAGE_SIZE
290 }
291
292 pub const fn level(&self) -> PagingLevel
300 returns
301 1u8,
302 {
303 1
304 }
305}
306
307#[verus_verify]
308impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + ?Sized> UniqueFrame<M> {
309 #[verus_spec(
311 with
312 Tracked(owner): Tracked<&UniqueFrameOwner<M>>,
313 Tracked(regions): Tracked<&MetaRegionOwners>,
314 requires
315 owner.inv(),
316 self.wf(*owner),
317 regions.inv(),
318 returns
319 meta_to_frame(self.ptr.addr()),
320 )]
321 pub fn start_paddr(&self) -> Paddr {
322 proof {
323 assert(regions.slot_owners.contains_key(owner.slot_index));
324 }
325 let tracked outer = regions.slots.tracked_borrow(owner.slot_index);
326 #[verus_spec(with Tracked(outer))]
327 let slot = self.slot();
328
329 #[verus_spec(with Tracked(outer))]
330 slot.frame_paddr()
331 }
332
333 #[verus_spec(
365 with
366 Tracked(owner): Tracked<UniqueFrameOwner<M>>,
367 Tracked(regions): Tracked<&mut MetaRegionOwners>,
368 requires
369 self.wf_with_region(owner, *old(regions)),
370 ensures
371 final(regions).inv(),
372 )]
373 pub fn reset_as_unused(self) {
374 let ghost idx = owner.slot_index;
375
376 proof {
377 assert(regions.slot_owners.contains_key(idx));
378 }
379
380 let tracked slot_own = regions.slot_owners.tracked_borrow_mut(idx);
381 let tracked perm_ref = regions.slots.tracked_borrow(idx);
382
383 #[verus_spec(with Tracked(perm_ref))]
384 let slot = self.slot();
385 slot.ref_count.store(Tracked(&mut slot_own.inner_perms.ref_count), 0);
386
387 unsafe {
390 #[verus_spec(with Tracked(slot_own))]
391 slot.drop_last_in_place()
392 };
393 }
394
395 pub open spec fn into_raw_requires(self, regions: MetaRegionOwners) -> bool {
396 &&& regions.slot_owners.contains_key(
397 self.index(),
398 )
399 &&& regions.frame_obligations.count(self.index()) > 0
402 &&& regions.inv()
403 }
404
405 pub open spec fn into_raw_ensures(
406 self,
407 old_regions: MetaRegionOwners,
408 regions: MetaRegionOwners,
409 r: Paddr,
410 ) -> bool {
411 &&& r == meta_to_frame(self.ptr.addr())
412 &&& regions.inv()
413 &&& regions.slots == old_regions.slots
414 &&& regions.slot_owners == old_regions.slot_owners
415 &&& regions.frame_obligations == old_regions.frame_obligations.remove(self.index())
416 }
417
418 #[verus_spec(r =>
420 with
421 Tracked(owner): Tracked<&UniqueFrameOwner<M>>,
422 Tracked(regions): Tracked<&mut MetaRegionOwners>,
423 requires
424 Self::into_raw_requires(self, *old(regions)),
425 self.wf(*owner),
426 owner.inv(),
427 old(regions).inv(),
428 old(regions).slot_owners[self.index()].inner_perms.ref_count.value() != REF_COUNT_UNUSED,
429 ensures
430 Self::into_raw_ensures(self, *old(regions), *final(regions), r),
431 final(regions).inv(),
432 )]
433 pub(crate) fn into_raw(self) -> Paddr {
434 #[verus_spec(with Tracked(owner), Tracked(&*regions))]
435 let paddr = self.start_paddr();
436
437 proof_decl! {
438 let ghost idx = self.index();
439 let tracked redeem_obl = DropObligation::tracked_mint(idx);
440 regions.tracked_redeem_frame_obligation(redeem_obl);
441 let tracked md_obl = DropObligation::tracked_mint(idx);
442 }
443 proof_with!(Tracked(md_obl));
444 let _ = ManuallyDrop::new(self);
445
446 paddr
447 }
448
449 #[verus_spec(res =>
456 with
457 Tracked(regions): Tracked<&mut MetaRegionOwners>,
458 Tracked(meta_own): Tracked<M::Owner>,
459 requires
460 valid_frame_paddr(paddr),
461 old(regions).inv(),
462 old(regions).slot_owners.contains_key(frame_to_index(paddr)),
463 old(regions).slot_owners[frame_to_index(paddr)].inner_perms.ref_count.value() == REF_COUNT_UNIQUE,
464 ensures
465 res.0.ptr.addr() == frame_to_meta(paddr),
466 res.0.wf(res.1@),
467 res.1@.meta_own == meta_own,
468 res.1@.slot_index == frame_to_index(paddr),
469 final(regions).inv(),
470 final(regions).slots == old(regions).slots,
471 final(regions).slot_owners == old(regions).slot_owners,
474 final(regions).frame_obligations == old(regions).frame_obligations.insert(
475 frame_to_index(paddr),
476 ),
477 )]
478 pub(crate) unsafe fn from_raw(paddr: Paddr) -> (Self, Tracked<UniqueFrameOwner<M>>) {
479 let vaddr = frame_to_meta(paddr);
480 let ptr = vstd::simple_pptr::PPtr::<MetaSlot>::from_addr(vaddr);
481
482 proof {
483 let tracked _ = regions.tracked_mint_frame_obligation(frame_to_index(paddr));
485 }
486
487 let tracked owner = UniqueFrameOwner { meta_own, slot_index: frame_to_index(paddr) };
488
489 (Self { ptr, _marker: PhantomData }, Tracked(owner))
490 }
491
492 #[verus_spec(
493 with
494 Tracked(slot_perm): Tracked<&'a vstd::simple_pptr::PointsTo<MetaSlot>>,
495 requires
496 slot_perm.pptr() == self.ptr,
497 slot_perm.is_init(),
498 returns
499 slot_perm.value(),
500 )]
501 pub fn slot<'a>(&self) -> &'a MetaSlot {
502 self.ptr.borrow(Tracked(slot_perm))
505 }
506}
507
508impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + ?Sized> UniqueFrame<M> {
521 #[verus_spec(
522 with
523 Tracked(owner): Tracked<UniqueFrameOwner<M>>,
524 Tracked(regions): Tracked<&mut MetaRegionOwners>,
525 requires
526 old(self).wf_with_region(owner, *old(regions)),
527 old(regions).frame_obligations.count(owner.slot_index) > 0,
528 ensures
529 final(regions).inv(),
530 final(regions).slots == old(regions).slots,
531 forall|i: int| #![trigger final(regions).slot_owners[i]]
532 i != owner.slot_index ==> final(regions).slot_owners[i]
533 == old(regions).slot_owners[i],
534 final(regions).frame_obligations == old(regions).frame_obligations.remove(
535 owner.slot_index,
536 ),
537 )]
538 pub(crate) fn drop(&mut self) {
539 let ghost idx = owner.slot_index;
540
541 proof {
542 assert(regions.slot_owners.contains_key(idx));
548 assert(regions.slot_owners[idx].slot_vaddr == index_to_meta(idx));
549 assert(regions.slot_owners[idx].inner_perms.storage.is_init());
550 assert(regions.slot_owners[idx].inner_perms.vtable_ptr.is_init());
551
552 let tracked redeem_tok = vstd_extra::drop_tracking::DropObligation::tracked_mint(idx);
554 regions.tracked_redeem_frame_obligation(redeem_tok);
555 }
556
557 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
558 let tracked perm_ref = regions.slots.tracked_borrow(idx);
559
560 #[verus_spec(with Tracked(perm_ref))]
563 let slot = self.slot();
564
565 unsafe {
566 #[verus_spec(with Tracked(&mut slot_own))]
567 slot.drop_last_in_place()
568 };
569
570 proof {
571 regions.slot_owners.tracked_insert(idx, slot_own);
572 }
573
574 }
576}
577
578#[verus_verify]
579impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Frame<M> {
580 #[verus_spec(res =>
585 with
586 Tracked(owner): Tracked<UniqueFrameOwner<M>>,
587 Tracked(regions): Tracked<&mut MetaRegionOwners>,
588 requires
589 unique.wf(owner),
590 owner.inv(),
591 old(regions).inv(),
592 ensures
593 final(regions).slots == old(regions).slots,
594 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
595 )]
596 pub fn from_unique(unique: UniqueFrame<M>) -> Self {
597 let ghost idx = frame_to_index(meta_to_frame(unique.ptr.addr()));
598 proof {
599 broadcast use group_page_meta;
600
601 regions.inv_implies_correct_addr(meta_to_frame(unique.ptr.addr()));
602 assert(idx == owner.slot_index);
603 assert(regions.slots[idx].addr() == unique.ptr.addr());
604 assert(regions.slots[idx].pptr() == unique.ptr);
605 }
606 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
607 let tracked slot_perm = regions.slots.tracked_borrow(idx);
608 let tracked mut inner_perms = slot_own.tracked_borrow_mut_inner_perms();
609
610 #[verus_spec(with Tracked(&slot_perm))]
611 let slot = unique.slot();
612 slot.ref_count.store(Tracked(&mut inner_perms.ref_count), 1);
613
614 proof {
615 regions.slot_owners.tracked_insert(idx, slot_own);
616 }
617
618 Frame { ptr: unique.ptr, _marker: PhantomData }
621 }
622}
623
624#[verus_verify]
625impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> UniqueFrame<M> {
626 #[verus_spec(res =>
630 with
631 Tracked(regions): Tracked<&mut MetaRegionOwners>,
632 requires
633 frame.inv(),
634 old(regions).inv(),
635 ensures
636 final(regions).slots == old(regions).slots,
637 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
638 )]
639 pub fn try_from_shared(frame: Frame<M>) -> Result<Self, Frame<M>> {
640 let ghost idx = frame_to_index(meta_to_frame(frame.ptr.addr()));
641 proof {
642 broadcast use group_page_meta;
643
644 regions.inv_implies_correct_addr(meta_to_frame(frame.ptr.addr()));
645 }
646 let tracked mut slot_own = regions.slot_owners.tracked_borrow_mut(idx);
647 let tracked slot_perm = regions.slots.tracked_borrow(idx);
648 let tracked inner_perms = slot_own.tracked_borrow_mut_inner_perms();
649
650 #[verus_spec(with Tracked(&slot_perm))]
651 let slot = frame.slot();
652 let res = slot.ref_count.compare_exchange(
653 Tracked(&mut inner_perms.ref_count),
654 1,
655 REF_COUNT_UNIQUE,
656 );
657
658 match res {
659 Ok(_) => Ok(UniqueFrame { ptr: frame.ptr, _marker: PhantomData }),
661 Err(_) => Err(frame),
662 }
663 }
664}
665
666impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> From<UniqueFrame<M>> for Frame<M> {
667 #[verifier::external_body]
668 fn from(unique: UniqueFrame<M>) -> Self {
669 Frame::from_unique(unique)
670 }
671}
672
673impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> TryFrom<Frame<M>> for UniqueFrame<M> {
674 type Error = Frame<M>;
675
676 #[verifier::external_body]
680 fn try_from(frame: Frame<M>) -> Result<Self, Self::Error> {
681 UniqueFrame::try_from_shared(frame)
682 }
683}
684
685}