ostd/specs/mm/frame/
frame_specs.rs1use vstd::prelude::*;
2
3use vstd_extra::cast_ptr::*;
4use vstd_extra::ownership::*;
5
6use crate::mm::frame::meta::{get_slot_spec, mapping::frame_to_index, REF_COUNT_UNUSED};
7use crate::mm::frame::*;
8use crate::mm::{Paddr, PagingLevel, Vaddr};
9use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, PAGE_SIZE};
10use crate::specs::mm::frame::meta_owners::{MetaPerm, MetaSlotStorage};
11use crate::specs::mm::frame::meta_region_owners::MetaRegionOwners;
12
13use core::marker::PhantomData;
14
15verus! {
16
17pub tracked struct BorrowDebt {
25 pub ghost frame_index: usize,
27 pub ghost raw_count_at_issue: usize,
29}
30
31impl BorrowDebt {
32 pub proof fn discharge_bookkeeping(tracked self)
36 requires self.raw_count_at_issue == 1,
37 {}
38
39 pub proof fn discharge_with_manual_drop(tracked self, regions: &MetaRegionOwners)
43 requires
44 regions.slot_owners.contains_key(self.frame_index),
45 regions.slot_owners[self.frame_index].raw_count == 1,
46 {}
47
48 pub proof fn discharge_in_lemma(tracked self, regions: &MetaRegionOwners)
54 requires
55 regions.slot_owners.contains_key(self.frame_index),
56 regions.slot_owners[self.frame_index].raw_count == 0,
57 {}
58}
59
60impl<'a, M: AnyFrameMeta> Frame<M> {
61 pub open spec fn from_raw_requires_safety(regions: MetaRegionOwners, paddr: Paddr) -> bool {
67 &&& regions.slot_owners.contains_key(frame_to_index(paddr))
68 &&& regions.slot_owners[frame_to_index(paddr)].self_addr == frame_to_meta(paddr)
69 &&& has_safe_slot(paddr) &&& regions.inv()
71 }
72
73 pub open spec fn from_raw_requires_bookkeeping(regions: MetaRegionOwners, paddr: Paddr) -> bool {
80 regions.slot_owners[frame_to_index(paddr)].raw_count == 1
81 }
82
83 pub open spec fn from_raw_requires(regions: MetaRegionOwners, paddr: Paddr) -> bool {
86 &&& Self::from_raw_requires_safety(regions, paddr)
87 &&& Self::from_raw_requires_bookkeeping(regions, paddr)
88 }
89
90 pub open spec fn from_raw_ensures(
91 old_regions: MetaRegionOwners,
92 new_regions: MetaRegionOwners,
93 paddr: Paddr,
94 r: Self,
95 ) -> bool {
96 &&& new_regions.inv()
97 &&& new_regions.slots.contains_key(frame_to_index(paddr))
98 &&& new_regions.slot_owners[frame_to_index(paddr)].raw_count == 0
99 &&& new_regions.slot_owners[frame_to_index(paddr)].inner_perms ==
100 old_regions.slot_owners[frame_to_index(paddr)].inner_perms
101 &&& new_regions.slot_owners[frame_to_index(paddr)].usage ==
102 old_regions.slot_owners[frame_to_index(paddr)].usage
103 &&& new_regions.slot_owners[frame_to_index(paddr)].paths_in_pt ==
104 old_regions.slot_owners[frame_to_index(paddr)].paths_in_pt
105 &&& new_regions.slot_owners[frame_to_index(paddr)].self_addr == r.ptr.addr()
106 &&& forall|i: usize|
107 #![trigger new_regions.slot_owners[i], old_regions.slot_owners[i]]
108 i != frame_to_index(paddr) ==> new_regions.slot_owners[i] == old_regions.slot_owners[i]
109 &&& forall|i: usize|
110 i != frame_to_index(paddr) ==>
111 new_regions.slots.contains_key(i) == old_regions.slots.contains_key(i)
112 &&& r.ptr.addr() == frame_to_meta(paddr)
113 &&& r.paddr() == paddr
114 }
115
116
117 pub open spec fn into_raw_pre_frame_inv(self) -> bool {
121 self.inv()
122 }
123
124 pub open spec fn into_raw_pre_not_unused(self, regions: MetaRegionOwners) -> bool {
126 regions.slot_owners[self.index()].inner_perms.ref_count.value() != REF_COUNT_UNUSED
127 }
128
129 pub open spec fn into_raw_post_raw_count_incremented(
133 self,
134 old_regions: MetaRegionOwners,
135 new_regions: MetaRegionOwners,
136 ) -> bool {
137 &&& new_regions.slot_owners.contains_key(self.index())
138 &&& new_regions.slot_owners[self.index()].raw_count
139 == (old_regions.slot_owners[self.index()].raw_count + 1) as usize
140 }
141
142 pub open spec fn into_raw_post_noninterference(
144 self,
145 old_regions: MetaRegionOwners,
146 new_regions: MetaRegionOwners,
147 ) -> bool {
148 &&& forall|i: usize|
149 #![trigger new_regions.slots[i], old_regions.slots[i]]
150 i != self.index() && old_regions.slots.contains_key(i)
151 ==> new_regions.slots.contains_key(i)
152 && new_regions.slots[i] == old_regions.slots[i]
153 &&& forall|i: usize|
154 #![trigger new_regions.slot_owners[i], old_regions.slot_owners[i]]
155 i != self.index() ==> new_regions.slot_owners[i] == old_regions.slot_owners[i]
156 &&& new_regions.slot_owners.dom() =~= old_regions.slot_owners.dom()
157 }
158}
159
160}