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};
14
15use core::{marker::PhantomData, sync::atomic::Ordering};
16
17use super::meta::mapping::{
18 frame_to_index, frame_to_meta, max_meta_slots, meta_addr, meta_to_frame, META_SLOT_SIZE,
19};
20use super::meta::{REF_COUNT_UNIQUE, REF_COUNT_UNUSED};
21use crate::mm::frame::MetaPerm;
22use crate::mm::{Paddr, PagingLevel, MAX_NR_PAGES, MAX_PADDR, PAGE_SIZE};
23use crate::specs::arch::kspace::FRAME_METADATA_RANGE;
24use crate::specs::arch::paging_consts::PagingConsts;
25use crate::specs::mm::frame::meta_owners::MetaSlotStorage;
26use crate::specs::mm::frame::meta_owners::Metadata;
27use crate::specs::mm::frame::unique::UniqueFrameOwner;
28
29verus! {
30
31pub struct UniqueFrame<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> {
32 pub ptr: PPtr<MetaSlot>,
33 pub _marker: PhantomData<M>,
34}
35
36#[verus_verify]
37impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> UniqueFrame<M> {
38 #[verus_spec(res =>
51 with Tracked(regions): Tracked<&mut MetaRegionOwners>
52 -> owner: Tracked<Option<UniqueFrameOwner<M>>>
53 requires
54 old(regions).slots.contains_key(frame_to_index(paddr)),
55 old(regions).slot_owners.contains_key(frame_to_index(paddr)),
56 old(regions).slot_owners[frame_to_index(paddr)].usage is Unused,
57 old(regions).inv(),
58 ensures
59 !has_safe_slot(paddr) ==> res is Err,
60 res is Ok ==> res.unwrap().wf(owner@.unwrap()),
61 )]
62 pub fn from_unused(paddr: Paddr, metadata: M) -> Result<Self, GetFrameError> {
63 #[verus_spec(with Tracked(regions))]
64 let from_unused = MetaSlot::get_from_unused(paddr, metadata, true);
65
66 if let Err(err) = from_unused {
67 proof_with!(|= Tracked(None));
68 Err(err)
69 } else {
70 let (ptr, Tracked(perm)) = from_unused.unwrap();
71 proof_decl! {
72 let tracked owner = UniqueFrameOwner::<M>::from_unused_owner(regions, paddr, perm);
73 }
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 old(regions).slot_owners.contains_key(frame_to_index(meta_to_frame(self.ptr.addr()))),
117 old(regions).slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].inner_perms.ref_count.value() == REF_COUNT_UNIQUE,
118 old(regions).inv(),
119 ensures
120 res.wf(new_owner@),
121 new_owner@.meta_perm.value().metadata == metadata,
122 regions.inv(),
123 )]
124 pub fn repurpose<M1: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf>(
125 self,
126 metadata: M1,
127 ) -> UniqueFrame<M1> {
128 let tracked mut slot_own = regions.slot_owners.tracked_remove(
129 frame_to_index(meta_to_frame(self.ptr.addr())),
130 );
131
132 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
133 let slot = self.slot();
134
135 assert(slot_own.inv()) by {
136 admit();
137 }
138
139 #[verus_spec(with Tracked(&mut slot_own))]
141 slot.drop_meta_in_place();
142
143 let Tracked(meta_perm) = MetaSlot::cast_perm::<M1>(
144 self.ptr.addr(),
145 Tracked(owner.meta_perm.points_to),
146 Tracked(owner.meta_perm.inner_perms),
147 );
148
149 proof_decl! {
150 let tracked mut new_owner = UniqueFrameOwner::<M1>::from_unused_owner(
151 regions,
152 meta_to_frame(self.ptr.addr()),
153 meta_perm,
154 );
155 }
156
157 proof {
162 regions.slot_owners.tracked_insert(
163 frame_to_index(meta_to_frame(self.ptr.addr())),
164 slot_own,
165 );
166 admit();
167 }
168
169 proof_with!(|= Tracked(new_owner));
171 self.transmute()
172 }
173
174 #[verus_spec(
187 with Tracked(owner): Tracked<&'a UniqueFrameOwner<M>>
188 )]
189 pub fn meta<'a>(&self) -> (l: &'a M)
190 requires
191 owner.inv(),
192 self.wf(*owner),
193 ensures
194 owner.meta_perm.mem_contents().value().metadata == l,
195 {
196 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
198 let slot = self.slot();
199
200 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
201 let ptr = slot.as_meta_ptr();
202
203 &ptr.borrow(Tracked(&owner.meta_perm)).metadata
204 }
205
206 #[verus_spec(
216 with Tracked(owner): Tracked<&UniqueFrameOwner<M>>
217 )]
218 pub fn meta_mut(&mut self) -> (res: ReprPtr<MetaSlot, Metadata<M>>)
219 requires
220 owner.inv(),
221 old(self).wf(*owner),
222 ensures
223 res.addr() == self.ptr.addr(),
224 res.ptr.addr() == self.ptr.addr(),
225 *self == *old(self),
226 {
227 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
230 let slot = self.slot();
231
232 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
233 slot.as_meta_ptr()
234 }
235}
236
237impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + ?Sized> UniqueFrame<M> {
238 #[verus_spec(
240 with Tracked(owner): Tracked<&UniqueFrameOwner<M>>,
241 requires
242 owner.inv(),
243 self.wf(*owner),
244 returns
245 meta_to_frame(self.ptr.addr()),
246 )]
247 pub fn start_paddr(&self) -> Paddr {
248 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
249 let slot = self.slot();
250
251 #[verus_spec(with Tracked(&owner.meta_perm.points_to))]
252 slot.frame_paddr()
253 }
254
255 pub const fn level(&self) -> PagingLevel {
263 1
264 }
265
266 pub const fn size(&self) -> usize {
268 PAGE_SIZE
269 }
270
271 pub open spec fn into_raw_requires(self, regions: MetaRegionOwners) -> bool {
292 &&& regions.slot_owners.contains_key(frame_to_index(meta_to_frame(self.ptr.addr())))
293 &&& regions.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].raw_count == 0
294 &&& regions.inv()
295 }
296
297 pub open spec fn into_raw_ensures(
298 self,
299 old_regions: MetaRegionOwners,
300 regions: MetaRegionOwners,
301 r: Paddr,
302 ) -> bool {
303 &&& r == meta_to_frame(self.ptr.addr())
304 &&& regions.inv()
305 &&& regions.slots =~= old_regions.slots
306 &&& regions.slot_owners[frame_to_index(r)].raw_count == 1
307 &&& forall|i: usize|
308 #![trigger regions.slot_owners[i]]
309 i != frame_to_index(r) ==> regions.slot_owners[i] == old_regions.slot_owners[i]
310 }
311
312 #[verus_spec(r =>
334 with Tracked(owner): Tracked<&UniqueFrameOwner<M>>,
335 Tracked(regions): Tracked<&mut MetaRegionOwners>
336 requires
337 Self::into_raw_requires(self, *old(regions)),
338 self.wf(*owner),
339 owner.inv(),
340 old(regions).inv(),
341 old(regions).slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].raw_count == 0,
342 old(regions).slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].inner_perms.ref_count.value() != REF_COUNT_UNUSED,
343 ensures
344 Self::into_raw_ensures(self, *old(regions), *regions, r),
345 regions.inv(),
346 )]
347 pub(crate) fn into_raw(self) -> Paddr {
348 #[verus_spec(with Tracked(owner))]
349 let paddr = self.start_paddr();
350
351 assert(self.constructor_requires(*old(regions)));
352 let _ = ManuallyDrop::new(self, Tracked(regions));
353
354 paddr
355 }
356
357 #[verus_spec(res =>
364 with Tracked(regions): Tracked<&mut MetaRegionOwners>,
365 Tracked(meta_perm): Tracked<PointsTo<MetaSlot, Metadata<M>>>,
366 Tracked(meta_own): Tracked<M::Owner>
367 )]
368 pub(crate) fn from_raw(paddr: Paddr) -> (res: (Self, Tracked<UniqueFrameOwner<M>>))
369 requires
370 paddr < MAX_PADDR,
371 paddr % PAGE_SIZE == 0,
372 old(regions).inv(),
373 old(regions).slot_owners.contains_key(frame_to_index(paddr)),
374 old(regions).slot_owners[frame_to_index(paddr)].raw_count > 0,
375 !old(regions).slots.contains_key(frame_to_index(paddr)),
376 meta_perm.inner_perms.ref_count.value() == REF_COUNT_UNIQUE,
377 meta_perm.addr() == frame_to_meta(paddr),
378 ensures
379 res.0.ptr.addr() == frame_to_meta(paddr),
380 res.0.wf(res.1@),
381 res.1@.meta_own == meta_own,
382 res.1@.meta_perm == meta_perm,
383 regions.inv(),
384 regions.slot_owners[frame_to_index(paddr)].raw_count == old(
385 regions,
386 ).slot_owners[frame_to_index(paddr)].raw_count - 1,
387 {
388 let vaddr = frame_to_meta(paddr);
389 let ptr = vstd::simple_pptr::PPtr::<MetaSlot>::from_addr(vaddr);
390
391 proof {
392 let tracked mut slot_own = regions.slot_owners.tracked_remove(frame_to_index(paddr));
393 slot_own.raw_count = (slot_own.raw_count - 1) as usize;
394 regions.slot_owners.tracked_insert(frame_to_index(paddr), slot_own);
395 }
396
397 let tracked owner = UniqueFrameOwner {
398 meta_own,
399 meta_perm,
400 slot_index: frame_to_index(paddr),
401 };
402
403 (Self { ptr, _marker: PhantomData }, Tracked(owner))
404 }
405
406 #[verifier::external_body]
407 #[verus_spec(
408 with Tracked(slot_perm): Tracked<&'a vstd::simple_pptr::PointsTo<MetaSlot>>
409 )]
410 pub fn slot<'a>(&self) -> &'a MetaSlot
411 requires
412 slot_perm.pptr() == self.ptr,
413 slot_perm.is_init(),
414 returns
415 slot_perm.value(),
416 {
417 unimplemented!()
418 }
423}
424
425impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf + ?Sized> UniqueFrame<M> {
426 #[verus_spec(
427 with Tracked(owner): Tracked<UniqueFrameOwner<M>>,
428 Tracked(regions): Tracked<&mut MetaRegionOwners>,
429 requires
430 old(self).wf(owner),
431 owner.inv(),
432 old(regions).slot_owners.contains_key(owner.slot_index),
433 old(regions).slot_owners[owner.slot_index].raw_count == 0,
434 old(regions).slot_owners[owner.slot_index].self_addr == meta_addr(owner.slot_index),
435 !old(regions).slots.contains_key(owner.slot_index),
436 owner.meta_perm.inner_perms.ref_count.value() == REF_COUNT_UNIQUE,
437 owner.meta_perm.inner_perms.in_list.value() == 0,
438 owner.meta_perm.inner_perms.storage.is_init(),
439 owner.meta_perm.inner_perms.vtable_ptr.is_init(),
440 old(regions).inv(),
441 ensures
442 regions.slot_owners[owner.slot_index].raw_count == 0,
443 regions.inv(),
444 )]
445 fn drop(&mut self) {
446 let ghost idx = owner.slot_index;
447 let ghost inner_storage_id = owner.meta_perm.inner_perms.storage.id();
448 let ghost inner_ref_count_id = owner.meta_perm.inner_perms.ref_count.id();
449 let ghost inner_vtable_pptr = owner.meta_perm.inner_perms.vtable_ptr.pptr();
450 let ghost inner_in_list_id = owner.meta_perm.inner_perms.in_list.id();
451
452 let tracked mut slot_own = regions.slot_owners.tracked_remove(idx);
453 let tracked perm = owner.meta_perm.points_to;
454
455 proof {
456 assert(perm.value().storage.id() == inner_storage_id);
457 assert(perm.value().ref_count.id() == inner_ref_count_id);
458 slot_own.inner_perms = owner.meta_perm.inner_perms;
459 }
460 ;
461
462 #[verus_spec(with Tracked(&perm))]
465 let slot = self.slot();
466
467 #[verus_spec(with Tracked(&mut slot_own))]
468 slot.drop_last_in_place();
469
470 proof {
471 regions.slot_owners.tracked_insert(idx, slot_own);
472 regions.slots.tracked_insert(idx, perm);
473 }
474
475 }
477}
478
479}