ostd/specs/mm/frame/
unique.rs1use vstd::prelude::*;
2
3use vstd_extra::{cast_ptr::*, drop_tracking::*, ownership::*};
4
5use crate::specs::{
6 arch::MAX_NR_PAGES,
7 mm::{
8 Paddr,
9 frame::{
10 mapping::{frame_to_index, index_to_meta, max_meta_slots},
11 meta_region_owners::MetaRegionOwners,
12 },
13 },
14};
15
16use crate::mm::{
17 frame::{
18 meta::{
19 REF_COUNT_MAX, REF_COUNT_UNIQUE, REF_COUNT_UNUSED,
20 mapping::{frame_to_meta, meta_to_frame},
21 },
22 *,
23 },
24 kspace::FRAME_METADATA_RANGE,
25};
26
27use super::meta_owners::*;
28
29verus! {
30
31impl<M: AnyFrameMeta + ?Sized + Repr<MetaSlotStorage> + OwnerOf> UniqueFrame<M> {
32 pub open spec fn paddr(self) -> Paddr {
33 meta_to_frame(self.ptr.addr())
34 }
35
36 pub open spec fn index(self) -> int {
37 frame_to_index(self.paddr())
38 }
39}
40
41pub tracked struct UniqueFrameOwner<M: AnyFrameMeta + ?Sized + Repr<MetaSlotStorage> + OwnerOf> {
43 pub meta_own: M::Owner,
44 pub ghost slot_index: int,
45}
46
47pub ghost struct UniqueFrameModel<M: AnyFrameMeta + ?Sized + Repr<MetaSlotStorage> + OwnerOf> {
48 pub meta: <M::Owner as View>::V,
49}
50
51impl<M: AnyFrameMeta + ?Sized + Repr<MetaSlotStorage> + OwnerOf> Inv for UniqueFrameOwner<M> {
52 open spec fn inv(self) -> bool {
53 &&& 0 <= self.slot_index < MAX_NR_PAGES
54 &&& self.slot_index < max_meta_slots()
55 }
56}
57
58impl<M: AnyFrameMeta + Sized + Repr<MetaSlotStorage> + OwnerOf> Inv for UniqueFrameModel<M> {
59 open spec fn inv(self) -> bool {
60 true
61 }
62}
63
64impl<M: AnyFrameMeta + ?Sized + Repr<MetaSlotStorage> + OwnerOf> View for UniqueFrameOwner<M> {
65 type V = UniqueFrameModel<M>;
66
67 open spec fn view(&self) -> Self::V {
68 UniqueFrameModel { meta: self.meta_own@ }
69 }
70}
71
72impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> InvView for UniqueFrameOwner<M> {
73 proof fn view_preserves_inv(self) {
74 }
75}
76
77impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> OwnerOf for UniqueFrame<M> {
78 type Owner = UniqueFrameOwner<M>;
79
80 open spec fn wf(self, owner: Self::Owner) -> bool {
81 &&& self.ptr.addr() == index_to_meta(owner.slot_index)
82 }
83}
84
85impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> UniqueFrame<M> {
86 pub open spec fn wf_with_region(self, owner: UniqueFrameOwner<M>, s: MetaRegionOwners) -> bool {
102 let idx = owner.slot_index;
103 let so = s.slot_owners[idx];
104 &&& self.wf(owner)
105 &&& owner.inv()
106 &&& s.inv()
107 &&& so.inner_perms.ref_count.value() == REF_COUNT_UNIQUE
108 &&& so.inner_perms.in_list.value() == 0
109 &&& so.paths_in_pt.is_empty()
110 }
111}
112
113impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> UniqueFrameOwner<M> {
114 pub open spec fn meta_perm_of(self, regions: MetaRegionOwners) -> PointsTo<
119 MetaSlot,
120 Metadata<M>,
121 > {
122 PointsTo::new_spec(
123 regions.slots[self.slot_index],
124 regions.slot_owners[self.slot_index].inner_perms,
125 )
126 }
127
128 pub open spec fn perm_inv(self, perm: vstd::simple_pptr::PointsTo<MetaSlot>) -> bool {
129 &&& perm.is_init()
130 &&& perm.addr() == index_to_meta(self.slot_index)
131 }
132
133 pub open spec fn global_inv(self, regions: MetaRegionOwners) -> bool {
143 let perm = self.meta_perm_of(regions);
144 &&& regions.slots.contains_key(self.slot_index)
145 &&& regions.slot_owners.contains_key(self.slot_index)
146 &&& perm.is_init()
147 &&& perm.wf(&perm.inner_perms)
148 &&& perm.addr() == index_to_meta(self.slot_index)
149 &&& perm.addr() == perm.points_to.addr()
150 &&& perm.value().metadata.wf(self.meta_own)
151 &&& regions.slot_owners[self.slot_index].slot_vaddr == index_to_meta(self.slot_index)
152 &&& regions.slot_owners[self.slot_index].inner_perms.ref_count.value()
153 == REF_COUNT_UNIQUE
154 &&& regions.slot_owners[self.slot_index].usage is Frame
159 &&& regions.frame_obligations.count(self.slot_index) > 0
160 }
161
162 pub proof fn from_raw_owner(owner: M::Owner, index: Ghost<int>) -> Self {
163 UniqueFrameOwner::<M> { meta_own: owner, slot_index: index@ }
164 }
165
166 pub open spec fn from_unused_owner(
167 old_regions: MetaRegionOwners,
168 paddr: Paddr,
169 metadata: M,
170 res: Self,
171 regions: MetaRegionOwners,
172 ) -> bool {
173 &&& <M as OwnerOf>::wf(metadata, res.meta_own)
174 &&& res.slot_index == frame_to_index(paddr)
175 &&& res.meta_perm_of(regions).addr() == frame_to_meta(paddr)
176 &&& res.meta_perm_of(regions).value().metadata == metadata
177 &&& regions.slots == old_regions.slots
178 &&& regions.slot_owners[frame_to_index(paddr)].inner_perms
179 == old_regions.slot_owners[frame_to_index(paddr)].inner_perms
180 &&& regions.slot_owners[frame_to_index(paddr)].usage
181 == old_regions.slot_owners[frame_to_index(paddr)].usage
182 &&& regions.slot_owners[frame_to_index(paddr)].paths_in_pt
183 == old_regions.slot_owners[frame_to_index(paddr)].paths_in_pt
184 &&& forall|i: int|
185 i != frame_to_index(paddr) ==> regions.slot_owners[i]
186 == old_regions.slot_owners[i]
187 &&& regions.frame_obligations == old_regions.frame_obligations
190 &&& regions.inv()
191 }
192
193 pub axiom fn tracked_from_unused_owner(
194 tracked regions: &mut MetaRegionOwners,
195 paddr: Paddr,
196 ) -> (tracked res: Self)
197 ensures
198 Self::from_unused_owner(
199 *old(regions),
200 paddr,
201 res.meta_perm_of(*final(regions)).value().metadata,
202 res,
203 *final(regions),
204 ),
205 ;
206}
207
208impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> TrackDrop for UniqueFrame<M> {
209 type State = MetaRegionOwners;
210
211 type Obligation = DropObligation<int>;
217
218 open spec fn tracked_redeem_requires(self, s: Self::State) -> bool {
219 &&& s.slot_owners.contains_key(self.index())
220 &&& s.slot_owners[frame_to_index(
221 meta_to_frame(self.ptr.addr()),
222 )].inner_perms.ref_count.value() != REF_COUNT_UNUSED
223 &&& s.inv()
224 }
225
226 open spec fn tracked_redeem_ensures(
227 self,
228 s0: Self::State,
229 s1: Self::State,
230 obl: Self::Obligation,
231 ) -> bool {
232 &&& s1.slot_owners[self.index()].inner_perms == s0.slot_owners[self.index()].inner_perms
233 &&& s1.slot_owners[self.index()].slot_vaddr == s0.slot_owners[self.index()].slot_vaddr
234 &&& s1.slot_owners[self.index()].usage == s0.slot_owners[self.index()].usage
235 &&& s1.slot_owners[self.index()].paths_in_pt == s0.slot_owners[self.index()].paths_in_pt
236 &&& forall|i: int|
237 #![trigger s1.slot_owners[i]]
238 i != self.index() ==> s1.slot_owners[i] == s0.slot_owners[i]
239 &&& s1.slots
240 =~= s0.slots
241 &&& s1.frame_obligations =~= s0.frame_obligations.insert(self.index())
245 &&& obl.value() == self.index()
246 &&& s1.inv()
247 }
248
249 proof fn tracked_redeem(self, tracked s: &mut Self::State) -> (tracked obl: Self::Obligation) {
250 let index = self.index();
251 let tracked mut slot_own = s.slot_owners.tracked_remove(index);
252 s.slot_owners.tracked_insert(index, slot_own);
253 s.tracked_mint_frame_obligation(index)
257 }
258
259 open spec fn drop_requires(self, s: Self::State, obl: Self::Obligation) -> bool {
260 &&& s.slot_owners.contains_key(self.index())
261 &&& s.inv()
262 &&& s.frame_obligations.count(self.index()) > 0
263 &&& obl.value() == self.index()
264 }
265
266 open spec fn drop_ensures(
267 self,
268 s0: Self::State,
269 s1: Self::State,
270 obl: Self::Obligation,
271 ) -> bool {
272 &&& forall|i: int|
273 #![trigger s1.slot_owners[i]]
274 i != self.index() ==> s1.slot_owners[i] == s0.slot_owners[i]
275 &&& s1.slots
276 =~= s0.slots
277 &&& s1.frame_obligations =~= s0.frame_obligations.remove(self.index())
282 &&& s1.inv()
283 }
284}
285
286}