ostd/specs/mm/frame/
frame_specs.rs1use vstd::{
2 cell::CellId,
3 prelude::*,
4 simple_pptr::{self, PPtr, PointsTo},
5};
6use vstd_extra::{cast_ptr::*, ownership::*};
7
8use crate::specs::{
9 arch::*,
10 mm::frame::{
11 mapping::{frame_to_index, meta_to_index},
12 meta_owners::{FracMetadataPerm, MetaSlotStorage, MetadataPerm, PageUsage, typed_meta_wf},
13 meta_region_owners::MetaRegionOwners,
14 },
15};
16
17use crate::mm::{
18 Paddr, PagingLevel, Vaddr,
19 frame::{
20 meta::{
21 META_SLOT_SIZE, MetaSlot, REF_COUNT_MAX, REF_COUNT_UNIQUE, REF_COUNT_UNUSED,
22 mapping::{frame_to_meta, meta_to_frame},
23 },
24 *,
25 },
26 kspace::FRAME_METADATA_RANGE,
27};
28use core::marker::PhantomData;
29
30verus! {
31
32pub open spec fn valid_slot_vaddr(addr: Vaddr) -> bool {
33 &&& valid_frame_paddr(meta_to_frame(addr))
34 &&& addr % META_SLOT_SIZE == 0
35 &&& FRAME_METADATA_RANGE.start <= addr < FRAME_METADATA_RANGE.start + MAX_NR_PAGES
36 * META_SLOT_SIZE
37}
38
39pub tracked struct FrameRawPerms {
41 pub slot_perm: &'static simple_pptr::PointsTo<MetaSlot>,
42 pub metadata_perm: FracMetadataPerm,
43}
44
45#[cfg(feature = "irc11")]
48unsafe impl vstd::thread_view::Objective for FrameRawPerms {
49
50}
51
52impl FrameRawPerms {
53 pub open spec fn slot_vaddr(self) -> Vaddr {
54 self.slot_perm.pptr().addr()
55 }
56}
57
58impl Inv for FrameRawPerms {
59 open spec fn inv(self) -> bool {
60 &&& valid_slot_vaddr(self.slot_vaddr())
61 &&& self.slot_perm.is_init()
62 &&& self.metadata_perm.frac() == 1
63 &&& MetaSlot::perms_related(*self.slot_perm, self.metadata_perm.resource())
64 }
65}
66
67impl<M: ?Sized> Frame<M> {
68 #[verifier::inline]
70 pub open spec fn frac_metadata_perm(self) -> FracMetadataPerm {
71 self.tracked_metadata_perm@->0
72 }
73
74 #[verifier::inline]
76 pub open spec fn metadata_perm(self) -> MetadataPerm {
77 self.frac_metadata_perm().resource()
78 }
79
80 pub open spec fn slot_perm(self) -> PointsTo<MetaSlot> {
82 *self.tracked_slot_perm@
83 }
84
85 #[verifier::inline]
87 pub open spec fn ref_count_id(self) -> int {
88 self.slot_perm().value().ref_count.id()
89 }
90
91 #[verifier::inline]
93 pub open spec fn storage_id(self) -> CellId {
94 self.slot_perm().value().storage.id()
95 }
96
97 #[verifier::inline]
100 pub open spec fn ptr_inv(self) -> bool {
101 &&& valid_slot_vaddr(self.ptr.addr())
102 &&& self.slot_perm().pptr() == self.ptr
103 &&& self.slot_perm().is_init()
104 }
105
106 pub open spec fn from_raw_requires(regions: MetaRegionOwners, paddr: Paddr) -> bool {
108 &&& regions.slot_owner(paddr).slot_vaddr == frame_to_meta(paddr)
109 &&& valid_frame_paddr(paddr)
110 &&& regions.inv()
111 &&& 0 < regions.slot_owner(paddr).ref_count() <= REF_COUNT_MAX
112 }
113}
114
115impl<M: AnyFrameMeta + Repr<MetaSlotStorage> + ?Sized> Frame<M> {
116 pub open spec fn external_meta_wf(
118 self,
119 metadata_perm: MetadataPerm,
120 repr_perm: M::ReprPerm,
121 ) -> bool {
122 &&& self.ptr_inv()
123 &&& self.tracked_metadata_perm@ is None
124 &&& typed_meta_wf::<M>(self.slot_perm(), metadata_perm, repr_perm)
125 }
126}
127
128impl<M: ?Sized> Inv for Frame<M> {
129 open spec fn inv(self) -> bool {
130 &&& self.ptr_inv()
131 &&& self.tracked_metadata_perm@ is Some
132 &&& self.frac_metadata_perm().frac() == 1
133 &&& MetaSlot::perms_related(self.slot_perm(), self.metadata_perm())
134 }
135}
136
137impl<M: ?Sized> Frame<M> {
138 pub open spec fn index(self) -> int {
139 frame_to_index(self.start_paddr_spec())
140 }
141
142 pub open spec fn start_paddr_spec(self) -> Paddr {
143 meta_to_frame(self.ptr.addr())
144 }
145
146 pub open spec fn drop_requires(self, region: MetaRegionOwners) -> bool {
147 let idx = self.index();
148 let slot_own = region.slot_owners[idx];
149 &&& self.inv()
150 &&& region.inv()
151 &&& self.wf_with_region(region)
152 &&& 0 < slot_own.ref_count() <= REF_COUNT_MAX
153 &&& slot_own.ref_count() == 1 ==> {
154 &&& slot_own.paths_in_pt.is_empty()
155 }
156 }
157
158 pub open spec fn drop_ensures(self, old: MetaRegionOwners, new: MetaRegionOwners) -> bool {
159 let paddr = self.start_paddr_spec();
160 let old_owner = old.slot_owner(paddr);
161 let new_owner = new.slot_owner(paddr);
162 &&& new.inv()
163 &&& new =~= old.insert_slot_owner(paddr, new_owner)
164 &&& new_owner.slot_vaddr == old_owner.slot_vaddr
165 &&& new_owner.usage == old_owner.usage
166 &&& new_owner.paths_in_pt == old_owner.paths_in_pt
167 &&& new_owner.metadata_perm.id() == old_owner.metadata_perm.id()
168 &&& old_owner.ref_count() == 1 ==> { new_owner.ref_count() == REF_COUNT_UNUSED }
169 &&& old_owner.ref_count() > 1 ==> new_owner.ref_count() == (old_owner.ref_count()
170 - 1) as u64
171 }
172}
173
174impl<M: ?Sized> Frame<M> {
175 pub open spec fn wf_with_region(self, s: MetaRegionOwners) -> bool {
177 let idx = self.index();
178 let slot_own = s.slot_owners[idx];
179 &&& s.contains(idx)
180 &&& self.tracked_slot_perm@ == s.slots[idx]
181 &&& self.frac_metadata_perm().id() == slot_own.metadata_perm.id()
182 }
183}
184
185impl<M: ?Sized> Frame<M> {
186 pub open spec fn from_raw_spec(
187 paddr: Paddr,
188 slot_perm: &'static PointsTo<MetaSlot>,
189 metadata_perm: Option<FracMetadataPerm>,
190 ) -> Self {
191 Frame::<M> {
192 ptr: PPtr::<MetaSlot>(frame_to_meta(paddr), PhantomData),
193 _marker: PhantomData,
194 #[cfg(verus_keep_ghost_body)]
195 tracked_slot_perm: Tracked(slot_perm),
196 #[cfg(verus_keep_ghost_body)]
197 tracked_metadata_perm: Tracked(metadata_perm),
198 }
199 }
200}
201
202}