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::MAX_PADDR;
12use crate::specs::arch::mm::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
13use crate::specs::arch::paging_consts::PagingConsts;
14use crate::specs::mm::page_table::Mapping;
15use crate::specs::mm::page_table::cursor::owners::*;
16use crate::specs::mm::page_table::owners::PageTableOwner;
17use vstd_extra::arithmetic::*;
18
19use crate::mm::page_table::page_size_spec as page_size;
20
21verus! {
22
23impl<C: PageTableConfig> CursorView<C> {
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(
43 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
44 );
45 assert(f.finite()) by {
46 vstd::set::axiom_set_intersect_finite::<Mapping>(
47 v.mappings,
48 Set::new(|m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end),
49 );
50 };
51 vstd::set::axiom_set_choose_len(f);
52 };
53 assert(m.inv());
54 assert(m.va_range.start + ps == m.va_range.end);
55
56 let diff: int = cur_va as int - m.va_range.start as int;
57 let ki: int = diff / new_size as int;
58 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(diff, new_size as int);
59 vstd::arithmetic::div_mod::lemma_mod_division_less_than_divisor(diff, new_size as int);
60 vstd::arithmetic::div_mod::lemma_div_pos_is_pos(diff, new_size as int);
61
62 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, new_size as int);
63 assert(ki < ps as int / new_size as int) by {
64 if ki >= ps as int / new_size as int {
65 vstd::arithmetic::mul::lemma_mul_inequality(
66 ps as int / new_size as int,
67 ki,
68 new_size as int,
69 );
70 }
71 };
72
73 let sub = Self::split_index(m, new_size, ki as usize);
74
75 assert(ki * (new_size as int) >= 0) by {
76 vstd::arithmetic::mul::lemma_mul_nonnegative(ki, new_size as int);
77 };
78 assert((ki + 1) * (new_size as int) <= ps as int) by {
79 vstd::arithmetic::mul::lemma_mul_inequality(
80 ki + 1,
81 ps as int / new_size as int,
82 new_size as int,
83 );
84 };
85 assert(m.va_range.start as int + (ki + 1) * (new_size as int) <= (m.va_range.end as int))
86 by {
87 vstd::arithmetic::mul::lemma_mul_is_commutative(ki + 1, new_size as int);
88 vstd::arithmetic::mul::lemma_mul_is_commutative(
89 ps as int / new_size as int,
90 new_size as int,
91 );
92 };
93
94 assert(ki as usize as int == ki);
95 vstd::arithmetic::mul::lemma_mul_is_distributive_add(new_size as int, ki, 1 as int);
96 assert((cur_va as int) >= (m.va_range.start as int) + ki * (new_size as int));
97 assert((cur_va as int) < (m.va_range.start as int) + (ki + 1) * (new_size as int));
98 assert(sub.va_range.start <= cur_va);
99 assert(cur_va < sub.va_range.end);
100
101 let new_self = v.split_if_mapped_huge_spec(new_size);
102 let domain = Set::<int>::new(|n: int| 0 <= n < ps as int / new_size as int);
103 assert(domain.contains(ki));
104 assert(new_self.mappings.contains(sub));
105
106 let new_filter = new_self.mappings.filter(
107 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end,
108 );
109 assert(new_filter.contains(sub));
110 assert(new_self.mappings.finite()) by {
111 vstd::set::axiom_set_remove_finite(v.mappings, m);
112 let domain = Set::<int>::new(|n: int| 0 <= n < ps as int / new_size as int);
113 assert(domain =~= int::range_set(0int, ps as int / new_size as int));
114 vstd::set_lib::range_set_properties::<int>(0int, ps as int / new_size as int);
115 domain.lemma_map_finite(|n: int| Self::split_index(m, new_size, n as usize));
116 vstd::set::axiom_set_union_finite(
117 v.mappings.remove(m),
118 domain.map(|n: int| Self::split_index(m, new_size, n as usize)),
119 );
120 };
121 assert(new_filter.finite()) by {
122 vstd::set::axiom_set_intersect_finite::<Mapping>(
123 new_self.mappings,
124 Set::new(|m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end),
125 );
126 };
127 vstd::set::axiom_set_contains_len(new_filter, sub);
128 }
129
130 pub proof fn split_if_mapped_huge_spec_decreases_page_size(v: Self, new_size: usize)
137 requires
138 v.inv(),
139 v.present(),
140 new_size > 0,
141 v.query_mapping().page_size > new_size,
142 v.query_mapping().page_size % new_size == 0,
143 ensures
144 v.split_if_mapped_huge_spec(new_size).present(),
145 v.split_if_mapped_huge_spec(new_size).query_mapping().page_size
146 < v.query_mapping().page_size,
147 {
148 Self::split_if_mapped_huge_spec_preserves_present(v, new_size);
149
150 let cur_va = v.cur_va;
151 let m = v.query_mapping();
152 let new_self = v.split_if_mapped_huge_spec(new_size);
153 let m2 = new_self.query_mapping();
154 let ps = m.page_size;
155
156 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
157 let f = v.mappings.filter(
158 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
159 );
160 assert(f.finite()) by {
161 vstd::set::axiom_set_intersect_finite::<Mapping>(
162 v.mappings,
163 Set::new(|m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end),
164 );
165 };
166 vstd::set::axiom_set_choose_len(f);
167 };
168
169 assert(new_self.mappings.contains(m2) && m2.va_range.start <= cur_va && cur_va
170 < m2.va_range.end) by {
171 let f = new_self.mappings.filter(
172 |m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end,
173 );
174 assert(new_self.mappings.finite()) by {
175 vstd::set::axiom_set_remove_finite(v.mappings, m);
176 let domain = Set::<int>::new(|n: int| 0 <= n < ps as int / new_size as int);
177 assert(domain =~= int::range_set(0int, ps as int / new_size as int));
178 vstd::set_lib::range_set_properties::<int>(0int, ps as int / new_size as int);
179 domain.lemma_map_finite(|n: int| Self::split_index(m, new_size, n as usize));
180 vstd::set::axiom_set_union_finite(
181 v.mappings.remove(m),
182 domain.map(|n: int| Self::split_index(m, new_size, n as usize)),
183 );
184 };
185 assert(f.finite()) by {
186 vstd::set::axiom_set_intersect_finite::<Mapping>(
187 new_self.mappings,
188 Set::new(|m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end),
189 );
190 };
191 vstd::set::axiom_set_choose_len(f);
192 };
193
194 if v.mappings.contains(m2) && m2 != m {
195 assert(m.va_range.end <= m2.va_range.start || m2.va_range.end <= m.va_range.start);
196 assert(false);
197 }
198 assert(!v.mappings.remove(m).contains(m2));
199 let new_mappings = Set::<int>::new(|n: int| 0 <= n < ps as int / new_size as int).map(
200 |n: int| Self::split_index(m, new_size, n as usize),
201 );
202 assert(new_mappings.contains(m2));
203 let k = choose|k: int|
204 0 <= k < ps as int / new_size as int && #[trigger] Self::split_index(
205 m,
206 new_size,
207 k as usize,
208 ) == m2;
209 assert(m2.page_size == new_size);
210 }
211
212 pub proof fn split_if_mapped_huge_spec_preserves_inv(v: Self, new_size: usize)
218 requires
219 v.inv(),
220 v.present(),
221 new_size > 0,
222 v.query_mapping().page_size > new_size,
223 v.query_mapping().page_size % new_size == 0,
224 set![4096usize, 2097152, 1073741824].contains(new_size),
225 ensures
226 v.split_if_mapped_huge_spec(new_size).inv(),
227 {
228 let cur_va = v.cur_va;
229 let m = v.query_mapping();
230 let ps = m.page_size;
231 let ns: int = new_size as int;
232 let new_self = v.split_if_mapped_huge_spec(new_size);
233 let count: int = ps as int / ns;
234 let domain = Set::<int>::new(|n: int| 0 <= n < count);
235 let new_mappings = domain.map(|n: int| Self::split_index(m, new_size, n as usize));
236
237 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
239 let f = v.mappings.filter(
240 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
241 );
242 assert(f.finite()) by {
243 vstd::set::axiom_set_intersect_finite::<Mapping>(
244 v.mappings,
245 Set::new(|m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end),
246 );
247 };
248 vstd::set::axiom_set_choose_len(f);
249 };
250 assert(m.inv());
251
252 assert(new_self.mappings.finite()) by {
256 vstd::set::axiom_set_remove_finite(v.mappings, m);
257 assert(domain =~= int::range_set(0int, count));
258 vstd::set_lib::range_set_properties::<int>(0int, count);
259 domain.lemma_map_finite(|n: int| Self::split_index(m, new_size, n as usize));
260 vstd::set::axiom_set_union_finite(v.mappings.remove(m), new_mappings);
261 };
262
263 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, ns);
265 assert(ps as int == count * ns);
266
267 assert(m.va_range.start % new_size as int == 0) by {
268 vstd::arithmetic::mul::lemma_mul_is_commutative(count, ns);
269 vstd::arithmetic::div_mod::lemma_mod_mod(m.va_range.start as int, ns, count);
270 };
271 assert(m.pa_range.start % new_size == 0) by {
272 vstd::arithmetic::mul::lemma_mul_is_commutative(count, ns);
273 vstd::arithmetic::div_mod::lemma_mod_mod(m.pa_range.start as int, ns, count);
274 };
275
276 assert forall|e: Mapping| new_self.mappings.contains(e) implies #[trigger] e.inv() by {
278 if v.mappings.remove(m).contains(e) {
279 assert(v.mappings.contains(e));
280 } else {
281 assert(new_mappings.contains(e));
282 let k = choose|k: int|
283 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == e;
284 let sub = Self::split_index(m, new_size, k as usize);
285
286 assert(set![4096usize, 2097152, 1073741824].contains(sub.page_size));
288
289 vstd::arithmetic::mul::lemma_mul_is_commutative(k, ns);
292 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
293 k,
294 m.va_range.start as int,
295 ns,
296 );
297 assert(sub.va_range.start % new_size as int == 0);
298 vstd::arithmetic::mul::lemma_mul_is_commutative(k + 1, ns);
299 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
300 k + 1,
301 m.va_range.start as int,
302 ns,
303 );
304 assert(sub.va_range.end % new_size as int == 0);
305
306 vstd::arithmetic::mul::lemma_mul_is_commutative(k, ns);
307 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
308 k,
309 m.pa_range.start as int,
310 ns,
311 );
312 assert(sub.pa_range.start % new_size == 0);
313 vstd::arithmetic::mul::lemma_mul_is_commutative(k + 1, ns);
314 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
315 k + 1,
316 m.pa_range.start as int,
317 ns,
318 );
319 assert(sub.pa_range.end % new_size == 0);
320
321 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, k, 1int);
323 assert(sub.va_range.start + new_size == sub.va_range.end);
324 assert(sub.pa_range.start + new_size == sub.pa_range.end);
325
326 vstd::arithmetic::mul::lemma_mul_nonnegative(k, ns);
328 vstd::arithmetic::mul::lemma_mul_inequality(k + 1, count, ns);
329 assert(sub.va_range.start >= m.va_range.start);
331 assert(sub.va_range.end <= m.va_range.end);
332 assert(sub.va_range.start <= sub.va_range.end);
333
334 assert(sub.pa_range.start >= m.pa_range.start);
335 assert(sub.pa_range.end <= m.pa_range.end);
336 assert(sub.pa_range.start <= sub.pa_range.end);
337 }
338 };
339
340 assert forall|e1: Mapping, e2: Mapping| #[trigger]
342 new_self.mappings.contains(e1) && #[trigger] new_self.mappings.contains(e2) && e1
343 != e2 implies e1.va_range.end <= e2.va_range.start || e2.va_range.end
344 <= e1.va_range.start by {
345 if v.mappings.remove(m).contains(e1) && v.mappings.remove(m).contains(e2) {
346 assert(v.mappings.contains(e1));
348 assert(v.mappings.contains(e2));
349 } else if v.mappings.remove(m).contains(e1) && new_mappings.contains(e2) {
350 assert(v.mappings.contains(e1));
352 assert(e1 != m);
353 let k2 = choose|k: int|
354 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == e2;
355 vstd::arithmetic::mul::lemma_mul_nonnegative(k2, ns);
356 vstd::arithmetic::mul::lemma_mul_inequality(k2 + 1, count, ns);
357 assert(e2.va_range.start >= m.va_range.start);
358 assert(e2.va_range.end <= m.va_range.end);
359 } else if new_mappings.contains(e1) && v.mappings.remove(m).contains(e2) {
360 assert(v.mappings.contains(e2));
362 assert(e2 != m);
363 let k1 = choose|k: int|
364 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == e1;
365 vstd::arithmetic::mul::lemma_mul_nonnegative(k1, ns);
366 vstd::arithmetic::mul::lemma_mul_inequality(k1 + 1, count, ns);
367 assert(e1.va_range.start >= m.va_range.start);
368 assert(e1.va_range.end <= m.va_range.end);
369 } else if new_mappings.contains(e1) && new_mappings.contains(e2) {
370 let i = choose|k: int|
372 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == e1;
373 let j = choose|k: int|
374 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == e2;
375 vstd::arithmetic::mul::lemma_mul_nonnegative(i, ns);
376 vstd::arithmetic::mul::lemma_mul_nonnegative(j, ns);
377 if i < j {
378 vstd::arithmetic::mul::lemma_mul_inequality(i + 1, j, ns);
379 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, i, 1int);
380 } else {
381 vstd::arithmetic::mul::lemma_mul_inequality(j + 1, i, ns);
382 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, j, 1int);
383 }
384 }
385 };
386 }
387
388 pub broadcast proof fn lemma_split_while_huge_preserves_cur_va(self, size: usize)
390 requires
391 self.inv(),
392 size >= PAGE_SIZE,
393 ensures
394 #[trigger] self.split_while_huge(size).cur_va == self.cur_va,
395 decreases
396 if self.present() {
397 self.query_mapping().page_size as int
398 } else {
399 0
400 },
401 {
402 if self.present() {
403 let m = self.query_mapping();
404 if m.page_size > size {
405 let new_size = m.page_size / NR_ENTRIES;
406 let new_self = self.split_if_mapped_huge_spec(new_size);
407 let f = self.mappings.filter(
409 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
410 );
411 vstd::set::axiom_set_intersect_finite::<Mapping>(
412 self.mappings,
413 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end),
414 );
415 vstd::set::axiom_set_choose_len(f);
416 assert(m.inv());
417 assert(NR_ENTRIES == 512usize) by (compute_only);
418 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
420 if m.page_size == 2097152 {
421 assert(2097152usize / 512 == 4096usize);
422 } else if m.page_size == 1073741824 {
423 assert(1073741824usize / 512 == 2097152usize);
424 } else {
425 assert(4096usize / 512 == 8usize);
426 assert(false);
427 } };
429 assert(m.page_size % new_size == 0) by {
430 if m.page_size == 2097152 {
431 assert(2097152usize % 4096 == 0);
432 } else {
433 assert(1073741824usize % 2097152 == 0);
434 }
435 };
436 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
437
438 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
439 Self::lemma_split_while_huge_preserves_cur_va(new_self, size);
440 }
441 }
442 }
443
444 pub proof fn lemma_split_while_huge_preserves_inv(self, size: usize)
446 requires
447 self.inv(),
448 size >= PAGE_SIZE,
449 ensures
450 self.split_while_huge(size).inv(),
451 decreases
452 if self.present() {
453 self.query_mapping().page_size as int
454 } else {
455 0
456 },
457 {
458 if self.present() {
459 let m = self.query_mapping();
460 if m.page_size > size {
461 let new_size = m.page_size / NR_ENTRIES;
462 let new_self = self.split_if_mapped_huge_spec(new_size);
463 let f = self.mappings.filter(
465 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
466 );
467 vstd::set::axiom_set_intersect_finite::<Mapping>(
468 self.mappings,
469 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end),
470 );
471 vstd::set::axiom_set_choose_len(f);
472 assert(m.inv());
473 assert(NR_ENTRIES == 512usize) by (compute_only);
474 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
475 if m.page_size == 2097152 {
476 assert(2097152usize / 512 == 4096usize);
477 } else if m.page_size == 1073741824 {
478 assert(1073741824usize / 512 == 2097152usize);
479 } else {
480 assert(4096usize / 512 == 8usize);
481 assert(false);
482 }
483 };
484 assert(m.page_size % new_size == 0) by {
485 if m.page_size == 2097152 {
486 assert(2097152usize % 4096 == 0);
487 } else {
488 assert(1073741824usize % 2097152 == 0);
489 }
490 };
491 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
492 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
493 new_self.lemma_split_while_huge_preserves_inv(size);
494 }
495 }
496 }
497
498 pub proof fn split_while_huge_compose(self, s1: usize, s2: usize)
502 requires
503 self.inv(),
504 s1 >= PAGE_SIZE,
505 s2 <= s1,
506 ensures
507 self.split_while_huge(s2) == self.split_while_huge(s1).split_while_huge(s2),
508 decreases
509 if self.present() {
510 self.query_mapping().page_size as int
511 } else {
512 0
513 },
514 {
515 if !self.present() {
516 return;
517 }
518 let m = self.query_mapping();
519 if m.page_size <= s1 {
520 return;
521 }
522 let new_size = m.page_size / NR_ENTRIES;
523 let f = self.mappings.filter(
524 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
525 );
526 vstd::set::axiom_set_intersect_finite::<Mapping>(
527 self.mappings,
528 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end),
529 );
530 vstd::set::axiom_set_choose_len(f);
531 assert(m.inv());
532 assert(NR_ENTRIES == 512usize) by (compute_only);
533 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
534 if m.page_size == 2097152 {
535 assert(2097152usize / 512 == 4096usize);
536 } else {
537 assert(1073741824usize / 512 == 2097152usize);
538 }
539 };
540 assert(m.page_size % new_size == 0) by {
541 if m.page_size == 2097152 {
542 assert(2097152usize % 4096 == 0);
543 } else {
544 assert(1073741824usize % 2097152 == 0);
545 }
546 };
547 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
548 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
549 self.split_if_mapped_huge_spec(new_size).split_while_huge_compose(s1, s2);
550 }
551
552 pub proof fn split_while_huge_idempotent(self, size: usize)
555 requires
556 self.inv(),
557 size >= PAGE_SIZE,
558 ensures
559 self.split_while_huge(size).split_while_huge(size) == self.split_while_huge(size),
560 {
561 self.split_while_huge_compose(size, size);
562 }
563
564 pub proof fn split_while_huge_noop_implies_page_size_le(self, size: usize)
567 requires
568 self.inv(),
569 size >= PAGE_SIZE,
570 self.split_while_huge(size) == self,
571 self.present(),
572 ensures
573 self.query_mapping().page_size <= size,
574 {
575 let m = self.query_mapping();
576 if m.page_size > size {
577 let new_size = m.page_size / NR_ENTRIES;
578 let f = self.mappings.filter(
579 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
580 );
581 vstd::set::axiom_set_intersect_finite::<Mapping>(
582 self.mappings,
583 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end),
584 );
585 vstd::set::axiom_set_choose_len(f);
586 assert(m.inv());
587 assert(NR_ENTRIES == 512usize) by (compute_only);
588 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
589 if m.page_size == 2097152 {
590 assert(2097152usize / 512 == 4096usize);
591 } else if m.page_size == 1073741824 {
592 assert(1073741824usize / 512 == 2097152usize);
593 } else {
594 assert(4096usize / 512 == 8usize);
595 assert(false);
596 }
597 };
598 assert(m.page_size % new_size == 0) by {
599 if m.page_size == 2097152 {
600 assert(2097152usize % 4096 == 0);
601 } else {
602 assert(1073741824usize % 2097152 == 0);
603 }
604 };
605 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
606 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
607 let new_self = self.split_if_mapped_huge_spec(new_size);
608 new_self.split_while_huge_refinement(size, m);
609 assert(!new_self.mappings.contains(m)) by {
610 let new_mappings = Set::<int>::new(
611 |n: int| 0 <= n < m.page_size as int / new_size as int,
612 ).map(|n: int| Self::split_index(m, new_size, n as usize));
613 if new_mappings.contains(m) {
614 let k = choose|k: int|
615 0 <= k < m.page_size as int / new_size as int
616 && #[trigger] Self::split_index(m, new_size, k as usize) == m;
617 }
618 };
619 let p = choose|p: Mapping| #[trigger]
620 new_self.mappings.contains(p) && p.va_range.start <= m.va_range.start
621 && m.va_range.end <= p.va_range.end && m.pa_range.start == (p.pa_range.start + (
622 m.va_range.start - p.va_range.start)) as Paddr && m.property == p.property;
623 if self.mappings.contains(p) {
624 assert(p.va_range.start <= self.cur_va < p.va_range.end);
625 } else {
626 let new_mappings = Set::<int>::new(
627 |n: int| 0 <= n < m.page_size as int / new_size as int,
628 ).map(|n: int| Self::split_index(m, new_size, n as usize));
629 let k = choose|k: int|
630 0 <= k < m.page_size as int / new_size as int && #[trigger] Self::split_index(
631 m,
632 new_size,
633 k as usize,
634 ) == p;
635 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(
636 m.page_size as int,
637 new_size as int,
638 );
639 vstd::arithmetic::mul::lemma_mul_inequality(
640 (k + 1) as int,
641 m.page_size as int / new_size as int,
642 new_size as int,
643 );
644 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
645 new_size as int,
646 k,
647 1int,
648 );
649 }
650 }
651 }
652
653 pub proof fn split_while_huge_one_step(self, size: usize)
663 requires
664 self.inv(),
665 self.present(),
666 self.query_mapping().page_size > size,
667 self.query_mapping().page_size / NR_ENTRIES == size,
668 self.query_mapping().page_size % size == 0,
669 set![4096usize, 2097152, 1073741824].contains(size),
670 ensures
671 self.split_while_huge(size).mappings =~= self.split_if_mapped_huge_spec(size).mappings,
672 {
673 let m = self.query_mapping();
674 let new_size = m.page_size / NR_ENTRIES;
675 let f0 = self.mappings.filter(
676 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
677 );
678 vstd::set::axiom_set_intersect_finite::<Mapping>(
679 self.mappings,
680 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end),
681 );
682 vstd::set::axiom_set_choose_len(f0);
683 assert(m.inv());
684 assert(NR_ENTRIES == 512usize) by (compute_only);
685 Self::split_if_mapped_huge_spec_preserves_present(self, new_size);
686 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
687 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
688 let new_self = self.split_if_mapped_huge_spec(new_size);
689
690 assert(new_self.query_mapping().page_size == new_size) by {
691 let new_m = new_self.query_mapping();
692 let f = new_self.mappings.filter(
693 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end,
694 );
695 vstd::set::axiom_set_intersect_finite::<Mapping>(
696 new_self.mappings,
697 Set::new(|m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end),
698 );
699 vstd::set::axiom_set_choose_len(f);
700 if self.mappings.contains(new_m) && new_m != m {
701 assert(false);
702 }
703 let new_mappings = Set::<int>::new(
704 |n: int| 0 <= n < m.page_size as int / new_size as int,
705 ).map(|n: int| Self::split_index(m, new_size, n as usize));
706 assert(new_mappings.contains(new_m));
707 };
708 assert(new_self.split_while_huge(size) == new_self);
709 }
710
711 pub proof fn split_if_mapped_huge_spec_locality(self, new_size: usize, m2: Mapping)
714 requires
715 self.inv(),
716 self.present(),
717 new_size > 0,
718 self.query_mapping().page_size % new_size == 0,
719 Mapping::disjoint_vaddrs(m2, self.query_mapping()),
720 ensures
721 self.split_if_mapped_huge_spec(new_size).mappings.contains(m2)
722 == self.mappings.contains(m2),
723 {
724 let m = self.query_mapping();
725 let size = m.page_size;
726 let new_mappings = Set::<int>::new(|n: int| 0 <= n < size / new_size).map(
727 |n: int| Self::split_index(m, new_size, n as usize),
728 );
729
730 let f = self.mappings.filter(
732 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
733 );
734 assert(f.finite()) by {
735 vstd::set::axiom_set_intersect_finite::<Mapping>(
736 self.mappings,
737 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end),
738 );
739 };
740 vstd::set::axiom_set_choose_len(f);
741 assert(m.inv());
742
743 assert(!new_mappings.contains(m2)) by {
744 if new_mappings.contains(m2) {
745 let k = choose|k: int|
746 0 <= k < size as int / new_size as int && #[trigger] Self::split_index(
747 m,
748 new_size,
749 k as usize,
750 ) == m2;
751 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(size as int, new_size as int);
752 vstd::arithmetic::mul::lemma_mul_inequality(
753 (k + 1) as int,
754 size as int / new_size as int,
755 new_size as int,
756 );
757 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
758 new_size as int,
759 k,
760 1int,
761 );
762 vstd::arithmetic::mul::lemma_mul_nonnegative(k, new_size as int);
763 }
764 };
765 }
766
767 #[verifier::rlimit(80)]
774 pub proof fn split_while_huge_locality(self, size: usize, m2: Mapping)
775 requires
776 self.inv(),
777 size >= PAGE_SIZE,
778 self.mappings.contains(m2),
779 !(m2.va_range.start <= self.cur_va < m2.va_range.end),
780 ensures
781 self.split_while_huge(size).mappings.contains(m2),
782 decreases
783 if self.present() {
784 self.query_mapping().page_size as int
785 } else {
786 0
787 },
788 {
789 if self.present() {
790 let m = self.query_mapping();
791 if m.page_size > size {
792 let new_size = m.page_size / NR_ENTRIES;
793 let f = self.mappings.filter(
795 |m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end,
796 );
797 assert(f.finite()) by {
798 vstd::set::axiom_set_intersect_finite::<Mapping>(
799 self.mappings,
800 Set::new(|m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end),
801 );
802 };
803 vstd::set::axiom_set_choose_len(f);
804 assert(self.mappings.contains(m));
805 assert(m.va_range.start <= self.cur_va < m.va_range.end);
806 assert(m.inv());
807 assert(Mapping::disjoint_vaddrs(m2, m));
809 assert(NR_ENTRIES == 512usize);
811 assert(m.page_size % new_size == 0) by {
812 if m.page_size == 4096 {
813 assert(4096usize % (4096usize / 512usize) == 0);
814 } else if m.page_size == 2097152 {
815 assert(2097152usize % (2097152usize / 512usize) == 0);
816 } else {
817 assert(1073741824usize % (1073741824usize / 512usize) == 0);
818 }
819 };
820 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
821 if m.page_size == 2097152 {
822 assert(2097152usize / 512 == 4096usize);
823 } else if m.page_size == 1073741824 {
824 assert(1073741824usize / 512 == 2097152usize);
825 } else {
826 assert(4096usize / 512 == 8usize);
827 assert(false);
828 }
829 };
830 self.split_if_mapped_huge_spec_locality(new_size, m2);
831 let new_self = self.split_if_mapped_huge_spec(new_size);
832 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
833 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
834 new_self.split_while_huge_locality(size, m2);
835 }
836 }
837 }
838
839 #[verifier::rlimit(120)]
847 pub proof fn split_while_huge_locality_absent(self, size: usize, m2: Mapping)
848 requires
849 self.inv(),
850 size >= PAGE_SIZE,
851 !self.mappings.contains(m2),
852 self.present() ==> Mapping::disjoint_vaddrs(m2, self.query_mapping()),
853 ensures
854 !self.split_while_huge(size).mappings.contains(m2),
855 decreases
856 if self.present() {
857 self.query_mapping().page_size as int
858 } else {
859 0
860 },
861 {
862 if self.present() {
863 let m = self.query_mapping();
864 if m.page_size > size {
865 let new_size = m.page_size / NR_ENTRIES;
866 let f = self.mappings.filter(
868 |m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end,
869 );
870 assert(f.finite()) by {
871 vstd::set::axiom_set_intersect_finite::<Mapping>(
872 self.mappings,
873 Set::new(|m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end),
874 );
875 };
876 vstd::set::axiom_set_choose_len(f);
877 assert(self.mappings.contains(m));
878 assert(m.inv());
880 assert(m.page_size % new_size == 0) by {
881 assert(set![4096usize, 2097152usize, 1073741824usize].contains(m.page_size));
882 assert(4096usize % (4096usize / 512usize) == 0) by (compute_only);
883 assert(2097152usize % (2097152usize / 512usize) == 0) by (compute_only);
884 assert(1073741824usize % (1073741824usize / 512usize) == 0) by (compute_only);
885 };
886 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
887 if m.page_size == 2097152 {
888 assert(2097152usize / 512 == 4096usize);
889 } else if m.page_size == 1073741824 {
890 assert(1073741824usize / 512 == 2097152usize);
891 } else {
892 assert(4096usize / 512 == 8usize);
893 assert(false);
894 }
895 };
896 self.split_if_mapped_huge_spec_locality(new_size, m2);
897 let new_self = self.split_if_mapped_huge_spec(new_size);
898 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
899 Self::split_if_mapped_huge_spec_preserves_present(self, new_size);
900 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
901 assert(new_self.present() ==> Mapping::disjoint_vaddrs(
902 m2,
903 new_self.query_mapping(),
904 )) by {
905 if new_self.present() {
906 let new_m = new_self.query_mapping();
907 let nf = new_self.mappings.filter(
908 |m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end,
909 );
910 vstd::set::axiom_set_intersect_finite::<Mapping>(
911 new_self.mappings,
912 Set::new(
913 |m3: Mapping|
914 m3.va_range.start <= new_self.cur_va < m3.va_range.end,
915 ),
916 );
917 vstd::set::axiom_set_choose_len(nf);
918 if self.mappings.contains(new_m) && new_m != m {
919 assert(false);
920 }
921 let new_mappings = Set::<int>::new(
922 |n: int| 0 <= n < m.page_size as int / new_size as int,
923 ).map(|n: int| Self::split_index(m, new_size, n as usize));
924 let k = choose|k: int|
925 0 <= k < m.page_size as int / new_size as int
926 && #[trigger] Self::split_index(m, new_size, k as usize) == new_m;
927 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(
928 m.page_size as int,
929 new_size as int,
930 );
931 vstd::arithmetic::mul::lemma_mul_inequality(
932 (k + 1) as int,
933 m.page_size as int / new_size as int,
934 new_size as int,
935 );
936 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
937 new_size as int,
938 k,
939 1int,
940 );
941 vstd::arithmetic::mul::lemma_mul_nonnegative(k, new_size as int);
942 }
943 };
944 new_self.split_while_huge_locality_absent(size, m2);
945 }
946 }
947 }
948
949 pub proof fn split_if_mapped_huge_spec_refinement(self, new_size: usize, e: Mapping)
954 requires
955 self.inv(),
956 self.present(),
957 new_size > 0,
958 self.query_mapping().page_size > new_size,
959 self.query_mapping().page_size % new_size == 0,
960 self.split_if_mapped_huge_spec(new_size).mappings.contains(e),
961 ensures
962 self.mappings.contains(e) || {
963 let parent = self.query_mapping();
964 &&& self.mappings.contains(parent)
965 &&& parent.va_range.start <= e.va_range.start
966 &&& e.va_range.end <= parent.va_range.end
967 &&& e.pa_range.start == (parent.pa_range.start + (e.va_range.start
968 - parent.va_range.start)) as Paddr
969 &&& e.property == parent.property
970 },
971 {
972 let qm = self.query_mapping();
973 let ps = qm.page_size;
974 let ns: int = new_size as int;
975 let count: int = ps as int / ns;
976 let new_self = self.split_if_mapped_huge_spec(new_size);
977 let domain = Set::<int>::new(|n: int| 0 <= n < count);
978 let new_mappings = domain.map(|n: int| Self::split_index(qm, new_size, n as usize));
979
980 let f = self.mappings.filter(
982 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
983 );
984 vstd::set::axiom_set_intersect_finite::<Mapping>(
985 self.mappings,
986 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end),
987 );
988 vstd::set::axiom_set_choose_len(f);
989 assert(self.mappings.contains(qm));
990 assert(qm.inv());
991
992 if self.mappings.remove(qm).contains(e) {
993 assert(self.mappings.contains(e));
994 } else {
995 assert(new_mappings.contains(e));
996 let k = choose|k: int|
997 0 <= k < count && #[trigger] Self::split_index(qm, new_size, k as usize) == e;
998
999 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, ns);
1000 assert(ps as int == count * ns);
1001
1002 vstd::arithmetic::mul::lemma_mul_nonnegative(k, ns);
1003 vstd::arithmetic::mul::lemma_mul_inequality(k + 1, count, ns);
1004
1005 assert(k as usize as int == k);
1006 let ku = k as usize;
1007 assert(e == Self::split_index(qm, new_size, ku));
1008 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, k, 1int);
1009
1010 assert(e.va_range.start as int == qm.va_range.start as int + k * ns);
1011 assert(e.va_range.start >= qm.va_range.start);
1012 assert(e.va_range.end as int == qm.va_range.start as int + (k + 1) * ns);
1013 assert(e.va_range.end <= qm.va_range.end);
1014 assert(e.pa_range.start as int == qm.pa_range.start as int + k * ns);
1015 assert(e.va_range.start - qm.va_range.start == k * ns);
1016 assert(e.pa_range.start == (qm.pa_range.start + (e.va_range.start
1017 - qm.va_range.start)) as Paddr);
1018 assert(e.property == qm.property);
1019 }
1020 }
1021
1022 pub proof fn split_while_huge_refinement(self, size: usize, m: Mapping)
1023 requires
1024 self.inv(),
1025 size >= PAGE_SIZE,
1026 self.split_while_huge(size).mappings.contains(m),
1027 ensures
1028 self.mappings.contains(m) || exists|parent: Mapping| #[trigger]
1029 self.mappings.contains(parent) && parent.va_range.start <= m.va_range.start
1030 && m.va_range.end <= parent.va_range.end && m.pa_range.start == (
1031 parent.pa_range.start + (m.va_range.start - parent.va_range.start)) as Paddr
1032 && m.property == parent.property,
1033 decreases
1034 if self.present() {
1035 self.query_mapping().page_size as int
1036 } else {
1037 0
1038 },
1039 {
1040 if self.present() {
1041 let qm = self.query_mapping();
1042 if qm.page_size > size {
1043 let new_size = qm.page_size / NR_ENTRIES;
1044 let new_self = self.split_if_mapped_huge_spec(new_size);
1045
1046 let f = self.mappings.filter(
1047 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
1048 );
1049 vstd::set::axiom_set_intersect_finite::<Mapping>(
1050 self.mappings,
1051 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end),
1052 );
1053 vstd::set::axiom_set_choose_len(f);
1054 assert(qm.inv());
1055 assert(NR_ENTRIES == 512usize) by (compute_only);
1056 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
1057 if qm.page_size == 2097152 {
1058 assert(2097152usize / 512 == 4096usize);
1059 } else if qm.page_size == 1073741824 {
1060 assert(1073741824usize / 512 == 2097152usize);
1061 } else {
1062 assert(4096usize / 512 == 8usize);
1063 assert(false);
1064 }
1065 };
1066 assert(qm.page_size % new_size == 0) by {
1067 if qm.page_size == 2097152 {
1068 assert(2097152usize % 4096 == 0);
1069 } else {
1070 assert(1073741824usize % 2097152 == 0);
1071 }
1072 };
1073 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
1074 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
1075
1076 new_self.split_while_huge_refinement(size, m);
1077
1078 if new_self.mappings.contains(m) {
1079 self.split_if_mapped_huge_spec_refinement(new_size, m);
1080 } else {
1081 let p = choose|p: Mapping| #[trigger]
1082 new_self.mappings.contains(p) && p.va_range.start <= m.va_range.start
1083 && m.va_range.end <= p.va_range.end && m.pa_range.start == (
1084 p.pa_range.start + (m.va_range.start - p.va_range.start)) as Paddr
1085 && m.property == p.property;
1086 self.split_if_mapped_huge_spec_refinement(new_size, p);
1087 if !self.mappings.contains(p) {
1088 assert(qm.va_range.start <= m.va_range.start);
1089 assert(m.va_range.end <= qm.va_range.end);
1090 new_self.lemma_split_while_huge_preserves_inv(size);
1093 assert(new_self.split_while_huge(size).inv());
1094 assert(m.inv());
1095 assert(new_self.inv());
1096 assert(p.inv());
1097 assert(m.va_range.start + m.page_size == m.va_range.end);
1099 assert(qm.va_range.start + qm.page_size == qm.va_range.end);
1100 assert(m.va_range.start - qm.va_range.start <= qm.page_size - m.page_size);
1102 assert(qm.pa_range.start + qm.page_size == qm.pa_range.end);
1104 assert(qm.pa_range.end <= MAX_PADDR);
1105 assert(p.pa_range.start as int == qm.pa_range.start as int + (
1106 p.va_range.start - qm.va_range.start));
1107 assert(m.pa_range.start as int == p.pa_range.start as int + (
1108 m.va_range.start - p.va_range.start));
1109 assert(m.pa_range.start as int == qm.pa_range.start as int + (
1110 m.va_range.start - qm.va_range.start));
1111 assert(qm.pa_range.start as int + (m.va_range.start - qm.va_range.start)
1113 <= qm.pa_range.end as int);
1114 assert(m.pa_range.start == (qm.pa_range.start + (m.va_range.start
1115 - qm.va_range.start)) as Paddr);
1116 assert(m.property == qm.property);
1117 }
1118 }
1119 }
1120 }
1121 }
1122
1123 pub proof fn split_while_huge_disjoint(self, size: usize, other: Set<Mapping>)
1133 requires
1134 self.inv(),
1135 size >= PAGE_SIZE,
1136 forall|m: Mapping, x: Mapping| #[trigger]
1137 self.mappings.contains(m) && #[trigger] other.contains(x)
1138 ==> Mapping::disjoint_vaddrs(m, x),
1139 ensures
1140 self.split_while_huge(size).mappings.disjoint(other),
1141 decreases
1142 if self.present() {
1143 self.query_mapping().page_size as int
1144 } else {
1145 0
1146 },
1147 {
1148 if !self.present() {
1149 assert forall|x: Mapping|
1151 #![trigger other.contains(x)]
1152 other.contains(x) implies !self.split_while_huge(size).mappings.contains(x) by {
1153 if self.mappings.contains(x) {
1154 assert(Mapping::disjoint_vaddrs(x, x));
1155 assert(x.inv());
1156 }
1157 };
1158 return;
1159 }
1160 let m = self.query_mapping();
1161 if m.page_size <= size {
1162 assert forall|x: Mapping|
1163 #![trigger other.contains(x)]
1164 other.contains(x) implies !self.split_while_huge(size).mappings.contains(x) by {
1165 if self.mappings.contains(x) {
1166 assert(Mapping::disjoint_vaddrs(x, x));
1167 assert(x.inv());
1168 }
1169 };
1170 return;
1171 }
1172 let new_size = m.page_size / NR_ENTRIES;
1173
1174 let f = self.mappings.filter(
1176 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
1177 );
1178 vstd::set::axiom_set_intersect_finite::<Mapping>(
1179 self.mappings,
1180 Set::new(|m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end),
1181 );
1182 vstd::set::axiom_set_choose_len(f);
1183 assert(self.mappings.contains(m));
1184 assert(m.inv());
1185
1186 assert(NR_ENTRIES == 512usize) by (compute_only);
1187 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
1188 if m.page_size == 2097152 {
1189 assert(2097152usize / 512 == 4096usize);
1190 } else if m.page_size == 1073741824 {
1191 assert(1073741824usize / 512 == 2097152usize);
1192 } else {
1193 assert(4096usize / 512 == 8usize);
1194 assert(false);
1195 }
1196 };
1197 assert(m.page_size % new_size == 0) by {
1198 if m.page_size == 2097152 {
1199 assert(2097152usize % 4096 == 0);
1200 } else {
1201 assert(1073741824usize % 2097152 == 0);
1202 }
1203 };
1204 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
1205 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
1206 let new_self = self.split_if_mapped_huge_spec(new_size);
1207
1208 assert forall|m2: Mapping, x: Mapping| #[trigger]
1210 new_self.mappings.contains(m2) && #[trigger] other.contains(
1211 x,
1212 ) implies Mapping::disjoint_vaddrs(m2, x) by {
1213 if self.mappings.contains(m2) {
1214 } else {
1216 let new_mappings = Set::<int>::new(
1218 |n: int| 0 <= n < m.page_size as int / new_size as int,
1219 ).map(|n: int| Self::split_index(m, new_size, n as usize));
1220 assert(new_mappings.contains(m2));
1221 let k = choose|k: int|
1222 0 <= k < m.page_size as int / new_size as int && #[trigger] Self::split_index(
1223 m,
1224 new_size,
1225 k as usize,
1226 ) == m2;
1227 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(
1228 m.page_size as int,
1229 new_size as int,
1230 );
1231 vstd::arithmetic::mul::lemma_mul_inequality(
1232 (k + 1) as int,
1233 m.page_size as int / new_size as int,
1234 new_size as int,
1235 );
1236 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
1237 new_size as int,
1238 k,
1239 1int,
1240 );
1241 vstd::arithmetic::mul::lemma_mul_nonnegative(k, new_size as int);
1242 assert(Mapping::disjoint_vaddrs(m, x));
1244 }
1245 };
1246
1247 new_self.split_while_huge_disjoint(size, other);
1248 }
1249}
1250
1251impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
1252 proof fn query_mapping_from_subtree(self, qm: Mapping)
1257 requires
1258 self.inv(),
1259 self.in_locked_range(),
1260 self@.inv(),
1261 self@.present(),
1262 qm == self@.query_mapping(),
1263 ensures
1264 PageTableOwner(self.cur_subtree()).view_rec(self.cur_subtree().value.path).contains(qm),
1265 {
1266 let f = self@.mappings.filter(
1267 |m2: Mapping| m2.va_range.start <= self@.cur_va < m2.va_range.end,
1268 );
1269 axiom_set_intersect_finite::<Mapping>(
1270 self@.mappings,
1271 Set::new(|m2: Mapping| m2.va_range.start <= self@.cur_va < m2.va_range.end),
1272 );
1273 axiom_set_choose_len(f);
1274 self.mapping_covering_cur_va_from_cur_subtree(qm);
1275 }
1276
1277 pub proof fn split_while_huge_node_noop(self)
1278 requires
1279 self.inv(),
1280 self.in_locked_range(),
1281 self.cur_entry_owner().is_node(),
1282 self.level > 1,
1283 ensures
1284 self@.split_while_huge(page_size((self.level - 1) as PagingLevel)) == self@,
1285 {
1286 self.view_preserves_inv();
1287 if self@.present() {
1288 self.cur_subtree_inv();
1289 let subtree = self.cur_subtree();
1290 let path = subtree.value.path;
1291 let qm = self@.query_mapping();
1292 self.query_mapping_from_subtree(qm);
1293 let cont = self.continuations[self.level - 1];
1294 cont.path().push_tail_property_len(cont.idx as usize);
1295 PageTableOwner(subtree).view_rec_node_page_size_bound(path, qm);
1296 }
1297 }
1298
1299 pub proof fn split_while_huge_absent_noop(self, size: usize)
1302 requires
1303 self.inv(),
1304 self.in_locked_range(),
1305 self.cur_entry_owner().is_absent(),
1306 ensures
1307 self@.split_while_huge(size) == self@,
1308 {
1309 self.view_preserves_inv();
1310 self.cur_entry_absent_not_present();
1311 }
1312
1313 pub proof fn split_while_huge_at_level_noop(self)
1314 requires
1315 self.inv(),
1316 self.in_locked_range(),
1317 ensures
1318 self@.split_while_huge(page_size(self.level as PagingLevel)) == self@,
1319 {
1320 self.view_preserves_inv();
1321 if self@.present() {
1322 self.cur_subtree_inv();
1323 let subtree = self.cur_subtree();
1324 let path = subtree.value.path;
1325 let qm = self@.query_mapping();
1326 self.query_mapping_from_subtree(qm);
1327 let cont = self.continuations[self.level - 1];
1328 cont.path().push_tail_property_len(cont.idx as usize);
1329 PageTableOwner(subtree).view_rec_page_size_bound(path, qm);
1330 }
1331 }
1332
1333 pub proof fn map_branch_frame_split_while_huge(
1343 self,
1344 owner0: Self,
1345 owner_before_frame: Self,
1346 level_before_frame: int,
1347 )
1348 requires
1349 self.inv(),
1350 owner0.inv(),
1351 owner_before_frame.inv(),
1352 1 <= level_before_frame - 1,
1353 level_before_frame <= NR_LEVELS,
1354 self.level == (level_before_frame - 1) as u8,
1355 owner_before_frame@ == owner0@.split_while_huge(
1356 page_size(level_before_frame as PagingLevel),
1357 ),
1358 self@ == owner_before_frame@.split_if_mapped_huge_spec(
1359 page_size((level_before_frame - 1) as PagingLevel),
1360 ),
1361 owner_before_frame@.present(),
1366 owner_before_frame@.query_mapping().page_size == page_size(
1367 level_before_frame as PagingLevel,
1368 ),
1369 {
1370 owner0.view_preserves_inv();
1371 owner_before_frame.view_preserves_inv();
1372 let s_top = page_size(level_before_frame as PagingLevel);
1373 let s_low = page_size((level_before_frame - 1) as PagingLevel);
1374
1375 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_spec_values();
1379 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_ge_page_size(
1380 level_before_frame as PagingLevel,
1381 );
1382 assert(NR_ENTRIES == 512usize) by (compute_only);
1383
1384 owner0@.split_while_huge_compose(s_top, s_low);
1388
1389 owner_before_frame@.split_while_huge_one_step(s_low);
1392 }
1393
1394 pub proof fn find_next_split_push_equals_split_while_huge(self, old_view: CursorView<C>)
1397 requires
1398 self.inv(),
1399 old_view.inv(),
1400 self.cur_entry_owner().is_frame(),
1401 self@.cur_va == old_view.cur_va,
1402 old_view.present(),
1403 old_view.query_mapping().page_size > page_size(self.level as PagingLevel),
1404 old_view.query_mapping().page_size / NR_ENTRIES == page_size(self.level as PagingLevel),
1405 old_view.query_mapping().page_size % page_size(self.level as PagingLevel) == 0,
1406 self@.mappings =~= old_view.split_if_mapped_huge_spec(
1407 page_size(self.level as PagingLevel),
1408 ).mappings,
1409 ensures
1410 self@.mappings =~= old_view.split_while_huge(
1411 page_size(self.level as PagingLevel),
1412 ).mappings,
1413 {
1414 let ps = page_size(self.level as PagingLevel);
1415 let m = old_view.query_mapping();
1416 let f = old_view.mappings.filter(
1417 |m2: Mapping| m2.va_range.start <= old_view.cur_va < m2.va_range.end,
1418 );
1419 vstd::set::axiom_set_intersect_finite::<Mapping>(
1420 old_view.mappings,
1421 Set::new(|m2: Mapping| m2.va_range.start <= old_view.cur_va < m2.va_range.end),
1422 );
1423 vstd::set::axiom_set_choose_len(f);
1424 assert(m.inv());
1425 assert(NR_ENTRIES == 512usize) by (compute_only);
1426 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_spec_values();
1427 assert(set![4096usize, 2097152, 1073741824].contains(ps)) by {
1428 if m.page_size == 2097152 {
1429 assert(2097152usize / 512 == 4096usize);
1430 } else {
1431 assert(1073741824usize / 512 == 2097152usize);
1432 }
1433 };
1434 old_view.split_while_huge_one_step(ps);
1435 }
1436
1437 pub proof fn split_while_huge_cur_va_independent(
1445 v1: CursorView<C>,
1446 v2: CursorView<C>,
1447 size: usize,
1448 )
1449 requires
1450 v1.inv(),
1451 v2.inv(),
1452 v1.mappings =~= v2.mappings,
1453 v1.cur_va <= v2.cur_va,
1454 v1.mappings.filter(
1456 |m: Mapping| v1.cur_va <= m.va_range.start && m.va_range.start < v2.cur_va,
1457 ) =~= Set::<Mapping>::empty(),
1458 !v1.present() && v2.present() ==> v2.query_mapping().page_size <= size,
1464 v1.cur_va < v2.cur_va ==> !v1.present(),
1467 ensures
1468 v1.split_while_huge(size).mappings =~= v2.split_while_huge(size).mappings,
1469 {
1470 if v1.cur_va == v2.cur_va {
1471 assert(v1 =~= v2);
1472 }
1473 }
1474}
1475
1476}