ostd/specs/mm/frame/
meta_region_owners.rs1use vstd::atomic::*;
2use vstd::cell;
3use vstd::prelude::*;
4use vstd::simple_pptr::{self, *};
5
6use core::ops::Range;
7
8use vstd_extra::ownership::*;
9
10use super::meta_owners::{MetaSlotModel, MetaSlotOwner};
11use super::*;
12use crate::mm::frame::meta::{
13 mapping::{frame_to_index_spec, frame_to_meta, max_meta_slots, meta_addr, META_SLOT_SIZE},
14 MetaSlot,
15};
16use crate::mm::Paddr;
17use crate::specs::arch::kspace::FRAME_METADATA_RANGE;
18use crate::specs::arch::mm::{MAX_PADDR, PAGE_SIZE};
19
20verus! {
21
22pub struct MetaRegion;
25
26pub tracked struct MetaRegionOwners {
27 pub slots: Map<usize, simple_pptr::PointsTo<MetaSlot>>,
28 pub dropped_slots: Map<usize, simple_pptr::PointsTo<MetaSlot>>,
29 pub slot_owners: Map<usize, MetaSlotOwner>,
30}
31
32pub ghost struct MetaRegionModel {
33 pub slots: Map<usize, MetaSlotModel>,
34}
35
36impl Inv for MetaRegionOwners {
37 open spec fn inv(self) -> bool {
38 &&& self.slots.dom().finite()
39 &&& {
40 forall|i: usize| i < max_meta_slots() <==> #[trigger] self.slot_owners.contains_key(i)
42 }
43 &&& { forall|i: usize| #[trigger] self.slots.contains_key(i) ==> i < max_meta_slots() }
44 &&& {
45 forall|i: usize| #[trigger] self.dropped_slots.contains_key(i) ==> i < max_meta_slots()
46 }
47 &&& {
48 forall|i: usize| #[trigger]
50 self.slot_owners.contains_key(i) ==> self.slot_owners[i].inv()
51 }
52 &&& {
53 forall|i: usize| #[trigger]
54 self.slots.contains_key(i) ==> {
55 &&& self.slots[i].is_init()
56 &&& self.slots[i].addr() == meta_addr(i)
57 &&& self.slots[i].value().wf(self.slot_owners[i])
58 &&& self.slot_owners[i].self_addr == self.slots[i].addr()
59 &&& !self.dropped_slots.contains_key(i)
60 }
61 }
62 &&& {
63 forall|i: usize| #[trigger]
64 self.dropped_slots.contains_key(i) ==> {
65 &&& self.dropped_slots[i].is_init()
66 &&& self.dropped_slots[i].addr() == meta_addr(i)
67 &&& self.dropped_slots[i].value().wf(self.slot_owners[i])
68 &&& self.slot_owners[i].self_addr == self.dropped_slots[i].addr()
69 &&& !self.slots.contains_key(i)
70 }
71 }
72 }
73}
74
75impl Inv for MetaRegionModel {
76 open spec fn inv(self) -> bool {
77 &&& self.slots.dom().finite()
78 &&& forall|i: usize| i < max_meta_slots() <==> #[trigger] self.slots.contains_key(i)
79 &&& forall|i: usize| #[trigger] self.slots.contains_key(i) ==> self.slots[i].inv()
80 }
81}
82
83impl View for MetaRegionOwners {
84 type V = MetaRegionModel;
85
86 open spec fn view(&self) -> <Self as View>::V {
87 let slots = self.slot_owners.map_values(|s: MetaSlotOwner| s@);
88 MetaRegionModel { slots }
89 }
90}
91
92impl InvView for MetaRegionOwners {
93 axiom fn view_preserves_inv(self);
95}
96
97impl OwnerOf for MetaRegion {
98 type Owner = MetaRegionOwners;
99
100 open spec fn wf(self, owner: Self::Owner) -> bool {
101 true
102 }
103}
104
105impl ModelOf for MetaRegion {
106
107}
108
109impl MetaRegionOwners {
110 pub open spec fn ref_count(self, i: usize) -> (res: u64)
111 recommends
112 self.inv(),
113 i < max_meta_slots() as usize,
114 {
115 self.slot_owners[i].ref_count.value()
116 }
117
118 pub open spec fn paddr_range_in_region(self, range: Range<Paddr>) -> bool
119 recommends
120 self.inv(),
121 range.start < range.end < MAX_PADDR(),
122 {
123 forall|paddr: Paddr|
124 #![trigger frame_to_index_spec(paddr)]
125 (range.start <= paddr < range.end && paddr % PAGE_SIZE() == 0)
126 ==> self.slots.contains_key(frame_to_index_spec(paddr))
127 }
128
129 pub open spec fn paddr_range_in_dropped_region(self, range: Range<Paddr>) -> bool
130 recommends
131 self.inv(),
132 range.start < range.end < MAX_PADDR(),
133 {
134 forall|paddr: Paddr|
135 #![trigger frame_to_index_spec(paddr)]
136 (range.start <= paddr < range.end && paddr % PAGE_SIZE() == 0)
137 ==> !self.slots.contains_key(frame_to_index_spec(paddr))
138 && self.dropped_slots.contains_key(frame_to_index_spec(paddr))
139 }
140
141 pub open spec fn paddr_range_not_in_region(self, range: Range<Paddr>) -> bool
142 recommends
143 self.inv(),
144 range.start < range.end < MAX_PADDR(),
145 {
146 forall|paddr: Paddr|
147 #![trigger frame_to_index_spec(paddr)]
148 (range.start <= paddr < range.end && paddr % PAGE_SIZE() == 0)
149 ==> !self.slots.contains_key(frame_to_index_spec(paddr))
150 && !self.dropped_slots.contains_key(frame_to_index_spec(paddr))
151 }
152
153 pub proof fn inv_implies_correct_addr(self, paddr: usize)
154 requires
155 paddr < MAX_PADDR(),
156 paddr % PAGE_SIZE() == 0,
157 self.inv(),
158 ensures
159 self.slot_owners.contains_key(frame_to_index_spec(paddr) as usize),
160 {
161 assert((frame_to_index_spec(paddr)) < max_meta_slots() as usize);
162 }
163}
164
165}