1use vstd::prelude::*;
2use vstd::set::{axiom_set_choose_len, axiom_set_intersect_finite};
3use vstd::set_lib::*;
4
5use vstd_extra::ghost_tree::*;
6use vstd_extra::ownership::*;
7
8use crate::mm::page_prop::PageProperty;
9use crate::mm::page_table::*;
10use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr};
11use crate::specs::arch::mm::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
12use crate::specs::arch::paging_consts::PagingConsts;
13use crate::specs::mm::page_table::cursor::owners::*;
14use crate::specs::mm::page_table::owners::PageTableOwner;
15use crate::specs::mm::page_table::Mapping;
16use vstd_extra::arithmetic::*;
17
18use crate::mm::page_table::page_size_spec as page_size;
19
20verus! {
21
22impl<C: PageTableConfig> CursorView<C> {
23
24 pub proof fn split_if_mapped_huge_spec_preserves_present(v: Self, new_size: usize)
28 requires
29 v.inv(),
30 v.present(),
31 new_size > 0,
32 v.query_mapping().page_size > 0,
33 v.query_mapping().page_size % new_size == 0,
34 ensures
35 v.split_if_mapped_huge_spec(new_size).present(),
36 {
37 let cur_va = v.cur_va;
38 let m = v.query_mapping();
39 let ps = m.page_size;
40
41 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
42 let f = v.mappings.filter(|m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end);
43 assert(f.finite()) by {
44 vstd::set::axiom_set_intersect_finite::<Mapping>(
45 v.mappings,
46 Set::new(|m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end));
47 };
48 vstd::set::axiom_set_choose_len(f);
49 };
50 assert(m.inv());
51 assert(m.va_range.start + ps == m.va_range.end);
52
53 let diff: int = cur_va as int - m.va_range.start as int;
54 let ki: int = diff / new_size as int;
55 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(diff, new_size as int);
56 vstd::arithmetic::div_mod::lemma_mod_division_less_than_divisor(diff, new_size as int);
57 vstd::arithmetic::div_mod::lemma_div_pos_is_pos(diff, new_size as int);
58
59 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, new_size as int);
60 assert(ki < ps as int / new_size as int) by {
61 if ki >= ps as int / new_size as int {
62 vstd::arithmetic::mul::lemma_mul_inequality(
63 ps as int / new_size as int, ki, new_size as int);
64 }
65 };
66
67 let sub = Self::split_index(m, new_size, ki as usize);
68
69 assert(ki * (new_size as int) >= 0) by {
70 vstd::arithmetic::mul::lemma_mul_nonnegative(ki, new_size as int);
71 };
72 assert((ki + 1) * (new_size as int) <= ps as int) by {
73 vstd::arithmetic::mul::lemma_mul_inequality(
74 ki + 1, ps as int / new_size as int, new_size as int);
75 };
76 assert(m.va_range.start as int + (ki + 1) * (new_size as int)
77 <= (m.va_range.end as int)) by {
78 vstd::arithmetic::mul::lemma_mul_is_commutative(ki + 1, new_size as int);
79 vstd::arithmetic::mul::lemma_mul_is_commutative(
80 ps as int / new_size as int, new_size as int);
81 };
82
83 assert(ki as usize as int == ki);
84 vstd::arithmetic::mul::lemma_mul_is_distributive_add(new_size as int, ki, 1 as int);
85 assert((cur_va as int) >= (m.va_range.start as int) + ki * (new_size as int));
86 assert((cur_va as int) < (m.va_range.start as int) + (ki + 1) * (new_size as int));
87 assert(sub.va_range.start <= cur_va);
88 assert(cur_va < sub.va_range.end);
89
90 let new_self = v.split_if_mapped_huge_spec(new_size);
91 let domain = Set::<int>::new(|n:int| 0 <= n < ps as int / new_size as int);
92 assert(domain.contains(ki));
93 assert(new_self.mappings.contains(sub));
94
95 let new_filter = new_self.mappings.filter(
96 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end);
97 assert(new_filter.contains(sub));
98 assert(new_self.mappings.finite()) by {
99 vstd::set::axiom_set_remove_finite(v.mappings, m);
100 let domain = Set::<int>::new(|n:int| 0 <= n < ps as int / new_size as int);
101 assert(domain =~= int::range_set(0int, ps as int / new_size as int));
102 vstd::set_lib::range_set_properties::<int>(0int, ps as int / new_size as int);
103 domain.lemma_map_finite(|n:int| Self::split_index(m, new_size, n as usize));
104 vstd::set::axiom_set_union_finite(
105 v.mappings.remove(m),
106 domain.map(|n:int| Self::split_index(m, new_size, n as usize)));
107 };
108 assert(new_filter.finite()) by {
109 vstd::set::axiom_set_intersect_finite::<Mapping>(
110 new_self.mappings,
111 Set::new(|m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end));
112 };
113 vstd::set::axiom_set_contains_len(new_filter, sub);
114 }
115
116 pub proof fn split_if_mapped_huge_spec_decreases_page_size(v: Self, new_size: usize)
123 requires
124 v.inv(),
125 v.present(),
126 new_size > 0,
127 v.query_mapping().page_size > new_size,
128 v.query_mapping().page_size % new_size == 0,
129 ensures
130 v.split_if_mapped_huge_spec(new_size).present(),
131 v.split_if_mapped_huge_spec(new_size).query_mapping().page_size < v.query_mapping().page_size,
132 {
133 Self::split_if_mapped_huge_spec_preserves_present(v, new_size);
134
135 let cur_va = v.cur_va;
136 let m = v.query_mapping();
137 let new_self = v.split_if_mapped_huge_spec(new_size);
138 let m2 = new_self.query_mapping();
139 let ps = m.page_size;
140
141 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
142 let f = v.mappings.filter(
143 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end);
144 assert(f.finite()) by {
145 vstd::set::axiom_set_intersect_finite::<Mapping>(
146 v.mappings,
147 Set::new(|m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end));
148 };
149 vstd::set::axiom_set_choose_len(f);
150 };
151
152 assert(new_self.mappings.contains(m2)
153 && m2.va_range.start <= cur_va && cur_va < m2.va_range.end) by {
154 let f = new_self.mappings.filter(
155 |m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end);
156 assert(new_self.mappings.finite()) by {
157 vstd::set::axiom_set_remove_finite(v.mappings, m);
158 let domain = Set::<int>::new(|n:int| 0 <= n < ps as int / new_size as int);
159 assert(domain =~= int::range_set(0int, ps as int / new_size as int));
160 vstd::set_lib::range_set_properties::<int>(0int, ps as int / new_size as int);
161 domain.lemma_map_finite(|n:int| Self::split_index(m, new_size, n as usize));
162 vstd::set::axiom_set_union_finite(
163 v.mappings.remove(m),
164 domain.map(|n:int| Self::split_index(m, new_size, n as usize)));
165 };
166 assert(f.finite()) by {
167 vstd::set::axiom_set_intersect_finite::<Mapping>(
168 new_self.mappings,
169 Set::new(|m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end));
170 };
171 vstd::set::axiom_set_choose_len(f);
172 };
173
174 if v.mappings.contains(m2) && m2 != m {
175 assert(m.va_range.end <= m2.va_range.start || m2.va_range.end <= m.va_range.start);
176 assert(false);
177 }
178
179 assert(!v.mappings.remove(m).contains(m2));
180 let new_mappings = Set::<int>::new(
181 |n:int| 0 <= n < ps as int / new_size as int
182 ).map(|n:int| Self::split_index(m, new_size, n as usize));
183 assert(new_mappings.contains(m2));
184 let k = choose|k: int| 0 <= k < ps as int / new_size as int
185 && #[trigger] Self::split_index(m, new_size, k as usize) == m2;
186 assert(m2.page_size == new_size);
187 }
188
189 pub proof fn split_if_mapped_huge_spec_preserves_inv(v: Self, new_size: usize)
195 requires
196 v.inv(),
197 v.present(),
198 new_size > 0,
199 v.query_mapping().page_size > new_size,
200 v.query_mapping().page_size % new_size == 0,
201 set![4096usize, 2097152, 1073741824].contains(new_size),
202 ensures
203 v.split_if_mapped_huge_spec(new_size).inv(),
204 {
205 let cur_va = v.cur_va;
206 let m = v.query_mapping();
207 let ps = m.page_size;
208 let ns: int = new_size as int;
209 let new_self = v.split_if_mapped_huge_spec(new_size);
210 let count: int = ps as int / ns;
211 let domain = Set::<int>::new(|n: int| 0 <= n < count);
212 let new_mappings = domain.map(|n: int| Self::split_index(m, new_size, n as usize));
213
214 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
216 let f = v.mappings.filter(|m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end);
217 assert(f.finite()) by {
218 vstd::set::axiom_set_intersect_finite::<Mapping>(
219 v.mappings,
220 Set::new(|m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end));
221 };
222 vstd::set::axiom_set_choose_len(f);
223 };
224 assert(m.inv());
225
226 assert(new_self.mappings.finite()) by {
230 vstd::set::axiom_set_remove_finite(v.mappings, m);
231 assert(domain =~= int::range_set(0int, count));
232 vstd::set_lib::range_set_properties::<int>(0int, count);
233 domain.lemma_map_finite(|n: int| Self::split_index(m, new_size, n as usize));
234 vstd::set::axiom_set_union_finite(
235 v.mappings.remove(m), new_mappings);
236 };
237
238 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, ns);
240 assert(ps as int == count * ns);
241
242 assert(m.va_range.start % new_size as int == 0) by {
243 vstd::arithmetic::mul::lemma_mul_is_commutative(count, ns);
244 vstd::arithmetic::div_mod::lemma_mod_mod(
245 m.va_range.start as int, ns, count);
246 };
247 assert(m.pa_range.start % new_size == 0) by {
248 vstd::arithmetic::mul::lemma_mul_is_commutative(count, ns);
249 vstd::arithmetic::div_mod::lemma_mod_mod(
250 m.pa_range.start as int, ns, count);
251 };
252
253 assert forall|e: Mapping| new_self.mappings.contains(e) implies #[trigger] e.inv() by {
255 if v.mappings.remove(m).contains(e) {
256 assert(v.mappings.contains(e));
257 } else {
258 assert(new_mappings.contains(e));
259 let k = choose|k: int| 0 <= k < count
260 && #[trigger] Self::split_index(m, new_size, k as usize) == e;
261 let sub = Self::split_index(m, new_size, k as usize);
262
263 assert(set![4096usize, 2097152, 1073741824].contains(sub.page_size));
265
266 vstd::arithmetic::mul::lemma_mul_is_commutative(k, ns);
269 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
270 k, m.va_range.start as int, ns);
271 assert(sub.va_range.start % new_size as int == 0);
272 vstd::arithmetic::mul::lemma_mul_is_commutative(k + 1, ns);
273 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
274 k + 1, m.va_range.start as int, ns);
275 assert(sub.va_range.end % new_size as int == 0);
276
277 vstd::arithmetic::mul::lemma_mul_is_commutative(k, ns);
278 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
279 k, m.pa_range.start as int, ns);
280 assert(sub.pa_range.start % new_size == 0);
281 vstd::arithmetic::mul::lemma_mul_is_commutative(k + 1, ns);
282 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
283 k + 1, m.pa_range.start as int, ns);
284 assert(sub.pa_range.end % new_size == 0);
285
286 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, k, 1int);
288 assert(sub.va_range.start + new_size == sub.va_range.end);
289 assert(sub.pa_range.start + new_size == sub.pa_range.end);
290
291 vstd::arithmetic::mul::lemma_mul_nonnegative(k, ns);
293 vstd::arithmetic::mul::lemma_mul_inequality(k + 1, count, ns);
294 assert(sub.va_range.start >= m.va_range.start);
296 assert(sub.va_range.end <= m.va_range.end);
297 assert(sub.va_range.start <= sub.va_range.end);
298
299 assert(sub.pa_range.start >= m.pa_range.start);
300 assert(sub.pa_range.end <= m.pa_range.end);
301 assert(sub.pa_range.start <= sub.pa_range.end);
302 }
303 };
304
305 assert forall|e1: Mapping, e2: Mapping|
307 #[trigger] new_self.mappings.contains(e1) &&
308 #[trigger] new_self.mappings.contains(e2) &&
309 e1 != e2
310 implies
311 e1.va_range.end <= e2.va_range.start || e2.va_range.end <= e1.va_range.start
312 by {
313 if v.mappings.remove(m).contains(e1) && v.mappings.remove(m).contains(e2) {
314 assert(v.mappings.contains(e1));
316 assert(v.mappings.contains(e2));
317 } else if v.mappings.remove(m).contains(e1) && new_mappings.contains(e2) {
318 assert(v.mappings.contains(e1));
320 assert(e1 != m);
321 let k2 = choose|k: int| 0 <= k < count
322 && #[trigger] Self::split_index(m, new_size, k as usize) == e2;
323 vstd::arithmetic::mul::lemma_mul_nonnegative(k2, ns);
324 vstd::arithmetic::mul::lemma_mul_inequality(k2 + 1, count, ns);
325 assert(e2.va_range.start >= m.va_range.start);
326 assert(e2.va_range.end <= m.va_range.end);
327 } else if new_mappings.contains(e1) && v.mappings.remove(m).contains(e2) {
328 assert(v.mappings.contains(e2));
330 assert(e2 != m);
331 let k1 = choose|k: int| 0 <= k < count
332 && #[trigger] Self::split_index(m, new_size, k as usize) == e1;
333 vstd::arithmetic::mul::lemma_mul_nonnegative(k1, ns);
334 vstd::arithmetic::mul::lemma_mul_inequality(k1 + 1, count, ns);
335 assert(e1.va_range.start >= m.va_range.start);
336 assert(e1.va_range.end <= m.va_range.end);
337 } else if new_mappings.contains(e1) && new_mappings.contains(e2) {
338 let i = choose|k: int| 0 <= k < count
340 && #[trigger] Self::split_index(m, new_size, k as usize) == e1;
341 let j = choose|k: int| 0 <= k < count
342 && #[trigger] Self::split_index(m, new_size, k as usize) == e2;
343 vstd::arithmetic::mul::lemma_mul_nonnegative(i, ns);
344 vstd::arithmetic::mul::lemma_mul_nonnegative(j, ns);
345 if i < j {
346 vstd::arithmetic::mul::lemma_mul_inequality(i + 1, j, ns);
347 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, i, 1int);
348 } else {
349 vstd::arithmetic::mul::lemma_mul_inequality(j + 1, i, ns);
350 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, j, 1int);
351 }
352 }
353 };
354 }
355
356 pub broadcast proof fn lemma_split_while_huge_preserves_cur_va(self, size: usize)
358 requires self.inv(), size >= PAGE_SIZE,
359 ensures #[trigger] self.split_while_huge(size).cur_va == self.cur_va
360 decreases if self.present() { self.query_mapping().page_size as int } else { 0 }
361 {
362 if self.present() {
363 let m = self.query_mapping();
364 if m.page_size > size {
365 let new_size = m.page_size / NR_ENTRIES;
366 let new_self = self.split_if_mapped_huge_spec(new_size);
367 let f = self.mappings.filter(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end);
369 vstd::set::axiom_set_intersect_finite::<Mapping>(
370 self.mappings, Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end));
371 vstd::set::axiom_set_choose_len(f);
372 assert(m.inv());
373 assert(NR_ENTRIES == 512usize) by (compute_only);
374 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
376 if m.page_size == 2097152 { assert(2097152usize / 512 == 4096usize); }
377 else if m.page_size == 1073741824 { assert(1073741824usize / 512 == 2097152usize); }
378 else { assert(4096usize / 512 == 8usize); assert(false); } };
380 assert(m.page_size % new_size == 0) by {
381 if m.page_size == 2097152 { assert(2097152usize % 4096 == 0); }
382 else { assert(1073741824usize % 2097152 == 0); }
383 };
384 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
385
386 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
387 Self::lemma_split_while_huge_preserves_cur_va(new_self, size);
388 }
389 }
390 }
391
392 pub proof fn lemma_split_while_huge_preserves_inv(self, size: usize)
394 requires self.inv(), size >= PAGE_SIZE,
395 ensures self.split_while_huge(size).inv(),
396 decreases if self.present() { self.query_mapping().page_size as int } else { 0 }
397 {
398 if self.present() {
399 let m = self.query_mapping();
400 if m.page_size > size {
401 let new_size = m.page_size / NR_ENTRIES;
402 let new_self = self.split_if_mapped_huge_spec(new_size);
403 let f = self.mappings.filter(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end);
405 vstd::set::axiom_set_intersect_finite::<Mapping>(
406 self.mappings, Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end));
407 vstd::set::axiom_set_choose_len(f);
408 assert(m.inv());
409 assert(NR_ENTRIES == 512usize) by (compute_only);
410 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
411 if m.page_size == 2097152 { assert(2097152usize / 512 == 4096usize); }
412 else if m.page_size == 1073741824 { assert(1073741824usize / 512 == 2097152usize); }
413 else { assert(4096usize / 512 == 8usize); assert(false); }
414 };
415 assert(m.page_size % new_size == 0) by {
416 if m.page_size == 2097152 { assert(2097152usize % 4096 == 0); }
417 else { assert(1073741824usize % 2097152 == 0); }
418 };
419 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
420 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
421 new_self.lemma_split_while_huge_preserves_inv(size);
422 }
423 }
424 }
425
426 pub proof fn split_while_huge_compose(self, s1: usize, s2: usize)
430 requires
431 self.inv(),
432 s1 >= PAGE_SIZE,
433 s2 <= s1,
434 ensures
435 self.split_while_huge(s2) == self.split_while_huge(s1).split_while_huge(s2),
436 decreases if self.present() { self.query_mapping().page_size as int } else { 0 },
437 {
438 if !self.present() {
439 return;
440 }
441 let m = self.query_mapping();
442 if m.page_size <= s1 {
443 return;
444 }
445 let new_size = m.page_size / NR_ENTRIES;
446 let f = self.mappings.filter(
447 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end);
448 vstd::set::axiom_set_intersect_finite::<Mapping>(
449 self.mappings,
450 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end));
451 vstd::set::axiom_set_choose_len(f);
452 assert(m.inv());
453 assert(NR_ENTRIES == 512usize) by (compute_only);
454 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
455 if m.page_size == 2097152 { assert(2097152usize / 512 == 4096usize); }
456 else { assert(1073741824usize / 512 == 2097152usize); }
457 };
458 assert(m.page_size % new_size == 0) by {
459 if m.page_size == 2097152 { assert(2097152usize % 4096 == 0); }
460 else { assert(1073741824usize % 2097152 == 0); }
461 };
462 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
463 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
464 self.split_if_mapped_huge_spec(new_size).split_while_huge_compose(s1, s2);
465 }
466
467 pub proof fn split_while_huge_idempotent(self, size: usize)
470 requires
471 self.inv(),
472 size >= PAGE_SIZE,
473 ensures
474 self.split_while_huge(size).split_while_huge(size) == self.split_while_huge(size),
475 {
476 self.split_while_huge_compose(size, size);
477 }
478
479 pub proof fn split_while_huge_noop_implies_page_size_le(self, size: usize)
482 requires
483 self.inv(),
484 size >= PAGE_SIZE,
485 self.split_while_huge(size) == self,
486 self.present(),
487 ensures
488 self.query_mapping().page_size <= size,
489 {
490 let m = self.query_mapping();
491 if m.page_size > size {
492 let new_size = m.page_size / NR_ENTRIES;
493 let f = self.mappings.filter(
494 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end);
495 vstd::set::axiom_set_intersect_finite::<Mapping>(
496 self.mappings,
497 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end));
498 vstd::set::axiom_set_choose_len(f);
499 assert(m.inv());
500 assert(NR_ENTRIES == 512usize) by (compute_only);
501 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
502 if m.page_size == 2097152 { assert(2097152usize / 512 == 4096usize); }
503 else if m.page_size == 1073741824 { assert(1073741824usize / 512 == 2097152usize); }
504 else { assert(4096usize / 512 == 8usize); assert(false); }
505 };
506 assert(m.page_size % new_size == 0) by {
507 if m.page_size == 2097152 { assert(2097152usize % 4096 == 0); }
508 else { assert(1073741824usize % 2097152 == 0); }
509 };
510 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
511 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
512 let new_self = self.split_if_mapped_huge_spec(new_size);
513 new_self.split_while_huge_refinement(size, m);
514 assert(!new_self.mappings.contains(m)) by {
515 let new_mappings = Set::<int>::new(
516 |n: int| 0 <= n < m.page_size as int / new_size as int
517 ).map(|n: int| Self::split_index(m, new_size, n as usize));
518 if new_mappings.contains(m) {
519 let k = choose|k: int|
520 0 <= k < m.page_size as int / new_size as int
521 && #[trigger] Self::split_index(m, new_size, k as usize) == m;
522 }
523 };
524 let p = choose |p: Mapping| #[trigger] new_self.mappings.contains(p)
525 && p.va_range.start <= m.va_range.start
526 && m.va_range.end <= p.va_range.end
527 && m.pa_range.start == (p.pa_range.start + (m.va_range.start - p.va_range.start)) as Paddr
528 && m.property == p.property;
529 if self.mappings.contains(p) {
530 assert(p.va_range.start <= self.cur_va < p.va_range.end);
531 } else {
532 let new_mappings = Set::<int>::new(
533 |n: int| 0 <= n < m.page_size as int / new_size as int
534 ).map(|n: int| Self::split_index(m, new_size, n as usize));
535 let k = choose|k: int|
536 0 <= k < m.page_size as int / new_size as int
537 && #[trigger] Self::split_index(m, new_size, k as usize) == p;
538 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(
539 m.page_size as int, new_size as int);
540 vstd::arithmetic::mul::lemma_mul_inequality(
541 (k + 1) as int, m.page_size as int / new_size as int, new_size as int);
542 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
543 new_size as int, k, 1int);
544 }
545 }
546 }
547
548 pub proof fn split_while_huge_one_step(self, size: usize)
558 requires
559 self.inv(),
560 self.present(),
561 self.query_mapping().page_size > size,
562 self.query_mapping().page_size / NR_ENTRIES == size,
563 self.query_mapping().page_size % size == 0,
564 set![4096usize, 2097152, 1073741824].contains(size),
565 ensures
566 self.split_while_huge(size).mappings
567 =~= self.split_if_mapped_huge_spec(size).mappings,
568 {
569 let m = self.query_mapping();
570 let new_size = m.page_size / NR_ENTRIES;
571 let f0 = self.mappings.filter(
572 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end);
573 vstd::set::axiom_set_intersect_finite::<Mapping>(
574 self.mappings,
575 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end));
576 vstd::set::axiom_set_choose_len(f0);
577 assert(m.inv());
578 assert(NR_ENTRIES == 512usize) by (compute_only);
579 Self::split_if_mapped_huge_spec_preserves_present(self, new_size);
580 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
581 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
582 let new_self = self.split_if_mapped_huge_spec(new_size);
583
584 assert(new_self.query_mapping().page_size == new_size) by {
585 let new_m = new_self.query_mapping();
586 let f = new_self.mappings.filter(
587 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end);
588 vstd::set::axiom_set_intersect_finite::<Mapping>(
589 new_self.mappings,
590 Set::new(|m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end));
591 vstd::set::axiom_set_choose_len(f);
592 if self.mappings.contains(new_m) && new_m != m {
593 assert(false);
594 }
595 let new_mappings = Set::<int>::new(
596 |n: int| 0 <= n < m.page_size as int / new_size as int
597 ).map(|n: int| Self::split_index(m, new_size, n as usize));
598 assert(new_mappings.contains(new_m));
599 };
600 assert(new_self.split_while_huge(size) == new_self);
601 }
602
603 pub proof fn split_if_mapped_huge_spec_locality(self, new_size: usize, m2: Mapping)
606 requires
607 self.inv(),
608 self.present(),
609 new_size > 0,
610 self.query_mapping().page_size % new_size == 0,
611 Mapping::disjoint_vaddrs(m2, self.query_mapping()),
612 ensures
613 self.split_if_mapped_huge_spec(new_size).mappings.contains(m2)
614 == self.mappings.contains(m2),
615 {
616 let m = self.query_mapping();
617 let size = m.page_size;
618 let new_mappings = Set::<int>::new(|n: int| 0 <= n < size / new_size)
619 .map(|n: int| Self::split_index(m, new_size, n as usize));
620
621 let f = self.mappings.filter(
623 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end);
624 assert(f.finite()) by {
625 vstd::set::axiom_set_intersect_finite::<Mapping>(
626 self.mappings,
627 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end));
628 };
629 vstd::set::axiom_set_choose_len(f);
630 assert(m.inv());
631
632 assert(!new_mappings.contains(m2)) by {
633 if new_mappings.contains(m2) {
634 let k = choose|k: int| 0 <= k < size as int / new_size as int
635 && #[trigger] Self::split_index(m, new_size, k as usize) == m2;
636 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(
637 size as int, new_size as int);
638 vstd::arithmetic::mul::lemma_mul_inequality(
639 (k + 1) as int, size as int / new_size as int, new_size as int);
640 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
641 new_size as int, k, 1int);
642 vstd::arithmetic::mul::lemma_mul_nonnegative(k, new_size as int);
643 }
644 };
645 }
646
647 #[verifier::rlimit(80)]
654 pub proof fn split_while_huge_locality(self, size: usize, m2: Mapping)
655 requires
656 self.inv(),
657 size >= PAGE_SIZE,
658 self.mappings.contains(m2),
659 !(m2.va_range.start <= self.cur_va < m2.va_range.end),
660 ensures
661 self.split_while_huge(size).mappings.contains(m2),
662 decreases if self.present() { self.query_mapping().page_size as int } else { 0 },
663 {
664 if self.present() {
665 let m = self.query_mapping();
666 if m.page_size > size {
667 let new_size = m.page_size / NR_ENTRIES;
668 let f = self.mappings.filter(
670 |m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end);
671 assert(f.finite()) by {
672 vstd::set::axiom_set_intersect_finite::<Mapping>(
673 self.mappings,
674 Set::new(|m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end));
675 };
676 vstd::set::axiom_set_choose_len(f);
677 assert(self.mappings.contains(m));
678 assert(m.va_range.start <= self.cur_va < m.va_range.end);
679 assert(m.inv());
680 assert(Mapping::disjoint_vaddrs(m2, m));
682 assert(NR_ENTRIES == 512usize);
684 assert(m.page_size % new_size == 0) by {
685 if m.page_size == 4096 { assert(4096usize % (4096usize / 512usize) == 0); }
686 else if m.page_size == 2097152 { assert(2097152usize % (2097152usize / 512usize) == 0); }
687 else { assert(1073741824usize % (1073741824usize / 512usize) == 0); }
688 };
689 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
690 if m.page_size == 2097152 { assert(2097152usize / 512 == 4096usize); }
691 else if m.page_size == 1073741824 { assert(1073741824usize / 512 == 2097152usize); }
692 else { assert(4096usize / 512 == 8usize); assert(false); }
693 };
694 self.split_if_mapped_huge_spec_locality(new_size, m2);
695 let new_self = self.split_if_mapped_huge_spec(new_size);
696 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
697 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
698 new_self.split_while_huge_locality(size, m2);
699 }
700 }
701 }
702
703 #[verifier::rlimit(120)]
711 pub proof fn split_while_huge_locality_absent(self, size: usize, m2: Mapping)
712 requires
713 self.inv(),
714 size >= PAGE_SIZE,
715 !self.mappings.contains(m2),
716 self.present() ==> Mapping::disjoint_vaddrs(m2, self.query_mapping()),
717 ensures
718 !self.split_while_huge(size).mappings.contains(m2),
719 decreases if self.present() { self.query_mapping().page_size as int } else { 0 },
720 {
721 if self.present() {
722 let m = self.query_mapping();
723 if m.page_size > size {
724 let new_size = m.page_size / NR_ENTRIES;
725 let f = self.mappings.filter(
727 |m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end);
728 assert(f.finite()) by {
729 vstd::set::axiom_set_intersect_finite::<Mapping>(
730 self.mappings,
731 Set::new(|m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end));
732 };
733 vstd::set::axiom_set_choose_len(f);
734 assert(self.mappings.contains(m));
735 assert(m.inv());
737 assert(m.page_size % new_size == 0) by {
738 assert(set![4096usize, 2097152usize, 1073741824usize].contains(m.page_size));
739 assert(4096usize % (4096usize / 512usize) == 0) by (compute_only);
740 assert(2097152usize % (2097152usize / 512usize) == 0) by (compute_only);
741 assert(1073741824usize % (1073741824usize / 512usize) == 0) by (compute_only);
742 };
743 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
744 if m.page_size == 2097152 { assert(2097152usize / 512 == 4096usize); }
745 else if m.page_size == 1073741824 { assert(1073741824usize / 512 == 2097152usize); }
746 else { assert(4096usize / 512 == 8usize); assert(false); }
747 };
748 self.split_if_mapped_huge_spec_locality(new_size, m2);
749 let new_self = self.split_if_mapped_huge_spec(new_size);
750 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
751 Self::split_if_mapped_huge_spec_preserves_present(self, new_size);
752 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
753 assert(new_self.present() ==>
754 Mapping::disjoint_vaddrs(m2, new_self.query_mapping())) by {
755 if new_self.present() {
756 let new_m = new_self.query_mapping();
757 let nf = new_self.mappings.filter(
758 |m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end);
759 vstd::set::axiom_set_intersect_finite::<Mapping>(
760 new_self.mappings,
761 Set::new(|m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end));
762 vstd::set::axiom_set_choose_len(nf);
763 if self.mappings.contains(new_m) && new_m != m {
764 assert(false);
765 }
766 let new_mappings = Set::<int>::new(
767 |n: int| 0 <= n < m.page_size as int / new_size as int
768 ).map(|n: int| Self::split_index(m, new_size, n as usize));
769 let k = choose|k: int|
770 0 <= k < m.page_size as int / new_size as int
771 && #[trigger] Self::split_index(m, new_size, k as usize) == new_m;
772 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(
773 m.page_size as int, new_size as int);
774 vstd::arithmetic::mul::lemma_mul_inequality(
775 (k + 1) as int, m.page_size as int / new_size as int, new_size as int);
776 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
777 new_size as int, k, 1int);
778 vstd::arithmetic::mul::lemma_mul_nonnegative(k, new_size as int);
779 }
780 };
781 new_self.split_while_huge_locality_absent(size, m2);
782 }
783 }
784 }
785
786 pub proof fn split_if_mapped_huge_spec_refinement(self, new_size: usize, e: Mapping)
791 requires
792 self.inv(),
793 self.present(),
794 new_size > 0,
795 self.query_mapping().page_size > new_size,
796 self.query_mapping().page_size % new_size == 0,
797 self.split_if_mapped_huge_spec(new_size).mappings.contains(e),
798 ensures
799 self.mappings.contains(e)
800 || {
801 let parent = self.query_mapping();
802 &&& self.mappings.contains(parent)
803 &&& parent.va_range.start <= e.va_range.start
804 &&& e.va_range.end <= parent.va_range.end
805 &&& e.pa_range.start == (parent.pa_range.start + (e.va_range.start - parent.va_range.start)) as Paddr
806 &&& e.property == parent.property
807 },
808 {
809 let qm = self.query_mapping();
810 let ps = qm.page_size;
811 let ns: int = new_size as int;
812 let count: int = ps as int / ns;
813 let new_self = self.split_if_mapped_huge_spec(new_size);
814 let domain = Set::<int>::new(|n: int| 0 <= n < count);
815 let new_mappings = domain.map(|n: int| Self::split_index(qm, new_size, n as usize));
816
817 let f = self.mappings.filter(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end);
819 vstd::set::axiom_set_intersect_finite::<Mapping>(
820 self.mappings,
821 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end));
822 vstd::set::axiom_set_choose_len(f);
823 assert(self.mappings.contains(qm));
824 assert(qm.inv());
825
826 if self.mappings.remove(qm).contains(e) {
827 assert(self.mappings.contains(e));
828 } else {
829 assert(new_mappings.contains(e));
830 let k = choose|k: int| 0 <= k < count
831 && #[trigger] Self::split_index(qm, new_size, k as usize) == e;
832
833 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, ns);
834 assert(ps as int == count * ns);
835
836 vstd::arithmetic::mul::lemma_mul_nonnegative(k, ns);
837 vstd::arithmetic::mul::lemma_mul_inequality(k + 1, count, ns);
838
839 assert(k as usize as int == k);
840 let ku = k as usize;
841 assert(e == Self::split_index(qm, new_size, ku));
842 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, k, 1int);
843
844 assert(e.va_range.start as int == qm.va_range.start as int + k * ns);
845 assert(e.va_range.start >= qm.va_range.start);
846 assert(e.va_range.end as int == qm.va_range.start as int + (k + 1) * ns);
847 assert(e.va_range.end <= qm.va_range.end);
848 assert(e.pa_range.start as int == qm.pa_range.start as int + k * ns);
849 assert(e.va_range.start - qm.va_range.start == k * ns);
850 assert(e.pa_range.start == (qm.pa_range.start + (e.va_range.start - qm.va_range.start)) as Paddr);
851 assert(e.property == qm.property);
852 }
853 }
854
855 pub proof fn split_while_huge_refinement(self, size: usize, m: Mapping)
856 requires
857 self.inv(),
858 size >= PAGE_SIZE,
859 self.split_while_huge(size).mappings.contains(m),
860 ensures
861 self.mappings.contains(m)
862 || exists |parent: Mapping| #[trigger] self.mappings.contains(parent)
863 && parent.va_range.start <= m.va_range.start
864 && m.va_range.end <= parent.va_range.end
865 && m.pa_range.start == (parent.pa_range.start + (m.va_range.start - parent.va_range.start)) as Paddr
866 && m.property == parent.property,
867 decreases if self.present() { self.query_mapping().page_size as int } else { 0 }
868 {
869 if self.present() {
870 let qm = self.query_mapping();
871 if qm.page_size > size {
872 let new_size = qm.page_size / NR_ENTRIES;
873 let new_self = self.split_if_mapped_huge_spec(new_size);
874
875 let f = self.mappings.filter(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end);
876 vstd::set::axiom_set_intersect_finite::<Mapping>(
877 self.mappings,
878 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end));
879 vstd::set::axiom_set_choose_len(f);
880 assert(qm.inv());
881 assert(NR_ENTRIES == 512usize) by (compute_only);
882 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
883 if qm.page_size == 2097152 { assert(2097152usize / 512 == 4096usize); }
884 else if qm.page_size == 1073741824 { assert(1073741824usize / 512 == 2097152usize); }
885 else { assert(4096usize / 512 == 8usize); assert(false); }
886 };
887 assert(qm.page_size % new_size == 0) by {
888 if qm.page_size == 2097152 { assert(2097152usize % 4096 == 0); }
889 else { assert(1073741824usize % 2097152 == 0); }
890 };
891 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
892 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
893
894 new_self.split_while_huge_refinement(size, m);
895
896 if new_self.mappings.contains(m) {
897 self.split_if_mapped_huge_spec_refinement(new_size, m);
898 } else {
899 let p = choose|p: Mapping|
900 #[trigger] new_self.mappings.contains(p)
901 && p.va_range.start <= m.va_range.start
902 && m.va_range.end <= p.va_range.end
903 && m.pa_range.start == (p.pa_range.start + (m.va_range.start - p.va_range.start)) as Paddr
904 && m.property == p.property;
905 self.split_if_mapped_huge_spec_refinement(new_size, p);
906 if !self.mappings.contains(p) {
907 admit();
912 assert(qm.va_range.start <= m.va_range.start);
913 assert(m.va_range.end <= qm.va_range.end);
914 assert(m.pa_range.start == (qm.pa_range.start + (m.va_range.start - qm.va_range.start)) as Paddr);
915 assert(m.property == qm.property);
916 }
917 }
918 }
919 }
920 }
921
922 pub proof fn split_while_huge_disjoint(self, size: usize, other: Set<Mapping>)
932 requires
933 self.inv(),
934 self.mappings.disjoint(other),
935 ensures
936 self.split_while_huge(size).mappings.disjoint(other),
937 { admit() }
938}
939
940
941impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
942
943 proof fn query_mapping_from_subtree(self, qm: Mapping)
948 requires
949 self.inv(),
950 self@.inv(),
951 self@.present(),
952 qm == self@.query_mapping(),
953 ensures
954 PageTableOwner(self.cur_subtree()).view_rec(self.cur_subtree().value.path).contains(qm),
955 {
956 let f = self@.mappings.filter(|m2: Mapping| m2.va_range.start <= self@.cur_va < m2.va_range.end);
957 axiom_set_intersect_finite::<Mapping>(
958 self@.mappings, Set::new(|m2: Mapping| m2.va_range.start <= self@.cur_va < m2.va_range.end));
959 axiom_set_choose_len(f);
960 self.mapping_covering_cur_va_from_cur_subtree(qm);
961 }
962
963 pub proof fn split_while_huge_node_noop(self)
964 requires
965 self.inv(),
966 self.cur_entry_owner().is_node(),
967 self.level > 1,
968 ensures
969 self@.split_while_huge(page_size((self.level - 1) as PagingLevel)) == self@
970 {
971 self.view_preserves_inv();
972 if self@.present() {
973 self.cur_subtree_inv();
974 let subtree = self.cur_subtree();
975 let path = subtree.value.path;
976 let qm = self@.query_mapping();
977 self.query_mapping_from_subtree(qm);
978 let cont = self.continuations[self.level - 1];
979 cont.path().push_tail_property_len(cont.idx as usize);
980 PageTableOwner(subtree).view_rec_node_page_size_bound(path, qm);
981 }
982 }
983
984 pub proof fn split_while_huge_absent_noop(self, size: usize)
987 requires
988 self.inv(),
989 self.cur_entry_owner().is_absent(),
990 ensures
991 self@.split_while_huge(size) == self@,
992 {
993 self.view_preserves_inv();
994 self.cur_entry_absent_not_present();
995 }
996
997 pub proof fn split_while_huge_at_level_noop(self)
998 requires
999 self.inv(),
1000 ensures
1001 self@.split_while_huge(page_size(self.level as PagingLevel)) == self@
1002 {
1003 self.view_preserves_inv();
1004 if self@.present() {
1005 self.cur_subtree_inv();
1006 let subtree = self.cur_subtree();
1007 let path = subtree.value.path;
1008 let qm = self@.query_mapping();
1009 self.query_mapping_from_subtree(qm);
1010 let cont = self.continuations[self.level - 1];
1011 cont.path().push_tail_property_len(cont.idx as usize);
1012 PageTableOwner(subtree).view_rec_page_size_bound(path, qm);
1013 }
1014 }
1015
1016 pub proof fn map_branch_frame_split_while_huge(
1026 self,
1027 owner0: Self,
1028 owner_before_frame: Self,
1029 level_before_frame: int,
1030 )
1031 requires
1032 self.inv(),
1033 owner0.inv(),
1034 owner_before_frame.inv(),
1035 1 <= level_before_frame - 1,
1036 level_before_frame <= NR_LEVELS,
1037 self.level == (level_before_frame - 1) as u8,
1038 owner_before_frame@ == owner0@.split_while_huge(
1039 page_size(level_before_frame as PagingLevel)),
1040 self@ == owner_before_frame@.split_if_mapped_huge_spec(
1041 page_size((level_before_frame - 1) as PagingLevel)),
1042 ensures
1043 self@ == owner0@.split_while_huge(page_size(self.level as PagingLevel))
1044 { admit() }
1045
1046 pub proof fn find_next_split_push_equals_split_while_huge(
1049 self,
1050 old_view: CursorView<C>,
1051 )
1052 requires
1053 self.inv(),
1054 old_view.inv(),
1055 self.cur_entry_owner().is_frame(),
1056 self@.cur_va == old_view.cur_va,
1057 old_view.present(),
1058 old_view.query_mapping().page_size > page_size(self.level as PagingLevel),
1059 old_view.query_mapping().page_size / NR_ENTRIES
1060 == page_size(self.level as PagingLevel),
1061 old_view.query_mapping().page_size
1062 % page_size(self.level as PagingLevel) == 0,
1063 self@.mappings =~= old_view.split_if_mapped_huge_spec(
1064 page_size(self.level as PagingLevel)).mappings,
1065 ensures
1066 self@.mappings =~= old_view.split_while_huge(
1067 page_size(self.level as PagingLevel)).mappings,
1068 {
1069 let ps = page_size(self.level as PagingLevel);
1070 let m = old_view.query_mapping();
1071 let f = old_view.mappings.filter(
1072 |m2: Mapping| m2.va_range.start <= old_view.cur_va < m2.va_range.end);
1073 vstd::set::axiom_set_intersect_finite::<Mapping>(
1074 old_view.mappings,
1075 Set::new(|m2: Mapping| m2.va_range.start <= old_view.cur_va < m2.va_range.end));
1076 vstd::set::axiom_set_choose_len(f);
1077 assert(m.inv());
1078 assert(NR_ENTRIES == 512usize) by (compute_only);
1079 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_spec_values();
1080 assert(set![4096usize, 2097152, 1073741824].contains(ps)) by {
1081 if m.page_size == 2097152 { assert(2097152usize / 512 == 4096usize); }
1082 else { assert(1073741824usize / 512 == 2097152usize); }
1083 };
1084 old_view.split_while_huge_one_step(ps);
1085 }
1086
1087 pub proof fn split_while_huge_cur_va_independent(
1090 v1: CursorView<C>,
1091 v2: CursorView<C>,
1092 size: usize,
1093 )
1094 requires
1095 v1.inv(),
1096 v2.inv(),
1097 v1.mappings =~= v2.mappings,
1098 v1.cur_va <= v2.cur_va,
1099 v1.mappings.filter(|m: Mapping|
1101 v1.cur_va <= m.va_range.start && m.va_range.start < v2.cur_va)
1102 =~= Set::<Mapping>::empty(),
1103 !v1.present() && v2.present() ==> v2.query_mapping().page_size <= size,
1109 ensures
1110 v1.split_while_huge(size).mappings =~= v2.split_while_huge(size).mappings,
1111 {
1112 if v1.cur_va == v2.cur_va {
1113 assert(v1 =~= v2);
1114 return;
1115 }
1116 if !v1.present() {
1117 return;
1118 }
1119 admit()
1120 }
1121}
1122
1123}