ostd/specs/mm/page_table/cursor/
page_table_cursor_specs.rs1use vstd::{prelude::*, set_lib::*};
2use vstd_extra::{arithmetic::*, ownership::*};
3
4use crate::specs::{
5 arch::NR_ENTRIES,
6 mm::page_table::{cursor::owners::*, *},
7};
8
9use crate::arch::mm::PagingConsts;
10use crate::mm::{
11 Paddr, PagingConstsTrait, PagingLevel, Vaddr, page_prop::PageProperty, page_table::*,
12};
13use core::ops::Range;
14
15verus! {
16
17impl<C: PageTableConfig> CursorView<C> {
22 pub open spec fn item_into_mapping(va: Vaddr, item: C::Item) -> Mapping {
23 let (paddr, level, prop, _perm) = C::item_into_raw(item);
24 let size = page_size::<PagingConsts>(level);
25 Mapping {
26 va_range: va as int..va + size,
27 pa_range: paddr..(paddr + size) as Paddr,
28 page_size: size,
29 property: prop,
30 }
31 }
32
33 pub open spec fn present(self) -> bool {
37 self.mappings.filter(|m: Mapping| m.va_range.start <= self.cur_va < m.va_range.end).len()
38 > 0
39 }
40
41 pub open spec fn query_mapping(self) -> Mapping
42 recommends
43 self.present(),
44 {
45 self.mappings.filter(|m: Mapping| m.va_range.start <= self.cur_va < m.va_range.end).choose()
46 }
47
48 pub open spec fn query(self, paddr: Paddr, size: usize, prop: PageProperty) -> bool {
49 let m = self.query_mapping();
50 m.pa_range.start == paddr && m.page_size == size && m.property == prop
51 }
52
53 pub open spec fn query_range(self) -> Range<int> {
54 self.query_mapping().va_range
55 }
56
57 pub open spec fn cur_slot_range(self, size: usize) -> Range<int> {
61 let start = nat_align_down(self.cur_va as nat, size as nat) as int;
62 start..start + size
63 }
64
65 pub open spec fn query_item_spec(self, item: C::Item) -> Option<Range<Vaddr>>
68 recommends
69 self.present(),
70 {
71 let (paddr, level, prop, _perm) = C::item_into_raw_spec(item);
72 let size = page_size::<PagingConsts>(level);
73 if self.query(paddr, size, prop) {
74 let r = self.query_range();
75 Some(r.start as Vaddr..r.end as Vaddr)
76 } else {
77 None
78 }
79 }
80
81 pub open spec fn jump_spec(self, va: usize) -> Self {
83 CursorView { cur_va: va as Vaddr, ..self }
84 }
85
86 pub open spec fn align_up_spec(self, size: usize) -> Vaddr {
93 (nat_align_down(self.cur_va as nat, size as nat) + size as nat) as Vaddr
94 }
95
96 pub open spec fn split_index(m: Mapping, new_size: usize, n: usize) -> Mapping {
97 Mapping {
98 va_range: m.va_range.start + n * new_size..m.va_range.start + (n + 1) * new_size,
99 pa_range: (m.pa_range.start + n * new_size) as usize..(m.pa_range.start + (n + 1)
100 * new_size) as usize,
101 page_size: new_size,
102 property: m.property,
103 }
104 }
105
106 pub open spec fn split_if_mapped_huge_spec(self, new_size: usize) -> Self {
107 let m = self.query_mapping();
108 let size = m.page_size;
109 let new_mappings = Set::<int>::range(0int, (size / new_size) as int).map(
110 |n: int| Self::split_index(m, new_size, n as usize),
111 );
112 CursorView { cur_va: self.cur_va, mappings: self.mappings - set![m] + new_mappings, ..self }
113 }
114
115 pub open spec fn split_while_huge(self, size: usize) -> Self
116 decreases self.query_mapping().page_size,
117 when self.inv()
118 {
119 if self.present() {
120 let m = self.query_mapping();
121 if m.page_size > size {
122 let new_size = m.page_size / NR_ENTRIES;
123 let new_self = self.split_if_mapped_huge_spec(new_size);
124 proof {
125 let f = self.mappings.filter(
126 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
127 );
128 vstd::set::lemma_set_choose_len(f);
129 assert(self.mappings.contains(m));
130 assert(m.inv());
131 assert(m.page_size % (m.page_size / 512usize) == 0) by {
132 if m.page_size == 4096 {
133 assert(4096usize % (4096usize / 512usize) == 0) by (compute_only);
134 } else if m.page_size == 2097152 {
135 assert(2097152usize % (2097152usize / 512usize) == 0) by (compute_only);
136 } else {
137 assert(1073741824usize % (1073741824usize / 512usize) == 0)
138 by (compute_only);
139 }
140 };
141 Self::split_if_mapped_huge_spec_preserves_present(self, new_size);
142 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
143 }
144 new_self.split_while_huge(size)
145 } else {
146 self
147 }
148 } else {
149 self
150 }
151 }
152
153 pub open spec fn remove_subtree(self, size: usize) -> Set<Mapping> {
154 let start = nat_align_down(self.cur_va as nat, size as nat) as Vaddr;
155 let subtree = self.mappings.filter(|m: Mapping| start <= m.va_range.start < start + size);
156 self.mappings - subtree
157 }
158
159 pub open spec fn map_spec(self, paddr: Paddr, size: usize, prop: PageProperty) -> Self {
163 let new = Mapping {
164 va_range: self.cur_slot_range(size),
165 pa_range: paddr..(paddr + size) as usize,
166 page_size: size,
167 property: prop,
168 };
169 let split_self = self.split_while_huge(size);
170 CursorView {
171 cur_va: split_self.align_up_spec(size),
172 mappings: split_self.remove_subtree(size) + set![new],
173 ..split_self
174 }
175 }
176
177 pub open spec fn map_simple(self, paddr: Paddr, size: usize, prop: PageProperty) -> Self {
178 let new = Mapping {
179 va_range: self.cur_slot_range(size),
180 pa_range: paddr..(paddr + size) as usize,
181 page_size: size,
182 property: prop,
183 };
184 CursorView { cur_va: self.cur_va, mappings: self.mappings + set![new], ..self }
185 }
186
187 pub open spec fn unmap_spec(self, len: usize, new_view: Self, num_unmapped: usize) -> bool {
196 let start = self.cur_va;
197 let end = (self.cur_va + len) as Vaddr;
198 &&& new_view.cur_va
200 >= end
201 &&& forall|m: Mapping| #[trigger]
205 self.mappings.contains(m) && (m.va_range.end <= start || m.va_range.start >= end)
206 ==> new_view.mappings.contains(
207 m,
208 )
209 &&& forall|m: Mapping|
214 new_view.mappings.contains(m) && start <= m.va_range.start < end ==> exists|
215 parent: Mapping,
216 | #[trigger]
217 self.mappings.contains(parent) && parent.va_range.start < start
218 && parent.va_range.start <= m.va_range.start && m.va_range.end
219 <= parent.va_range.end && m.pa_range.start == (parent.pa_range.start + (
220 m.va_range.start - parent.va_range.start)) as Paddr && m.property
221 == parent.property
222 &&& forall|m: Mapping| #[trigger]
225 new_view.mappings.contains(m) ==> self.mappings.contains(m) || exists|parent: Mapping|
226 #[trigger]
227 self.mappings.contains(parent) && parent.va_range.start <= m.va_range.start
228 && m.va_range.end <= parent.va_range.end && m.pa_range.start == (
229 parent.pa_range.start + (m.va_range.start - parent.va_range.start)) as Paddr
230 && m.property == parent.property
231 }
232}
233
234}