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