ostd/specs/arch/x86_64/
page_table_entry.rs1use vstd::prelude::*;
2use vstd::raw_ptr::*;
3
4use core::fmt::Debug;
5
6use vstd_extra::prelude::*;
7
8use super::*;
9use crate::mm::{
10 page_prop::{CachePolicy, PageFlags, PageProperty, PrivilegedPageFlags},
11 page_table::*,
12 Paddr, PagingLevel,
13};
14
15decl_bms_const!(
16 PAGE_FLAG_MAPPING,
17 PAGE_FLAG_MAPPING_SPEC,
18 u8,
19 usize,
20 4,
21 [
22 (PageFlags::R().value(), PageTableFlags::PRESENT()),
23 (PageFlags::W().value(), PageTableFlags::WRITABLE()),
24 (PageFlags::ACCESSED().value(), PageTableFlags::ACCESSED()),
25 (PageFlags::DIRTY().value(), PageTableFlags::DIRTY())
26 ]
27);
28
29decl_bms_const!(
30 PAGE_PRIV_MAPPING,
31 PAGE_PRIV_MAPPING_SPEC,
32 u8,
33 usize,
34 2,
35 [
36 (PrivilegedPageFlags::USER().value(), PageTableFlags::USER()),
37 (
38 PrivilegedPageFlags::GLOBAL().value(),
39 PageTableFlags::GLOBAL()
40 )
41 ]
42);
43
44decl_bms_const!(
45 PAGE_INVERTED_FLAG_MAPPING,
46 PAGE_INVERTED_FLAG_MAPPING_SPEC,
47 u8,
48 usize,
49 1,
50 [(PageFlags::X().value(), PageTableFlags::NO_EXECUTE())]
51);
52
53verus! {
54
55#[repr(transparent)]
56#[derive(Copy, Debug, PartialEq)]
57pub struct PageTableEntry(pub usize);
58
59global layout PageTableEntry is size == 8, align == 8;
60
61pub const PHYS_ADDR_MASK: usize = 0xffff_ffff_ffff_f000;
63
64impl Clone for PageTableEntry {
65 fn clone(&self) -> Self {
66 Self { 0: self.0 }
67 }
68}
69
70#[allow(non_snake_case)]
71impl PageTableEntry {
72
73 #[inline(always)]
74 #[vstd::contrib::auto_spec]
75 pub const fn PROP_MASK() -> (res: usize)
76 {
77 !PHYS_ADDR_MASK & !(PageTableFlags::HUGE())
78 }
79
80 #[verifier::inline]
81 pub open spec fn prop_assign_spec(self, flags: usize) -> Self {
82 Self((self.0 & !Self::PROP_MASK()) | flags as usize)
83 }
84
85 #[inline(always)]
86 pub fn prop_assign(&mut self, flags: usize)
87 ensures self.0 == old(self).prop_assign_spec(flags).0
88 {
89 self.0 = (self.0 & !Self::PROP_MASK()) | flags as usize;
90 }
91
92 #[vstd::contrib::auto_spec]
93 pub fn encode_cache(cache: CachePolicy) -> (res: usize)
94 {
95 match cache {
96 CachePolicy::Uncacheable => PageTableFlags::NO_CACHE(),
97 CachePolicy::Writethrough => PageTableFlags::WRITE_THROUGH(),
98 _ => 0,
99 }
100 }
101
102 pub open spec fn format_flags_spec(prop: PageProperty) -> usize {
103 let flags: u8 = prop.flags.value();
104 let priv_flags: u8 = prop.priv_flags.value();
105 PageTableFlags::PRESENT()
106 | flags.map_forward(&PAGE_FLAG_MAPPING)
107 | flags.map_invert_forward(&PAGE_INVERTED_FLAG_MAPPING)
108 | priv_flags.map_forward(&PAGE_PRIV_MAPPING)
109 | Self::encode_cache(prop.cache)
110 }
111
112 #[verifier::external_body]
113 #[verifier::when_used_as_spec(format_flags_spec)]
114 pub fn format_flags(prop: PageProperty) -> usize
115 returns Self::format_flags_spec(prop)
116 {
117 let flags: u8 = prop.flags.value();
118 let priv_flags: u8 = prop.priv_flags.value();
119 PageTableFlags::PRESENT()
120 | flags.map_forward(&PAGE_FLAG_MAPPING)
121 | flags.map_invert_forward(&PAGE_INVERTED_FLAG_MAPPING)
122 | priv_flags.map_forward(&PAGE_PRIV_MAPPING)
123 | Self::encode_cache(prop.cache)
124 }
125
126 #[vstd::contrib::auto_spec]
127 pub fn format_cache(flags: usize) -> (res: CachePolicy)
128 {
129 if flags & PageTableFlags::NO_CACHE() != 0 {
130 CachePolicy::Uncacheable
131 } else if flags & PageTableFlags::WRITE_THROUGH() != 0 {
132 CachePolicy::Writethrough
133 } else {
134 CachePolicy::Writeback
135 }
136 }
137
138 pub open spec fn format_property_spec(entry: usize) -> PageProperty {
139 let flags: u8 = entry.map_backward(&PAGE_FLAG_MAPPING)
140 | entry.map_invert_backward(&PAGE_INVERTED_FLAG_MAPPING);
141 let priv_flags: u8 = entry.map_backward(&PAGE_PRIV_MAPPING);
142 let cache = Self::format_cache(entry);
143 PageProperty {
144 flags: PageFlags::from_bits(flags),
145 cache,
146 priv_flags: PrivilegedPageFlags::from_bits(priv_flags),
147 }
148 }
149
150 #[verifier::external_body]
151 #[verifier::when_used_as_spec(format_property_spec)]
152 pub fn format_property(entry: usize) -> PageProperty
153 returns Self::format_property_spec(entry)
154 {
155 let flags = entry.map_backward(&PAGE_FLAG_MAPPING)
156 | entry.map_invert_backward(&PAGE_INVERTED_FLAG_MAPPING);
157 let priv_flags: u8 = entry.map_backward(&PAGE_PRIV_MAPPING);
158 let cache = Self::format_cache(entry);
159 PageProperty {
160 flags: PageFlags::from_bits(flags),
161 cache,
162 priv_flags: PrivilegedPageFlags::from_bits(priv_flags),
163 }
164 }
165
166 #[inline(always)]
167 #[vstd::contrib::auto_spec]
168 pub fn format_huge_page(level: PagingLevel) -> (res: u64)
169 {
170 if level == 1 {
171 0
172 } else {
173 PageTableFlags::HUGE() as u64
174 }
175 }
176
177}
178
179}
180
181verus! {
182
183impl PageTableEntryTrait for PageTableEntry {
184
185 #[verifier::inline]
186 open spec fn default_spec() -> Self
187 {
188 Self { 0: 0 }
189 }
190
191 #[inline(always)]
192 fn default() -> Self
193 returns Self::default_spec()
194 {
195 Self { 0: 0 }
196 }
197
198 #[verifier::inline]
199 open spec fn new_absent_spec() -> Self {
200 Self::default_spec()
201 }
202
203 #[inline(always)]
204 #[verifier::external_body]
205 fn new_absent() -> (res: Self)
206 {
207 Self::default()
208 }
209
210 #[verifier::inline]
211 open spec fn as_usize_spec(self) -> usize {
212 self.0 as usize
213 }
214
215 #[inline(always)]
216 fn as_usize(self) -> usize
217 returns self.as_usize_spec()
218 {
219 self.0 as usize
220 }
221
222 #[verifier::inline]
223 open spec fn is_present_spec(&self) -> bool {
224 self.0 & PageTableFlags::PRESENT() != 0
225 }
226
227 #[inline(always)]
228 fn is_present(&self) -> bool
229 returns self.is_present_spec()
230 {
231 self.0 & PageTableFlags::PRESENT() != 0
232 }
233
234 open spec fn set_prop_spec(&self, prop: PageProperty) -> Self {
235 let flags = Self::format_flags(prop);
236 self.prop_assign_spec(flags)
237 }
238
239 fn set_prop(&mut self, prop: PageProperty)
240 ensures *self == old(self).set_prop_spec(prop)
241 {
242 let flags = Self::format_flags(prop);
243 self.prop_assign(flags)
244 }
245
246 open spec fn new_page_spec(paddr: Paddr, level: PagingLevel, prop: PageProperty) -> Self {
247 let addr = paddr & PHYS_ADDR_MASK;
248 let hp = Self::format_huge_page(level) as usize;
249 let flags = Self::format_flags(prop) as usize;
250 Self(addr | hp | flags)
251 }
252
253 #[verifier::external_body]
254 fn new_page(paddr: Paddr, level: PagingLevel, prop: PageProperty) -> (res: Self)
255 {
256 let addr = paddr & PHYS_ADDR_MASK;
257 let hp = Self::format_huge_page(level) as usize;
258 let flags = Self::format_flags(prop) as usize;
259 Self(addr | hp | flags)
260 }
261
262 open spec fn new_pt_spec(paddr: Paddr) -> Self {
263 let addr = paddr & PHYS_ADDR_MASK;
264 Self(addr | PageTableFlags::PRESENT() | PageTableFlags::WRITABLE() | PageTableFlags::USER())
265 }
266
267 #[verifier::external_body]
268 fn new_pt(paddr: Paddr) -> (res: Self)
269 {
270 let addr = paddr & PHYS_ADDR_MASK;
271 Self(addr | PageTableFlags::PRESENT() | PageTableFlags::WRITABLE() | PageTableFlags::USER())
272 }
273
274 #[verifier::inline]
275 open spec fn paddr_spec(&self) -> Paddr {
276 self.0 & PHYS_ADDR_MASK
277 }
278
279 #[inline(always)]
280 fn paddr(&self) -> Paddr
281 returns self.paddr_spec()
282 {
283 self.0 & PHYS_ADDR_MASK
284 }
285
286 #[verifier::inline]
287 open spec fn prop_spec(&self) -> PageProperty {
288 Self::format_property(self.0)
289 }
290
291 #[inline(always)]
292 fn prop(&self) -> PageProperty
293 returns self.prop_spec()
294 {
295 Self::format_property(self.0)
296 }
297
298 #[verifier::inline]
299 open spec fn is_last_spec(&self, level: PagingLevel) -> bool {
300 level == 1 || (self.0 & PageTableFlags::HUGE() != 0)
301 }
302
303 #[inline(always)]
304 fn is_last(&self, level: PagingLevel) -> bool
305 returns self.is_last_spec(level)
306 {
307 level == 1 || (self.0 & PageTableFlags::HUGE() != 0)
308 }
309
310 proof fn set_prop_properties(self, prop: PageProperty)
311 {
312 admit();
313 }
314
315 proof fn new_properties()
316 {
317 admit();
318 }
319
320}
321
322impl PageTableEntry {
323 pub axiom fn absent_pte_paddr_ok()
325 ensures
326 Self::new_absent_spec().paddr_spec() % crate::specs::arch::mm::PAGE_SIZE == 0,
327 Self::new_absent_spec().paddr_spec() < crate::specs::arch::mm::MAX_PADDR;
328}
329
330}