1use vstd::atomic::PermissionU64;
4use vstd::prelude::*;
5use vstd::simple_pptr::{self, PPtr};
6
7use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
8
9use vstd_extra::cast_ptr::*;
10use vstd_extra::drop_tracking::*;
11use vstd_extra::ownership::*;
12
13use super::meta::{has_safe_slot, AnyFrameMeta, GetFrameError, MetaSlot};
14use super::Frame;
15
16use core::{marker::PhantomData, sync::atomic::Ordering};
17
18use super::meta::mapping::{
19 frame_to_index, frame_to_meta, max_meta_slots, meta_addr, meta_to_frame, META_SLOT_SIZE,
20};
21use super::meta::{REF_COUNT_UNIQUE, REF_COUNT_UNUSED};
22use crate::mm::frame::MetaPerm;
23use crate::mm::{Paddr, PagingLevel, MAX_NR_PAGES, MAX_PADDR, PAGE_SIZE};
24use crate::specs::arch::kspace::FRAME_METADATA_RANGE;
25use crate::specs::arch::paging_consts::PagingConsts;
26use crate::specs::mm::frame::meta_owners::MetaSlotStorage;
27use crate::specs::mm::frame::meta_owners::Metadata;
28use crate::specs::mm::frame::unique::UniqueFrameOwner;
29
30verus! {
31
32pub struct UniqueFrame<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> {
33 pub ptr: PPtr<MetaSlot>,
34 pub _marker: PhantomData<M>,
35}
36
37#[verus_verify]
38impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> UniqueFrame<M> {
39 #[verus_spec(res =>
52 with Tracked(regions): Tracked<&mut MetaRegionOwners>
53 -> owner: Tracked<Option<UniqueFrameOwner<M>>>
54 requires
55 old(regions).slots.contains_key(frame_to_index(paddr)),
56 old(regions).slot_owners.contains_key(frame_to_index(paddr)),
57 old(regions).slot_owners[frame_to_index(paddr)].usage is Unused,
58 old(regions).inv(),
59 ensures
60 !has_safe_slot(paddr) ==> res is Err,
61 res is Ok ==> res.unwrap().wf(owner@.unwrap()),
62 )]
63 pub fn from_unused(paddr: Paddr, metadata: M) -> Result<Self, GetFrameError> {
64 #[verus_spec(with Tracked(regions))]
65 let from_unused = MetaSlot::get_from_unused(paddr, metadata, true);
66
67 if let Err(err) = from_unused {
68 proof_with!(|= Tracked(None));
69 Err(err)
70 } else {
71 let (ptr, Tracked(perm)) = from_unused.unwrap();
72 proof_decl! {
73 let tracked owner = UniqueFrameOwner::<M>::from_unused_owner(regions, paddr, perm);
74 }
75 proof_with!(|= Tracked(Some(owner)));
76 Ok(Self { ptr, _marker: PhantomData })
77 }
78 }
79
80 pub open spec fn transmute_spec<M1: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf>(
81 self,
82 transmuted: UniqueFrame<M1>,
83 ) -> bool {
84 &&& transmuted.ptr.addr() == self.ptr.addr()
85 &&& transmuted._marker == PhantomData::<M1>
86 }
87
88 #[verifier::external_body]
89 pub fn transmute<M1: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf>(self) -> (res: UniqueFrame<
90 M1,
91 >)
92 ensures
93 Self::transmute_spec(self, res),
94 {
95 unimplemented!()
96 }
97
98 #[verus_spec(res =>
110 with Tracked(owner): Tracked<UniqueFrameOwner<M>>,
111 Tracked(regions): Tracked<&mut MetaRegionOwners>
112 -> new_owner: Tracked<UniqueFrameOwner<M1>>
113 requires
114 self.wf(owner),
115 owner.inv(),
116 owner.global_inv(*old(regions)),
117 old(regions).slot_owners.contains_key(frame_to_index(meta_to_frame(self.ptr.addr()))),
118 old(regions).slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].inner_perms.ref_count.value() == REF_COUNT_UNIQUE,
119 old(regions).inv(),
120 ensures
121 res.wf(new_owner@),
122 new_owner@.meta_perm.value().metadata == metadata,
123 final(regions).inv(),
124 )]
125 pub fn repurpose<M1: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf>(
126 self,
127 metadata: M1,
128 ) -> UniqueFrame<M1> {
129 let tracked mut slot_own = regions.slot_owners.tracked_remove(
130 frame_to_index(meta_to_frame(self.ptr.addr())),
131 );
132 let tracked mut slot_perm = owner.meta_perm.points_to;
133
134 #[verus_spec(with Tracked(&slot_perm))]
135 let slot = self.slot();
136
137 assert(slot_own.inv()) by {
138 let idx = frame_to_index(meta_to_frame(self.ptr.addr()));
139 assert(old(regions).slot_owners.contains_key(idx));
140 assert(old(regions).slot_owners[idx].inv());
141 }
142
143 #[verus_spec(with Tracked(&mut slot_own))]
145 slot.drop_meta_in_place();
146
147 let tracked mut inner_perms = slot_own.take_inner_perms();
150
151 proof {
156 let idx = frame_to_index(meta_to_frame(self.ptr.addr()));
157 assert(inner_perms.storage.id() == slot_perm.value().storage.id());
158 }
159
160 let slot = self.ptr.borrow(Tracked(&slot_perm));
162
163 #[verus_spec(with
164 Tracked(&mut inner_perms.storage),
165 Tracked(&mut inner_perms.vtable_ptr)
166 )]
167 slot.write_meta(metadata);
168
169 proof { slot_own.sync_inner(&inner_perms); }
171 let tracked meta_perm = MetaSlot::cast_perm::<M1>(slot_perm, inner_perms);
172
173 let tracked mut new_owner = UniqueFrameOwner::<M1>::from_unused_owner(
174 regions,
175 meta_to_frame(self.ptr.addr()),
176 meta_perm,
177 );
178
179 proof_with!(|= Tracked(new_owner));
181 self.transmute()
182 }
183
184 #[verus_spec(
197 with Tracked(owner): Tracked<&'a UniqueFrameOwner<M>>
198 )]
199 pub fn meta<'a>(&self) -> (l: &'a M)
200 requires
201 owner.inv(),
202 self.wf(*owner),
203 ensures
204 owner.meta_perm.mem_contents().value().metadata == l,
205 {
206 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
208 let slot = self.slot();
209
210 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
211 let ptr = slot.as_meta_ptr();
212
213 &ptr.borrow(Tracked(&owner.meta_perm)).metadata
214 }
215
216 #[verus_spec(
226 with Tracked(owner): Tracked<&UniqueFrameOwner<M>>
227 )]
228 pub fn meta_mut(&mut self) -> (res: ReprPtr<MetaSlot, Metadata<M>>)
229 requires
230 owner.inv(),
231 old(self).wf(*owner),
232 ensures
233 res.addr() == final(self).ptr.addr(),
234 res.ptr.addr() == final(self).ptr.addr(),
235 *final(self) == *old(self),
236 {
237 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
240 let slot = self.slot();
241
242 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
243 slot.as_meta_ptr()
244 }
245}
246
247impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + ?Sized> UniqueFrame<M> {
248 #[verus_spec(
250 with Tracked(owner): Tracked<&UniqueFrameOwner<M>>,
251 requires
252 owner.inv(),
253 self.wf(*owner),
254 returns
255 meta_to_frame(self.ptr.addr()),
256 )]
257 pub fn start_paddr(&self) -> Paddr {
258 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
259 let slot = self.slot();
260
261 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
262 slot.frame_paddr()
263 }
264
265 pub const fn level(&self) -> PagingLevel {
273 1
274 }
275
276 pub const fn size(&self) -> usize {
278 PAGE_SIZE
279 }
280
281 pub open spec fn into_raw_requires(self, regions: MetaRegionOwners) -> bool {
302 &&& regions.slot_owners.contains_key(frame_to_index(meta_to_frame(self.ptr.addr())))
303 &&& regions.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].raw_count == 0
304 &&& regions.inv()
305 }
306
307 pub open spec fn into_raw_ensures(
308 self,
309 old_regions: MetaRegionOwners,
310 regions: MetaRegionOwners,
311 r: Paddr,
312 ) -> bool {
313 &&& r == meta_to_frame(self.ptr.addr())
314 &&& regions.inv()
315 &&& regions.slots =~= old_regions.slots
316 &&& regions.slot_owners[frame_to_index(r)].raw_count == 1
317 &&& forall|i: usize|
318 #![trigger regions.slot_owners[i]]
319 i != frame_to_index(r) ==> regions.slot_owners[i] == old_regions.slot_owners[i]
320 }
321
322 #[verus_spec(
334 with Tracked(owner): Tracked<UniqueFrameOwner<M>>,
335 Tracked(regions): Tracked<&mut MetaRegionOwners>
336 requires
337 self.wf(owner),
338 owner.inv(),
339 old(regions).inv(),
340 old(regions).slot_owners.contains_key(owner.slot_index),
341 old(regions).slot_owners[owner.slot_index].raw_count == 0,
342 old(regions).slot_owners[owner.slot_index].self_addr == meta_addr(owner.slot_index),
343 !old(regions).slots.contains_key(owner.slot_index),
344 owner.meta_perm.inner_perms.ref_count.value() == REF_COUNT_UNIQUE,
345 owner.meta_perm.inner_perms.in_list.value() == 0,
346 owner.meta_perm.inner_perms.storage.is_init(),
347 owner.meta_perm.inner_perms.vtable_ptr.is_init(),
348 ensures
349 final(regions).slot_owners[owner.slot_index].raw_count == 0,
350 final(regions).inv(),
351 )]
352 pub fn reset_as_unused(self) {
353 let ghost idx = owner.slot_index;
354 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
355 let tracked perm = owner.meta_perm.points_to;
356
357 proof {
358 slot_own.inner_perms = owner.meta_perm.inner_perms;
359 }
360
361 #[verus_spec(with Tracked(&perm))]
362 let slot = self.slot();
363 slot.ref_count.store(Tracked(&mut slot_own.inner_perms.ref_count), 0);
364
365 #[verus_spec(with Tracked(&mut slot_own))]
368 slot.drop_last_in_place();
369
370 proof {
371 regions.slot_owners.tracked_insert(idx, slot_own);
372 regions.slots.tracked_insert(idx, perm);
373 }
374 }
375 #[verus_spec(r =>
377 with Tracked(owner): Tracked<&UniqueFrameOwner<M>>,
378 Tracked(regions): Tracked<&mut MetaRegionOwners>
379 requires
380 Self::into_raw_requires(self, *old(regions)),
381 self.wf(*owner),
382 owner.inv(),
383 old(regions).inv(),
384 old(regions).slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].raw_count == 0,
385 old(regions).slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].inner_perms.ref_count.value() != REF_COUNT_UNUSED,
386 ensures
387 Self::into_raw_ensures(self, *old(regions), *final(regions), r),
388 final(regions).inv(),
389 )]
390 pub(crate) fn into_raw(self) -> Paddr {
391 #[verus_spec(with Tracked(owner))]
392 let paddr = self.start_paddr();
393
394 assert(self.constructor_requires(*old(regions)));
395 let _ = ManuallyDrop::new(self, Tracked(regions));
396
397 paddr
398 }
399
400 #[verus_spec(res =>
407 with Tracked(regions): Tracked<&mut MetaRegionOwners>,
408 Tracked(meta_perm): Tracked<PointsTo<MetaSlot, Metadata<M>>>,
409 Tracked(meta_own): Tracked<M::Owner>
410 )]
411 pub(crate) fn from_raw(paddr: Paddr) -> (res: (Self, Tracked<UniqueFrameOwner<M>>))
412 requires
413 paddr < MAX_PADDR,
414 paddr % PAGE_SIZE == 0,
415 old(regions).inv(),
416 old(regions).slot_owners.contains_key(frame_to_index(paddr)),
417 old(regions).slot_owners[frame_to_index(paddr)].raw_count > 0,
418 !old(regions).slots.contains_key(frame_to_index(paddr)),
419 meta_perm.inner_perms.ref_count.value() == REF_COUNT_UNIQUE,
420 meta_perm.addr() == frame_to_meta(paddr),
421 ensures
422 res.0.ptr.addr() == frame_to_meta(paddr),
423 res.0.wf(res.1@),
424 res.1@.meta_own == meta_own,
425 res.1@.meta_perm == meta_perm,
426 final(regions).inv(),
427 final(regions).slot_owners[frame_to_index(paddr)].raw_count == old(
428 regions,
429 ).slot_owners[frame_to_index(paddr)].raw_count - 1,
430 {
431 let vaddr = frame_to_meta(paddr);
432 let ptr = vstd::simple_pptr::PPtr::<MetaSlot>::from_addr(vaddr);
433
434 proof {
435 let tracked mut slot_own = regions.slot_owners.tracked_remove(frame_to_index(paddr));
436 slot_own.raw_count = (slot_own.raw_count - 1) as usize;
437 regions.slot_owners.tracked_insert(frame_to_index(paddr), slot_own);
438 }
439
440 let tracked owner = UniqueFrameOwner {
441 meta_own,
442 meta_perm,
443 slot_index: frame_to_index(paddr),
444 };
445
446 (Self { ptr, _marker: PhantomData }, Tracked(owner))
447 }
448
449 #[verifier::external_body]
450 #[verus_spec(
451 with Tracked(slot_perm): Tracked<&'a vstd::simple_pptr::PointsTo<MetaSlot>>
452 )]
453 pub fn slot<'a>(&self) -> &'a MetaSlot
454 requires
455 slot_perm.pptr() == self.ptr,
456 slot_perm.is_init(),
457 returns
458 slot_perm.value(),
459 {
460 unimplemented!()
461 }
466
467}
468
469impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + ?Sized> UniqueFrame<M> {
470 #[verus_spec(
471 with Tracked(owner): Tracked<UniqueFrameOwner<M>>,
472 Tracked(regions): Tracked<&mut MetaRegionOwners>,
473 requires
474 old(self).wf(owner),
475 owner.inv(),
476 old(regions).slot_owners.contains_key(owner.slot_index),
477 old(regions).slot_owners[owner.slot_index].raw_count == 0,
478 old(regions).slot_owners[owner.slot_index].self_addr == meta_addr(owner.slot_index),
479 !old(regions).slots.contains_key(owner.slot_index),
480 owner.meta_perm.inner_perms.ref_count.value() == REF_COUNT_UNIQUE,
481 owner.meta_perm.inner_perms.in_list.value() == 0,
482 owner.meta_perm.inner_perms.storage.is_init(),
483 owner.meta_perm.inner_perms.vtable_ptr.is_init(),
484 old(regions).inv(),
485 ensures
486 final(regions).slot_owners[owner.slot_index].raw_count == 0,
487 final(regions).inv(),
488 )]
489 pub(crate) fn drop(&mut self) {
490 let ghost idx = owner.slot_index;
491 let ghost inner_storage_id = owner.meta_perm.inner_perms.storage.id();
492 let ghost inner_ref_count_id = owner.meta_perm.inner_perms.ref_count.id();
493 let ghost inner_vtable_pptr = owner.meta_perm.inner_perms.vtable_ptr.pptr();
494 let ghost inner_in_list_id = owner.meta_perm.inner_perms.in_list.id();
495
496 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
497 let tracked perm = owner.meta_perm.points_to;
498
499 proof {
500 assert(perm.value().storage.id() == inner_storage_id);
501 assert(perm.value().ref_count.id() == inner_ref_count_id);
502 slot_own.inner_perms = owner.meta_perm.inner_perms;
503 }
504 ;
505
506 #[verus_spec(with Tracked(&perm))]
509 let slot = self.slot();
510
511 #[verus_spec(with Tracked(&mut slot_own))]
512 slot.drop_last_in_place();
513
514 proof {
515 regions.slot_owners.tracked_insert(idx, slot_own);
516 regions.slots.tracked_insert(idx, perm);
517 }
518
519 }
521}
522
523impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Frame<M> {
524 #[verus_spec(
529 with Tracked(owner): Tracked<UniqueFrameOwner<M>>,
530 Tracked(regions): Tracked<&mut MetaRegionOwners>
531 )]
532 pub fn from_unique(unique: UniqueFrame<M>) -> (res: Self)
533 requires
534 unique.wf(owner),
535 owner.inv(),
536 old(regions).inv(),
537 old(regions).slots.contains_key(owner.slot_index),
538 old(regions).slot_owners.contains_key(owner.slot_index),
539 old(regions).slots[owner.slot_index].pptr() == unique.ptr,
540 old(regions).slot_owners[owner.slot_index].inner_perms.ref_count.id()
541 == old(regions).slots[owner.slot_index].value().ref_count.id(),
542 ensures
543 final(regions).slots == old(regions).slots,
544 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
545 {
546 let ghost idx_g = owner.slot_index;
547 let idx = frame_to_index(meta_to_frame(unique.ptr.addr()));
548 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
549 let tracked slot_perm = regions.slots.tracked_borrow(idx);
550 let tracked mut inner_perms = slot_own.take_inner_perms();
551
552 #[verus_spec(with Tracked(&slot_perm))]
553 let slot = unique.slot();
554 slot.ref_count.store(Tracked(&mut inner_perms.ref_count), 1);
555
556 proof {
557 slot_own.sync_inner(&inner_perms);
558 regions.slot_owners.tracked_insert(idx, slot_own);
559 }
560
561 Frame { ptr: unique.ptr, _marker: PhantomData }
564 }
565}
566
567impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> UniqueFrame<M> {
568 #[verus_spec(
572 with Tracked(regions): Tracked<&mut MetaRegionOwners>
573 )]
574 pub fn try_from_shared(frame: Frame<M>) -> (res: Result<Self, Frame<M>>)
575 requires
576 frame.inv(),
577 old(regions).inv(),
578 old(regions).slots.contains_key(
579 frame_to_index(meta_to_frame(frame.ptr.addr()))),
580 old(regions).slot_owners.contains_key(
581 frame_to_index(meta_to_frame(frame.ptr.addr()))),
582 old(regions).slots[frame_to_index(meta_to_frame(frame.ptr.addr()))].pptr()
583 == frame.ptr,
584 old(regions).slot_owners[frame_to_index(meta_to_frame(frame.ptr.addr()))]
585 .inner_perms.ref_count.id()
586 == old(regions).slots[frame_to_index(meta_to_frame(frame.ptr.addr()))]
587 .value().ref_count.id(),
588 ensures
589 final(regions).slots == old(regions).slots,
590 final(regions).slot_owners.dom() == old(regions).slot_owners.dom(),
591 {
592 let idx = frame_to_index(meta_to_frame(frame.ptr.addr()));
593 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
594 let tracked slot_perm = regions.slots.tracked_borrow(idx);
595 let tracked mut inner_perms = slot_own.take_inner_perms();
596
597 #[verus_spec(with Tracked(&slot_perm))]
598 let slot = frame.slot();
599 let res = slot.ref_count.compare_exchange(
600 Tracked(&mut inner_perms.ref_count),
601 1,
602 REF_COUNT_UNIQUE,
603 );
604
605 proof {
606 slot_own.sync_inner(&inner_perms);
607 regions.slot_owners.tracked_insert(idx, slot_own);
608 }
609
610 match res {
611 Ok(_) => Ok(UniqueFrame { ptr: frame.ptr, _marker: PhantomData }),
613 Err(_) => Err(frame),
614 }
615 }
616}
617
618impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> From<UniqueFrame<M>> for Frame<M> {
619 #[verifier::external_body]
620 fn from(unique: UniqueFrame<M>) -> Self {
621 Frame::from_unique(unique)
622 }
623}
624
625impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> TryFrom<Frame<M>> for UniqueFrame<M> {
626 type Error = Frame<M>;
627
628 #[verifier::external_body]
632 fn try_from(frame: Frame<M>) -> Result<Self, Self::Error> {
633 UniqueFrame::try_from_shared(frame)
634 }
635}
636}