1use vstd::cell;
2use vstd::prelude::*;
3use vstd::simple_pptr::{self, PPtr};
4
5use vstd_extra::cast_ptr::*;
6use vstd_extra::ownership::*;
7
8use super::meta_owners::{MetaSlotModel, MetaSlotStatus, PageUsage};
9use crate::mm::frame::meta::{
10 get_slot_spec,
11 mapping::{frame_to_index, frame_to_meta},
12 REF_COUNT_MAX, REF_COUNT_UNIQUE, REF_COUNT_UNUSED,
13};
14use crate::mm::frame::*;
15use crate::mm::{Paddr, PagingLevel, Vaddr};
16use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, PAGE_SIZE};
17use crate::specs::mm::frame::meta_region_owners::{MetaRegionModel, MetaRegionOwners};
18
19use core::marker::PhantomData;
20
21verus! {
22
23impl MetaSlot {
24 #[rustc_allow_incoherent_impl]
25 pub open spec fn from_unused_slot_spec<M: AnyFrameMeta>(
26 paddr: Paddr,
27 metadata: M,
28 as_unique_ptr: bool,
29 ) -> MetaSlotModel {
30 let (rc, status) = if as_unique_ptr {
31 (REF_COUNT_UNIQUE, MetaSlotStatus::UNIQUE)
32 } else {
33 (1, MetaSlotStatus::SHARED)
34 };
35 MetaSlotModel {
36 status,
37 storage: cell::MemContents::Uninit, ref_count: rc,
39 vtable_ptr: simple_pptr::MemContents::Init(metadata.vtable_ptr()),
40 in_list: 0,
41 self_addr: frame_to_meta(paddr),
42 usage: PageUsage::Frame,
43 }
44 }
45
46 #[rustc_allow_incoherent_impl]
47 pub open spec fn get_from_unused_spec<M: AnyFrameMeta>(
48 paddr: Paddr,
49 metadata: M,
50 as_unique_ptr: bool,
51 pre: MetaRegionModel,
53 ) -> (PPtr<MetaSlot>, MetaRegionModel)
54 recommends
55 paddr % 4096 == 0,
56 paddr < MAX_PADDR(),
57 pre.inv(),
58 pre.slots[frame_to_index(paddr)].ref_count == REF_COUNT_UNUSED,
59 {
60 let ptr = get_slot_spec(paddr);
61 let idx = frame_to_index(paddr);
62
63 let post = MetaRegionModel {
64 slots: pre.slots.insert(
65 idx,
66 Self::from_unused_slot_spec(paddr, metadata, as_unique_ptr),
67 ),
68 };
69 (ptr, post)
70 }
71
72 #[rustc_allow_incoherent_impl]
74 pub open spec fn update_index_tracked(
75 idx: usize,
76 pre: MetaRegionOwners,
77 post: MetaRegionOwners,
78 ) -> bool
79 recommends
80 pre.slots.contains_key(idx),
81 {
82 &&& pre.slots.dom() == post.slots.dom()
83 &&& pre.dropped_slots.dom() == post.dropped_slots.dom()
84 &&& pre.slot_owners.dom() == post.slot_owners.dom()
85 &&& forall|i: usize| #[trigger]
86 pre.slots.contains_key(i) && i != idx ==> pre.slots[i] == post.slots[i]
87 &&& forall|i: usize| #[trigger]
88 pre.dropped_slots.contains_key(i) && i != idx ==> pre.dropped_slots[i]
89 == post.dropped_slots[i]
90 &&& forall|i: usize| #[trigger]
91 pre.slot_owners.contains_key(i) && i != idx ==> pre.slot_owners[i]
92 == post.slot_owners[i]
93 }
94
95 #[rustc_allow_incoherent_impl]
96 pub open spec fn get_from_unused_tracked<M: AnyFrameMeta>(
97 paddr: Paddr,
98 metadata: M,
99 as_unique_ptr: bool,
100 pre: MetaRegionOwners,
102 post: MetaRegionOwners,
103 ) -> bool
104 recommends
105 paddr % 4096 == 0,
106 paddr < MAX_PADDR(),
107 pre.inv(),
108 pre.view().slots[paddr / 4096].ref_count == REF_COUNT_UNUSED,
109 {
110 let idx = paddr / 4096;
111 {
112 &&& Self::update_index_tracked(idx, pre, post)
113 &&& Self::get_from_unused_spec(paddr, metadata, as_unique_ptr, pre.view()).1
114 == post.view()
115 }
116 }
117
118 #[rustc_allow_incoherent_impl]
119 pub open spec fn get_from_in_use_spec(paddr: Paddr, pre: MetaRegionModel) -> (
120 PPtr<MetaSlot>,
121 MetaRegionModel,
122 )
123 recommends
124 paddr % 4096 == 0,
125 paddr < MAX_PADDR(),
126 pre.inv(),
127 0 <= pre.slots[paddr / 4096].ref_count < REF_COUNT_MAX,
128 {
129 let ptr = get_slot_spec(paddr);
130 let idx = paddr / 4096;
131 let pre_slot = pre.slots[idx];
132 let post = MetaRegionModel {
133 slots: pre.slots.insert(
134 idx,
135 MetaSlotModel { ref_count: (pre_slot.ref_count + 1) as u64, ..pre_slot },
136 ),
137 };
138 (ptr, post)
139 }
140
141 #[rustc_allow_incoherent_impl]
142 pub open spec fn get_from_in_use_tracked(
143 paddr: Paddr,
144 pre: MetaRegionOwners,
146 post: MetaRegionOwners,
147 ) -> bool
148 recommends
149 paddr % 4096 == 0,
150 paddr < MAX_PADDR(),
151 pre.inv(),
152 0 <= pre.view().slots[paddr / 4096].ref_count < REF_COUNT_MAX,
153 {
154 let idx = paddr / 4096;
155 {
156 &&& Self::update_index_tracked(idx, pre, post)
157 &&& Self::get_from_in_use_spec(paddr, pre.view()).1 == post.view()
158 }
159 }
160
161 #[rustc_allow_incoherent_impl]
162 pub open spec fn inc_ref_count_spec(&self, pre: MetaSlotModel) -> (MetaSlotModel)
163 recommends
164 pre.inv(),
165 pre.status == MetaSlotStatus::SHARED,
166 {
167 MetaSlotModel { ref_count: (pre.ref_count + 1) as u64, ..pre }
168 }
169}
170
171impl<M: AnyFrameMeta + Repr<MetaSlot> + OwnerOf> Frame<M> {
172 #[rustc_allow_incoherent_impl]
173 pub open spec fn from_raw_spec(paddr: Paddr) -> Self {
174 Frame::<M> {
175 ptr: PPtr::<MetaSlot>(frame_to_meta(paddr), PhantomData),
176 _marker: PhantomData,
177 }
178 }
179}
180
181}