ostd/specs/mm/frame/
meta_region_owners.rs1use vstd::{
2 atomic::*,
3 prelude::*,
4 simple_pptr::{self, *},
5};
6use vstd_extra::{cast_ptr::Repr, ownership::*};
7
8use crate::specs::{
9 arch::{MAX_PADDR, PAGE_SIZE, valid_frame_paddr},
10 mm::frame::mapping::{frame_to_index, index_to_meta, max_meta_slots},
11};
12
13use super::{meta_owners::MetaSlotOwner, *};
14use crate::mm::{
15 Paddr,
16 frame::{
17 Link,
18 meta::{AnyFrameMeta, META_SLOT_SIZE, MetaSlot, REF_COUNT_MAX, mapping::frame_to_meta},
19 },
20 kspace::FRAME_METADATA_RANGE,
21};
22use core::ops::Range;
23
24verus! {
25
26#[verifier::ext_equal]
32pub tracked struct MetaRegionOwners {
33 pub slots: Map<int, &'static simple_pptr::PointsTo<MetaSlot>>,
34 pub slot_owners: Map<int, MetaSlotOwner>,
35}
36
37impl Inv for MetaRegionOwners {
38 open spec fn inv(self) -> bool {
39 &&& {
40 forall|i: int|
43 0 <= i < max_meta_slots() <==> #[trigger] self.slot_owners.contains_key(i)
44 }
45 &&& {
46 forall|i: int| #[trigger]
47 self.slot_owners.contains_key(i) ==> self.slots.contains_key(i)
48 }
49 &&& { forall|i: int| #[trigger] self.slots.contains_key(i) ==> 0 <= i < max_meta_slots() }
50 &&& {
51 forall|i: int| #[trigger]
52 self.slots.contains_key(i) ==> {
53 &&& self.slot_owners[i].inv()
54 &&& self.slots[i].is_init()
55 &&& self.slots[i].addr() == index_to_meta(i)
56 &&& self.slots[i].value().wf(self.slot_owners[i])
57 &&& self.slot_owners[i].slot_vaddr == self.slots[i].addr()
58 }
59 }
60 }
61}
62
63impl MetaRegionOwners {
64 pub open spec fn contains(self, index: int) -> bool {
66 &&& self.slot_owners.contains_key(index)
67 &&& self.slots.contains_key(index)
68 }
69
70 pub open spec fn insert_slot_owner(self, paddr: Paddr, owner: MetaSlotOwner) -> Self {
71 let index = frame_to_index(paddr);
72 Self { slot_owners: self.slot_owners.insert(index, owner), ..self }
73 }
74
75 pub open spec fn ref_count(self, i: int) -> (res: u64)
76 recommends
77 0 <= i < max_meta_slots(),
78 {
79 self.slot_owners[i].ref_count()
80 }
81
82 pub open spec fn paddr_range_not_mapped(self, range: Range<Paddr>) -> bool
83 recommends
84 range.start < range.end < MAX_PADDR,
85 {
86 forall|paddr: Paddr|
87 #![trigger frame_to_index(paddr)]
88 (range.start <= paddr < range.end && paddr % PAGE_SIZE == 0) ==> self.slot_owner(
89 paddr,
90 ).paths_in_pt.is_empty()
91 }
92
93 pub proof fn lemma_contains_valid_frame_paddr(self, paddr: usize)
94 requires
95 valid_frame_paddr(paddr),
96 self.inv(),
97 ensures
98 self.contains(frame_to_index(paddr)),
99 {
100 }
101
102 pub open spec fn slot_owner(self, paddr: Paddr) -> MetaSlotOwner {
104 self.slot_owners[frame_to_index(paddr)]
105 }
106
107 pub proof fn tracked_borrow_slot(
109 tracked &self,
110 paddr: Paddr,
111 ) -> tracked &'static simple_pptr::PointsTo<MetaSlot>
112 requires
113 valid_frame_paddr(paddr),
114 self.inv(),
115 returns
116 self.slots[frame_to_index(paddr)],
117 {
118 self.lemma_contains_valid_frame_paddr(paddr);
119 *self.slots.tracked_borrow(frame_to_index(paddr))
120 }
121
122 pub proof fn tracked_borrow_slot_owner(tracked &self, paddr: Paddr) -> tracked &MetaSlotOwner
124 requires
125 valid_frame_paddr(paddr),
126 self.inv(),
127 returns
128 self.slot_owner(paddr),
129 {
130 self.lemma_contains_valid_frame_paddr(paddr);
131 self.slot_owners.tracked_borrow(frame_to_index(paddr))
132 }
133
134 pub proof fn tracked_borrow_mut_slot_owner(tracked &mut self, paddr: Paddr) -> (tracked ret:
136 &mut MetaSlotOwner)
137 requires
138 valid_frame_paddr(paddr),
139 self.inv(),
140 ensures
141 *ret == old(self).slot_owner(paddr),
142 *final(self) == old(self).insert_slot_owner(paddr, *final(ret)),
143 {
144 self.lemma_contains_valid_frame_paddr(paddr);
145 self.slot_owners.tracked_borrow_mut(frame_to_index(paddr))
146 }
147
148 pub open spec fn inc_frame_reference_region_spec(self, paddr: Paddr, post: Self) -> bool {
150 let idx = frame_to_index(paddr);
151 let pre_owner = self.slot_owners[idx];
152 let post_owner = post.slot_owners[idx];
153 {
154 &&& post.ref_count(idx) == self.ref_count(idx) + 1
155 &&& post_owner.ref_count_perm.id() == pre_owner.ref_count_perm.id()
156 &&& post_owner.metadata_perm.id() == pre_owner.metadata_perm.id()
157 &&& post_owner.metadata_perm.frac() + 1 == pre_owner.metadata_perm.frac()
158 &&& post_owner.metadata_perm@ == pre_owner.metadata_perm@
159 &&& post_owner.in_list_perm == pre_owner.in_list_perm
160 &&& post_owner.slot_vaddr == pre_owner.slot_vaddr
161 &&& post_owner.usage == pre_owner.usage
162 &&& post_owner.paths_in_pt == pre_owner.paths_in_pt
163 &&& post =~= self.insert_slot_owner(paddr, post_owner)
164 }
165 }
166}
167
168}