ostd/mm/frame/
frame_ref.rs1use vstd::{
3 prelude::*,
4 simple_pptr::{PPtr, PointsTo},
5};
6use vstd_extra::{cast_ptr::Repr, prelude::*};
7
8use crate::specs::{
9 arch::valid_frame_paddr,
10 mm::frame::{
11 frame_specs::FrameRawPerms,
12 mapping::meta_to_index,
13 meta_owners::{FracMetadataPerm, MetaSlotStorage},
14 meta_region_owners::MetaRegionOwners,
15 },
16};
17
18use super::{
19 Frame,
20 meta::{AnyFrameMeta, MetaSlot},
21};
22use crate::mm::Paddr;
23use crate::mm::frame::meta::mapping::frame_to_meta;
24use core::{marker::PhantomData, mem::ManuallyDrop, ops::Deref, ptr::NonNull};
25
26verus! {
27
28pub struct FrameRef<'a, M: AnyFrameMeta + ?Sized + Repr<MetaSlotStorage>> {
31 pub inner: ManuallyDrop<Frame<M>>,
32 pub _marker: PhantomData<&'a Frame<M>>,
33}
34
35#[verus_verify]
36impl<M: AnyFrameMeta + Repr<MetaSlotStorage>> FrameRef<'_, M> {
37 #[verus_spec(r =>
43 with
44 Tracked(slot_perm): Tracked<&'static PointsTo<MetaSlot>>,
45 Tracked(metadata_perm): Tracked<&FracMetadataPerm>
46 requires
47 valid_frame_paddr(raw),
48 MetaSlot::perms_related(*slot_perm,metadata_perm.resource()),
49 slot_perm.pptr().addr() == frame_to_meta(raw),
50 slot_perm.is_init(),
51 ensures
52 r.inner@.ptr.addr() == frame_to_meta(raw),
53 r.inner@.ptr_inv(),
54 r.inner@.tracked_slot_perm@ == slot_perm,
55 r.inner@.tracked_metadata_perm@ is None,
56 MetaSlot::perms_related(r.inner@.slot_perm(), metadata_perm.resource()),
57 )]
58 pub(in crate::mm) unsafe fn borrow_paddr(raw: Paddr) -> Self {
59 proof_with!{ tracked_slot_perm: Tracked(slot_perm), tracked_metadata_perm: Tracked(None)}
60 let frame = Frame::<M> {
61 ptr: PPtr::<MetaSlot>::from_addr(frame_to_meta(raw)),
62 _marker: PhantomData,
63 };
64
65 let inner = ManuallyDrop::new(frame);
66
67 Self { inner, _marker: PhantomData }
68 }
69}
70
71impl<M: AnyFrameMeta + ?Sized + Repr<MetaSlotStorage>> Deref for FrameRef<'_, M> {
72 type Target = Frame<M>;
73
74 #[verus_spec(r => ensures *r == self.inner@)]
75 fn deref(&self) -> &Self::Target {
76 &self.inner
77 }
78}
79
80pub unsafe trait NonNullPtr: 'static + Sized {
95 type Target;
98
99 #[cfg(not(feature = "irc11"))]
100 type Permission: Inv;
101
102 #[cfg(feature = "irc11")]
103 type Permission: Inv + vstd::thread_view::Objective;
104
105 type Ref<'a>;
107
108 const ALIGN_BITS: u32;
110
111 fn into_raw(self) -> ((res_ptr, perm): (PPtr<Self::Target>, Tracked<Self::Permission>))
120 ensures
121 Self::ptr_perm_match(res_ptr, perm@),
122 self.rel_perm(perm@),
123 perm@.inv(),
124 res_ptr.addr() % (1usize << Self::ALIGN_BITS) == 0,
125 ;
126
127 unsafe fn from_raw(ptr: PPtr<Self::Target>, perm: Tracked<Self::Permission>) -> (ret: Self)
140 requires
141 Self::ptr_perm_match(ptr, perm@),
142 perm@.inv(),
143 ensures
144 ret.rel_perm(perm@),
145 ;
146
147 unsafe fn raw_as_ref<'a>(raw: PPtr<Self::Target>) -> Self::Ref<'a>;
154
155 fn ref_as_raw(ptr_ref: Self::Ref<'_>) -> PPtr<Self::Target>;
157
158 spec fn ptr_perm_match(ptr: PPtr<Self::Target>, perm: Self::Permission) -> bool;
161
162 spec fn rel_perm(self, perm: Self::Permission) -> bool;
164}
165
166unsafe impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + 'static> NonNullPtr for Frame<M> {
169 type Target = PhantomData<Self>;
170
171 type Permission = FrameRawPerms;
172
173 type Ref<'a> = FrameRef<'a, M>;
174
175 #[verifier::external_body]
176 const ALIGN_BITS: u32 = core::mem::align_of::<MetaSlot>().trailing_zeros();
177
178 fn into_raw(mut self) -> (PPtr<Self::Target>, Tracked<Self::Permission>) {
179 assume(self.inv());
180 proof_decl! {
181 let tracked perm = FrameRawPerms {
182 slot_perm: *self.tracked_slot_perm.borrow(),
183 metadata_perm: self.tracked_metadata_perm.tracked_take(),
184 };
185 }
186 let ptr = self.ptr;
187 let _ = ManuallyDrop::new(self);
188 assume(ptr.addr() % (1usize << Self::ALIGN_BITS) == 0);
189 (PPtr::<Self::Target>::from_addr(ptr.addr()), Tracked(perm))
190 }
191
192 unsafe fn from_raw(raw: PPtr<Self::Target>, Tracked(perm): Tracked<Self::Permission>) -> Self {
193 Self {
194 ptr: PPtr::<MetaSlot>::from_addr(raw.addr()),
195 _marker: PhantomData,
196 #[cfg(verus_keep_ghost_body)]
197 tracked_slot_perm: Tracked(perm.slot_perm),
198 #[cfg(verus_keep_ghost_body)]
199 tracked_metadata_perm: Tracked(Some(perm.metadata_perm)),
200 }
201 }
202
203 #[verifier::external_body]
204 unsafe fn raw_as_ref<'a>(raw: PPtr<Self::Target>) -> Self::Ref<'a> {
205 let frame = Frame::<M> {
206 ptr: PPtr::<MetaSlot>::from_addr(raw.addr()),
207 _marker: PhantomData,
208 #[cfg(verus_keep_ghost_body)]
209 tracked_slot_perm: Tracked::assume_new(),
210 #[cfg(verus_keep_ghost_body)]
211 tracked_metadata_perm: Tracked(None),
212 };
213 let dropped = ManuallyDrop::<Frame<M>>::new(frame);
214 Self::Ref { inner: dropped, _marker: PhantomData }
215 }
216
217 fn ref_as_raw(ptr_ref: Self::Ref<'_>) -> PPtr<Self::Target> {
218 PPtr::from_addr(ptr_ref.inner.ptr.addr())
219 }
220
221 open spec fn ptr_perm_match(ptr: PPtr<Self::Target>, perm: Self::Permission) -> bool {
222 ptr.addr() == perm.slot_perm.addr()
223 }
224
225 open spec fn rel_perm(self, perm: Self::Permission) -> bool {
226 &&& perm.slot_perm == self.slot_perm()
227 &&& perm.metadata_perm == self.frac_metadata_perm()
228 }
229}
230
231}