ostd/mm/frame/
frame_ref.rs1use core::{marker::PhantomData, ops::Deref, ptr::NonNull};
3
4use vstd::prelude::*;
5
6use vstd_extra::drop_tracking::*;
7use vstd_extra::ownership::*;
8
9use crate::mm::frame::meta::mapping::{frame_to_index, frame_to_meta, meta_to_frame};
10use crate::mm::frame::meta::{has_safe_slot, AnyFrameMeta, MetaSlot};
11use crate::mm::frame::MetaPerm;
12use crate::mm::{Paddr, PagingLevel, Vaddr};
13use crate::specs::arch::mm::{MAX_PADDR, PAGE_SIZE};
14use crate::specs::mm::frame::frame_specs::BorrowDebt;
15use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
16
17use super::Frame;
18
19use vstd::simple_pptr::PPtr;
20
21verus! {
22
23pub struct FrameRef<'a, M: AnyFrameMeta> {
25 pub inner: ManuallyDrop<Frame<M>>,
26 pub _marker: PhantomData<&'a Frame<M>>,
27}
28
29impl<M: AnyFrameMeta> Deref for FrameRef<'_, M> {
30 type Target = Frame<M>;
31
32 #[verus_spec(ensures returns &self.inner.0)]
33 fn deref(&self) -> &Self::Target {
34 &self.inner
35 }
36}
37
38#[verus_verify]
39impl<M: AnyFrameMeta> FrameRef<'_, M> {
40 #[verus_spec(r =>
54 with
55 Tracked(regions): Tracked<&mut MetaRegionOwners>,
56 Tracked(perm): Tracked<&MetaPerm<M>>
57 requires
58 Frame::<M>::from_raw_requires_safety(*old(regions), raw),
59 old(regions).slot_owners[frame_to_index(raw)].raw_count <= 1,
60 old(regions).slot_owners[frame_to_index(raw)].inner_perms.ref_count.value()
61 != crate::mm::frame::meta::REF_COUNT_UNUSED,
62 perm.points_to.is_init(),
63 perm.points_to.addr() == frame_to_meta(raw),
64 perm.points_to.value().wf(old(regions).slot_owners[frame_to_index(raw)]),
65 ensures
66 final(regions).inv(),
67 r.inner.0.ptr.addr() == frame_to_meta(raw),
68 final(regions).slot_owners[frame_to_index(raw)].raw_count == 1,
70 final(regions).slot_owners[frame_to_index(raw)].inner_perms
72 == old(regions).slot_owners[frame_to_index(raw)].inner_perms,
73 final(regions).slot_owners[frame_to_index(raw)].self_addr
74 == old(regions).slot_owners[frame_to_index(raw)].self_addr,
75 final(regions).slot_owners[frame_to_index(raw)].usage
76 == old(regions).slot_owners[frame_to_index(raw)].usage,
77 final(regions).slot_owners[frame_to_index(raw)].paths_in_pt
78 == old(regions).slot_owners[frame_to_index(raw)].paths_in_pt,
79 forall |i: usize|
81 #![trigger final(regions).slot_owners[i]]
82 i != frame_to_index(raw) ==> final(regions).slot_owners[i]
83 == old(regions).slot_owners[i],
84 final(regions).slot_owners.dom() =~= old(regions).slot_owners.dom(),
85 final(regions).slots == old(regions).slots.insert(frame_to_index(raw), perm.points_to),
87 )]
88 pub(in crate::mm) fn borrow_paddr(raw: Paddr) -> Self {
89 proof {
90 broadcast use crate::mm::frame::meta::mapping::group_page_meta;
91
92 old(regions).inv_implies_correct_addr(raw);
93 }
94
95 proof_decl! {
96 let tracked debt: BorrowDebt;
97 }
98
99 #[verus_spec(with Tracked(regions), Tracked(perm) => Tracked(debt))]
100 let frame = Frame::from_raw(raw);
101
102 proof {
103 Frame::lemma_from_raw_manuallydrop_general(raw, frame, *old(regions), *regions, debt);
104 }
105
106 Self { inner: ManuallyDrop::new(frame, Tracked(regions)), _marker: PhantomData }
107 }
108}
109
110pub unsafe trait NonNullPtr: 'static + Sized + TrackDrop<State = MetaRegionOwners> {
126 type Target;
129
130 type Ref<'a>;
132
133 fn ALIGN_BITS() -> u32;
135
136 fn into_raw(self, Tracked(regions): Tracked<&mut MetaRegionOwners>) -> PPtr<Self::Target>
145 requires
146 self.constructor_requires(*old(regions)),
147 ;
148
149 unsafe fn from_raw(ptr: PPtr<Self::Target>) -> Self;
162
163 unsafe fn raw_as_ref<'a>(
170 raw: PPtr<Self::Target>,
171 Tracked(regions): Tracked<&mut MetaRegionOwners>,
172 ) -> Self::Ref<'a>
173 requires
174 old(regions).inv(),
175 old(regions).slot_owners.contains_key(frame_to_index(meta_to_frame(raw.addr()))),
176 old(regions).slot_owners[frame_to_index(meta_to_frame(raw.addr()))].raw_count
177 == 0,
178 ;
181
182 fn ref_as_raw(ptr_ref: Self::Ref<'_>) -> PPtr<Self::Target>;
184}
185
186pub assume_specification[ usize::trailing_zeros ](_0: usize) -> u32
187;
188
189unsafe impl<M: AnyFrameMeta + ?Sized + 'static> NonNullPtr for Frame<M> {
192 type Target = PhantomData<Self>;
193
194 type Ref<'a> = FrameRef<'a, M>;
195
196 fn ALIGN_BITS() -> u32 {
197 core::mem::align_of::<MetaSlot>().trailing_zeros()
198 }
199
200 fn into_raw(self, Tracked(regions): Tracked<&mut MetaRegionOwners>) -> PPtr<Self::Target> {
201 let ptr = self.ptr;
202 assert(self.constructor_requires(*old(regions)));
203 let _ = ManuallyDrop::new(self, Tracked(regions));
204 PPtr::<Self::Target>::from_addr(ptr.addr())
205 }
206
207 unsafe fn from_raw(raw: PPtr<Self::Target>) -> Self {
208 Self { ptr: PPtr::<MetaSlot>::from_addr(raw.addr()), _marker: PhantomData }
209 }
210
211 unsafe fn raw_as_ref<'a>(
212 raw: PPtr<Self::Target>,
213 Tracked(regions): Tracked<&mut MetaRegionOwners>,
214 ) -> Self::Ref<'a> {
215 let dropped = ManuallyDrop::<Frame<M>>::new(
216 Frame { ptr: PPtr::<MetaSlot>::from_addr(raw.addr()), _marker: PhantomData },
217 Tracked(regions),
218 );
219 Self::Ref { inner: dropped, _marker: PhantomData }
220 }
221
222 fn ref_as_raw(ptr_ref: Self::Ref<'_>) -> PPtr<Self::Target> {
223 PPtr::from_addr(ptr_ref.inner.ptr.addr())
224 }
225}
226
227}