ostd/specs/mm/frame/
unique.rs1use vstd::prelude::*;
2use vstd_extra::cast_ptr::*;
3use vstd_extra::drop_tracking::*;
4use vstd_extra::ownership::*;
5
6use super::meta_owners::*;
7use crate::mm::frame::*;
8use crate::specs::arch::kspace::FRAME_METADATA_RANGE;
9use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, PAGE_SIZE};
10use crate::specs::mm::Paddr;
11use crate::specs::mm::frame::mapping::{
12 frame_to_index, frame_to_meta, max_meta_slots, meta_addr, meta_to_frame,
13};
14use crate::specs::mm::frame::meta_region_owners::{MetaRegionModel, MetaRegionOwners};
15
16verus! {
17
18pub tracked struct UniqueFrameOwner<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> {
19 pub meta_own: M::Owner,
20 pub ghost slot_index: usize,
21}
22
23pub ghost struct UniqueFrameModel<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> {
24 pub meta: <M::Owner as View>::V,
25}
26
27impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Inv for UniqueFrameOwner<M> {
28 open spec fn inv(self) -> bool {
29 &&& self.slot_index < MAX_NR_PAGES
30 &&& self.slot_index < max_meta_slots()
31 }
32}
33
34impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> Inv for UniqueFrameModel<M> {
35 open spec fn inv(self) -> bool {
36 true
37 }
38}
39
40impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> View for UniqueFrameOwner<M> {
41 type V = UniqueFrameModel<M>;
42
43 open spec fn view(&self) -> Self::V {
44 UniqueFrameModel { meta: self.meta_own@ }
45 }
46}
47
48impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> InvView for UniqueFrameOwner<M> {
49 proof fn view_preserves_inv(self) {
50 }
51}
52
53impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> OwnerOf for UniqueFrame<M> {
54 type Owner = UniqueFrameOwner<M>;
55
56 open spec fn wf(self, owner: Self::Owner) -> bool {
57 &&& self.ptr.addr() == meta_addr(owner.slot_index)
58 }
59}
60
61impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> ModelOf for UniqueFrame<M> {
62
63}
64
65impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> UniqueFrameOwner<M> {
66 pub open spec fn meta_perm_of(self, regions: MetaRegionOwners) -> PointsTo<
71 MetaSlot,
72 Metadata<M>,
73 > {
74 PointsTo::new_spec(
75 regions.slots[self.slot_index],
76 regions.slot_owners[self.slot_index].inner_perms,
77 )
78 }
79
80 pub open spec fn perm_inv(self, perm: vstd::simple_pptr::PointsTo<MetaSlot>) -> bool {
81 &&& perm.is_init()
82 &&& perm.addr() == meta_addr(self.slot_index)
83 }
84
85 pub open spec fn global_inv(self, regions: MetaRegionOwners) -> bool {
95 let perm = self.meta_perm_of(regions);
96 &&& regions.slots.contains_key(self.slot_index)
97 &&& regions.slot_owners.contains_key(self.slot_index)
98 &&& perm.is_init()
99 &&& perm.wf(&perm.inner_perms)
100 &&& perm.addr() == meta_addr(self.slot_index)
101 &&& perm.addr() == perm.points_to.addr()
102 &&& perm.value().metadata.wf(self.meta_own)
103 &&& regions.slot_owners[self.slot_index].self_addr == meta_addr(self.slot_index)
104 &&& regions.slot_owners[self.slot_index].inner_perms.ref_count.value() == REF_COUNT_UNIQUE
105 &&& regions.frame_obligations.count(self.slot_index) > 0
106 }
107
108 pub proof fn from_raw_owner(owner: M::Owner, index: Ghost<usize>) -> Self {
109 UniqueFrameOwner::<M> { meta_own: owner, slot_index: index@ }
110 }
111
112 pub open spec fn from_unused_owner(
113 old_regions: MetaRegionOwners,
114 paddr: Paddr,
115 metadata: M,
116 res: Self,
117 regions: MetaRegionOwners,
118 ) -> bool {
119 &&& <M as OwnerOf>::wf(metadata, res.meta_own)
120 &&& res.slot_index == frame_to_index(paddr)
121 &&& res.meta_perm_of(regions).addr() == frame_to_meta(paddr)
122 &&& res.meta_perm_of(regions).value().metadata == metadata
123 &&& regions.slots == old_regions.slots
124 &&& regions.slot_owners[frame_to_index(paddr)].inner_perms
125 == old_regions.slot_owners[frame_to_index(paddr)].inner_perms
126 &&& regions.slot_owners[frame_to_index(paddr)].usage
127 == old_regions.slot_owners[frame_to_index(paddr)].usage
128 &&& regions.slot_owners[frame_to_index(paddr)].paths_in_pt
129 == old_regions.slot_owners[frame_to_index(paddr)].paths_in_pt
130 &&& forall|i: usize|
131 i != frame_to_index(paddr) ==> regions.slot_owners[i]
132 == old_regions.slot_owners[i]
133 &&& regions.frame_obligations == old_regions.frame_obligations
136 &&& regions.inv()
137 }
138
139 pub axiom fn tracked_from_unused_owner(
140 tracked regions: &mut MetaRegionOwners,
141 paddr: Paddr,
142 ) -> (tracked res: Self)
143 ensures
144 Self::from_unused_owner(
145 *old(regions),
146 paddr,
147 res.meta_perm_of(*final(regions)).value().metadata,
148 res,
149 *final(regions),
150 ),
151 ;
152}
153
154impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + OwnerOf> TrackDrop for UniqueFrame<M> {
155 type State = MetaRegionOwners;
156
157 type Key = usize;
163
164 open spec fn key(self) -> Self::Key {
165 frame_to_index(meta_to_frame(self.ptr.addr()))
166 }
167
168 open spec fn constructor_requires(self, s: Self::State) -> bool {
169 &&& s.slot_owners.contains_key(frame_to_index(meta_to_frame(self.ptr.addr())))
170 &&& s.slot_owners[frame_to_index(
171 meta_to_frame(self.ptr.addr()),
172 )].inner_perms.ref_count.value() != REF_COUNT_UNUSED
173 &&& s.inv()
174 }
175
176 open spec fn constructor_ensures(
177 self,
178 s0: Self::State,
179 s1: Self::State,
180 obl_key: Self::Key,
181 ) -> bool {
182 &&& s1.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].inner_perms
183 == s0.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].inner_perms
184 &&& s1.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].self_addr
185 == s0.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].self_addr
186 &&& s1.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].usage
187 == s0.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].usage
188 &&& s1.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].paths_in_pt
189 == s0.slot_owners[frame_to_index(meta_to_frame(self.ptr.addr()))].paths_in_pt
190 &&& forall|i: usize|
191 #![trigger s1.slot_owners[i]]
192 i != frame_to_index(meta_to_frame(self.ptr.addr())) ==> s1.slot_owners[i]
193 == s0.slot_owners[i]
194 &&& s1.slots
195 =~= s0.slots
196 &&& s1.frame_obligations =~= s0.frame_obligations.insert(obl_key)
200 &&& s1.inv()
201 }
202
203 proof fn constructor_spec(self, tracked s: &mut Self::State) -> (tracked obl: DropObligation<
204 Self::Key,
205 >) {
206 let index = frame_to_index(meta_to_frame(self.ptr.addr()));
207 let tracked mut slot_own = s.slot_owners.tracked_remove(index);
208 s.slot_owners.tracked_insert(index, slot_own);
209 s.tracked_mint_frame_obligation(index)
213 }
214
215 open spec fn drop_requires(self, s: Self::State) -> bool {
216 &&& s.slot_owners.contains_key(frame_to_index(meta_to_frame(self.ptr.addr())))
217 &&& s.inv()
218 }
219
220 open spec fn drop_ensures(self, s0: Self::State, s1: Self::State, obl_key: Self::Key) -> bool {
221 &&& forall|i: usize|
222 #![trigger s1.slot_owners[i]]
223 i != frame_to_index(meta_to_frame(self.ptr.addr())) ==> s1.slot_owners[i]
224 == s0.slot_owners[i]
225 &&& s1.slots
226 =~= s0.slots
227 &&& s1.frame_obligations =~= s0.frame_obligations.remove(obl_key)
232 &&& s1.inv()
233 }
234
235 open spec fn consume_requires(self, s: Self::State, obl_key: Self::Key) -> bool {
239 s.frame_obligations.count(obl_key) > 0
240 }
241
242 open spec fn consume_ensures(
243 self,
244 s0: Self::State,
245 s1: Self::State,
246 obl_key: Self::Key,
247 ) -> bool {
248 &&& s1.frame_obligations =~= s0.frame_obligations.remove(obl_key)
249 &&& s1.slots =~= s0.slots
250 &&& s1.slot_owners =~= s0.slot_owners
251 }
252
253 proof fn consume_obligation(
254 self,
255 tracked s: &mut Self::State,
256 tracked obl: DropObligation<Self::Key>,
257 ) {
258 s.tracked_redeem_frame_obligation(obl);
261 }
262}
263
264}