1use vstd::prelude::*;
2
3use vstd::{set::lemma_set_choose_len, set_lib::*};
4use vstd_extra::{arithmetic::*, ghost_tree::*, ownership::*};
5
6use crate::specs::{
7 arch::{MAX_PADDR, NR_ENTRIES, NR_LEVELS, PAGE_SIZE},
8 mm::page_table::{Mapping, cursor::owners::*, owners::PageTableOwner},
9};
10
11use crate::arch::mm::PagingConsts;
12use crate::mm::{
13 Paddr, PagingConstsTrait, PagingLevel, Vaddr, page_prop::PageProperty, page_size, page_table::*,
14};
15
16verus! {
17
18broadcast use group_ghost_tree_lemmas;
19
20impl<C: PageTableConfig> CursorView<C> {
21 pub proof fn split_if_mapped_huge_spec_preserves_present(v: Self, new_size: usize)
25 requires
26 v.inv(),
27 v.present(),
28 new_size > 0,
29 v.query_mapping().page_size > 0,
30 v.query_mapping().page_size % new_size == 0,
31 ensures
32 v.split_if_mapped_huge_spec(new_size).present(),
33 {
34 let cur_va = v.cur_va;
35 let m = v.query_mapping();
36 let ps = m.page_size;
37
38 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
39 let f = v.mappings.filter(
40 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
41 );
42 vstd::set::lemma_set_choose_len(f);
43 };
44 assert(m.inv());
45
46 let diff: int = cur_va - m.va_range.start;
47 let ki: int = diff / new_size as int;
48 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(diff, new_size as int);
49
50 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, new_size as int);
51 assert(ki < ps as int / new_size as int) by {
52 if ki >= ps as int / new_size as int {
53 vstd::arithmetic::mul::lemma_mul_inequality(
54 ps as int / new_size as int,
55 ki,
56 new_size as int,
57 );
58 }
59 };
60
61 let sub = Self::split_index(m, new_size, ki as usize);
62
63 assert(ki * new_size >= 0);
64 assert((ki + 1) * new_size <= ps) by {
65 vstd::arithmetic::mul::lemma_mul_inequality(
66 ki + 1,
67 ps as int / new_size as int,
68 new_size as int,
69 );
70 };
71
72 vstd::arithmetic::mul::lemma_mul_is_distributive_add(new_size as int, ki, 1 as int);
73
74 let new_self = v.split_if_mapped_huge_spec(new_size);
75 let domain = Set::<int>::range(0int, ps as int / new_size as int);
76 assert(domain.contains(ki));
77
78 let new_filter = new_self.mappings.filter(
79 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end,
80 );
81 vstd::set::lemma_set_contains_len(new_filter, sub);
82 }
83
84 pub proof fn split_if_mapped_huge_spec_decreases_page_size(v: Self, new_size: usize)
91 requires
92 v.inv(),
93 v.present(),
94 new_size > 0,
95 v.query_mapping().page_size > new_size,
96 v.query_mapping().page_size % new_size == 0,
97 ensures
98 v.split_if_mapped_huge_spec(new_size).present(),
99 v.split_if_mapped_huge_spec(new_size).query_mapping().page_size
100 < v.query_mapping().page_size,
101 {
102 Self::split_if_mapped_huge_spec_preserves_present(v, new_size);
103
104 let cur_va = v.cur_va;
105 let m = v.query_mapping();
106 let new_self = v.split_if_mapped_huge_spec(new_size);
107 let m2 = new_self.query_mapping();
108 let ps = m.page_size;
109
110 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
111 let f = v.mappings.filter(
112 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
113 );
114 vstd::set::lemma_set_choose_len(f);
115 };
116
117 assert(new_self.mappings.contains(m2) && m2.va_range.start <= cur_va && cur_va
118 < m2.va_range.end) by {
119 let f = new_self.mappings.filter(
120 |m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end,
121 );
122 vstd::set::lemma_set_choose_len(f);
123 };
124
125 if v.mappings.contains(m2) && m2 != m {
126 assert(false);
127 }
128 let new_mappings = Set::<int>::range(0int, ps as int / new_size as int).map(
129 |n: int| Self::split_index(m, new_size, n as usize),
130 );
131 let k = choose|k: int|
132 0 <= k < ps as int / new_size as int && #[trigger] Self::split_index(
133 m,
134 new_size,
135 k as usize,
136 ) == m2;
137 }
138
139 pub proof fn split_if_mapped_huge_spec_preserves_inv(v: Self, new_size: usize)
145 requires
146 v.inv(),
147 v.present(),
148 new_size > 0,
149 v.query_mapping().page_size > new_size,
150 v.query_mapping().page_size % new_size == 0,
151 set![4096usize, 2097152, 1073741824].contains(new_size),
152 ensures
153 v.split_if_mapped_huge_spec(new_size).inv(),
154 {
155 let cur_va = v.cur_va;
156 let m = v.query_mapping();
157 let ps = m.page_size;
158 let ns: int = new_size as int;
159 let count: int = ps as int / ns;
160
161 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
163 let f = v.mappings.filter(
164 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
165 );
166 vstd::set::lemma_set_choose_len(f);
167 };
168 assert(m.inv());
169 assert(m.va_range.start % new_size as int == 0) by {
170 vstd::arithmetic::mul::lemma_mul_is_commutative(count, ns);
171 vstd::arithmetic::div_mod::lemma_mod_mod(m.va_range.start as int, ns, count);
172 };
173 }
174
175 pub broadcast proof fn lemma_split_while_huge_preserves_cur_va(self, size: usize)
177 requires
178 self.inv(),
179 size >= PAGE_SIZE,
180 ensures
181 #[trigger] self.split_while_huge(size).cur_va == self.cur_va,
182 decreases
183 if self.present() {
184 self.query_mapping().page_size as int
185 } else {
186 0
187 },
188 {
189 if self.present() {
190 let m = self.query_mapping();
191 if m.page_size > size {
192 let new_size = m.page_size / NR_ENTRIES;
193 let new_self = self.split_if_mapped_huge_spec(new_size);
194 let f = self.mappings.filter(
196 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
197 );
198 vstd::set::lemma_set_choose_len(f);
199 assert(m.inv());
200 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
202 if m.page_size != 2097152 && m.page_size != 1073741824 {
203 assert(false);
204 }
205 };
206 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
207
208 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
209 Self::lemma_split_while_huge_preserves_cur_va(new_self, size);
210 }
211 }
212 }
213
214 pub proof fn lemma_split_while_huge_preserves_inv(self, size: usize)
216 requires
217 self.inv(),
218 size >= PAGE_SIZE,
219 ensures
220 self.split_while_huge(size).inv(),
221 decreases
222 if self.present() {
223 self.query_mapping().page_size as int
224 } else {
225 0
226 },
227 {
228 if self.present() {
229 let m = self.query_mapping();
230 if m.page_size > size {
231 let new_size = m.page_size / NR_ENTRIES;
232 let new_self = self.split_if_mapped_huge_spec(new_size);
233 let f = self.mappings.filter(
235 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
236 );
237 vstd::set::lemma_set_choose_len(f);
238 assert(m.inv());
239 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
240 if m.page_size != 2097152 && m.page_size != 1073741824 {
241 assert(false);
242 }
243 };
244 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
245 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
246 new_self.lemma_split_while_huge_preserves_inv(size);
247 }
248 }
249 }
250
251 pub proof fn split_while_huge_compose(self, s1: usize, s2: usize)
255 requires
256 self.inv(),
257 s1 >= PAGE_SIZE,
258 s2 <= s1,
259 ensures
260 self.split_while_huge(s2) == self.split_while_huge(s1).split_while_huge(s2),
261 decreases
262 if self.present() {
263 self.query_mapping().page_size as int
264 } else {
265 0
266 },
267 {
268 if !self.present() {
269 return;
270 }
271 let m = self.query_mapping();
272 if m.page_size <= s1 {
273 return;
274 }
275 let new_size = m.page_size / NR_ENTRIES;
276 let f = self.mappings.filter(
277 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
278 );
279 vstd::set::lemma_set_choose_len(f);
280 assert(m.inv());
281 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
282 if m.page_size == 2097152 {
283 } else {
284 }
285 };
286 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
287 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
288 self.split_if_mapped_huge_spec(new_size).split_while_huge_compose(s1, s2);
289 }
290
291 pub proof fn split_while_huge_idempotent(self, size: usize)
294 requires
295 self.inv(),
296 size >= PAGE_SIZE,
297 ensures
298 self.split_while_huge(size).split_while_huge(size) == self.split_while_huge(size),
299 {
300 self.split_while_huge_compose(size, size);
301 }
302
303 pub proof fn split_while_huge_noop_implies_page_size_le(self, size: usize)
306 requires
307 self.inv(),
308 size >= PAGE_SIZE,
309 self.split_while_huge(size) == self,
310 self.present(),
311 ensures
312 self.query_mapping().page_size <= size,
313 {
314 let m = self.query_mapping();
315 if m.page_size > size {
316 let new_size = m.page_size / NR_ENTRIES;
317 let f = self.mappings.filter(
318 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
319 );
320 vstd::set::lemma_set_choose_len(f);
321 assert(m.inv());
322 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
323 if m.page_size == 2097152 {
324 } else if m.page_size == 1073741824 {
325 } else {
326 assert(false);
327 }
328 };
329 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
330 let new_self = self.split_if_mapped_huge_spec(new_size);
331 new_self.split_while_huge_refinement(size, m);
332 let p = choose|p: Mapping| #[trigger]
333 new_self.mappings.contains(p) && p.va_range.start <= m.va_range.start
334 && m.va_range.end <= p.va_range.end && m.pa_range.start == (p.pa_range.start + (
335 m.va_range.start - p.va_range.start)) as Paddr && m.property == p.property;
336 if self.mappings.contains(p) {
337 } else {
338 let new_mappings = Set::<int>::range(
339 0int,
340 m.page_size as int / new_size as int,
341 ).map(|n: int| Self::split_index(m, new_size, n as usize));
342 let k = choose|k: int|
343 0 <= k < m.page_size as int / new_size as int && #[trigger] Self::split_index(
344 m,
345 new_size,
346 k as usize,
347 ) == p;
348 }
349 }
350 }
351
352 pub proof fn split_while_huge_one_step(self, size: usize)
362 requires
363 self.inv(),
364 self.present(),
365 self.query_mapping().page_size > size,
366 self.query_mapping().page_size / NR_ENTRIES == size,
367 self.query_mapping().page_size % size == 0,
368 set![4096usize, 2097152, 1073741824].contains(size),
369 ensures
370 self.split_while_huge(size).mappings == self.split_if_mapped_huge_spec(size).mappings,
371 {
372 let m = self.query_mapping();
373 let new_size = m.page_size / NR_ENTRIES;
374 let f0 = self.mappings.filter(
375 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
376 );
377 vstd::set::lemma_set_choose_len(f0);
378 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
379 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
380 let new_self = self.split_if_mapped_huge_spec(new_size);
381
382 assert(new_self.query_mapping().page_size == new_size) by {
383 let new_m = new_self.query_mapping();
384 let f = new_self.mappings.filter(
385 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end,
386 );
387 vstd::set::lemma_set_choose_len(f);
388 if self.mappings.contains(new_m) && new_m != m {
389 assert(false);
390 }
391 let new_mappings = Set::<int>::range(0int, m.page_size as int / new_size as int).map(
392 |n: int| Self::split_index(m, new_size, n as usize),
393 );
394 };
395 assert(new_self.split_while_huge(size) == new_self);
396 }
397
398 pub proof fn split_if_mapped_huge_spec_locality(self, new_size: usize, m2: Mapping)
401 requires
402 self.inv(),
403 self.present(),
404 new_size > 0,
405 self.query_mapping().page_size % new_size == 0,
406 Mapping::disjoint_vaddrs(m2, self.query_mapping()),
407 ensures
408 self.split_if_mapped_huge_spec(new_size).mappings.contains(m2)
409 == self.mappings.contains(m2),
410 {
411 let m = self.query_mapping();
412 let size = m.page_size;
413 let new_mappings = Set::<int>::range(0int, (size / new_size) as int).map(
414 |n: int| Self::split_index(m, new_size, n as usize),
415 );
416
417 let f = self.mappings.filter(
419 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
420 );
421 vstd::set::lemma_set_choose_len(f);
422 assert(m.inv());
423
424 assert(!new_mappings.contains(m2)) by {
425 if new_mappings.contains(m2) {
426 let k = choose|k: int|
427 0 <= k < size as int / new_size as int && #[trigger] Self::split_index(
428 m,
429 new_size,
430 k as usize,
431 ) == m2;
432 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(size as int, new_size as int);
433 vstd::arithmetic::mul::lemma_mul_inequality(
434 (k + 1) as int,
435 size as int / new_size as int,
436 new_size as int,
437 );
438 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
439 new_size as int,
440 k,
441 1int,
442 );
443 }
444 };
445 }
446
447 #[verifier::rlimit(80)]
454 pub proof fn split_while_huge_locality(self, size: usize, m2: Mapping)
455 requires
456 self.inv(),
457 size >= PAGE_SIZE,
458 self.mappings.contains(m2),
459 !(m2.va_range.start <= self.cur_va < m2.va_range.end),
460 ensures
461 self.split_while_huge(size).mappings.contains(m2),
462 decreases
463 if self.present() {
464 self.query_mapping().page_size as int
465 } else {
466 0
467 },
468 {
469 if self.present() {
470 let m = self.query_mapping();
471 if m.page_size > size {
472 let new_size = m.page_size / NR_ENTRIES;
473 let f = self.mappings.filter(
475 |m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end,
476 );
477 vstd::set::lemma_set_choose_len(f);
478 assert(m.inv());
479 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
481 if m.page_size != 2097152 && m.page_size != 1073741824 {
482 assert(false);
483 }
484 };
485 let new_self = self.split_if_mapped_huge_spec(new_size);
486 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
487 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
488 new_self.split_while_huge_locality(size, m2);
489 }
490 }
491 }
492
493 #[verifier::rlimit(120)]
501 pub proof fn split_while_huge_locality_absent(self, size: usize, m2: Mapping)
502 requires
503 self.inv(),
504 size >= PAGE_SIZE,
505 !self.mappings.contains(m2),
506 self.present() ==> Mapping::disjoint_vaddrs(m2, self.query_mapping()),
507 ensures
508 !self.split_while_huge(size).mappings.contains(m2),
509 decreases
510 if self.present() {
511 self.query_mapping().page_size as int
512 } else {
513 0
514 },
515 {
516 if self.present() {
517 let m = self.query_mapping();
518 if m.page_size > size {
519 let new_size = m.page_size / NR_ENTRIES;
520 let f = self.mappings.filter(
522 |m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end,
523 );
524 vstd::set::lemma_set_choose_len(f);
525 assert(m.inv());
527 assert(m.page_size % new_size == 0) by {
528 assert(2097152usize % (2097152usize / 512usize) == 0) by (compute_only);
529 assert(1073741824usize % (1073741824usize / 512usize) == 0) by (compute_only);
530 };
531 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
532 if m.page_size != 2097152 && m.page_size != 1073741824 {
533 assert(false);
534 }
535 };
536 let new_self = self.split_if_mapped_huge_spec(new_size);
537 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
538 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
539 assert(new_self.present() ==> Mapping::disjoint_vaddrs(
540 m2,
541 new_self.query_mapping(),
542 )) by {
543 if new_self.present() {
544 let new_m = new_self.query_mapping();
545 let nf = new_self.mappings.filter(
546 |m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end,
547 );
548 vstd::set::lemma_set_choose_len(nf);
549 if self.mappings.contains(new_m) && new_m != m {
550 assert(false);
551 }
552 let new_mappings = Set::<int>::range(
553 0int,
554 m.page_size as int / new_size as int,
555 ).map(|n: int| Self::split_index(m, new_size, n as usize));
556 let k = choose|k: int|
557 0 <= k < m.page_size as int / new_size as int
558 && #[trigger] Self::split_index(m, new_size, k as usize) == new_m;
559 }
560 };
561 new_self.split_while_huge_locality_absent(size, m2);
562 }
563 }
564 }
565
566 pub proof fn split_if_mapped_huge_spec_refinement(self, new_size: usize, e: Mapping)
571 requires
572 self.inv(),
573 self.present(),
574 new_size > 0,
575 self.query_mapping().page_size > new_size,
576 self.query_mapping().page_size % new_size == 0,
577 self.split_if_mapped_huge_spec(new_size).mappings.contains(e),
578 ensures
579 self.mappings.contains(e) || {
580 let parent = self.query_mapping();
581 &&& self.mappings.contains(parent)
582 &&& parent.va_range.start <= e.va_range.start
583 &&& e.va_range.end <= parent.va_range.end
584 &&& e.pa_range.start == (parent.pa_range.start + (e.va_range.start
585 - parent.va_range.start)) as Paddr
586 &&& e.property == parent.property
587 },
588 {
589 let qm = self.query_mapping();
590 let ps = qm.page_size;
591 let ns: int = new_size as int;
592 let count: int = ps as int / ns;
593 let new_self = self.split_if_mapped_huge_spec(new_size);
594 let domain = Set::<int>::range(0int, count);
595 let new_mappings = domain.map(|n: int| Self::split_index(qm, new_size, n as usize));
596
597 let f = self.mappings.filter(
599 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
600 );
601 vstd::set::lemma_set_choose_len(f);
602 assert(qm.inv());
603
604 if self.mappings.remove(qm).contains(e) {
605 } else {
606 let k = choose|k: int|
607 0 <= k < count && #[trigger] Self::split_index(qm, new_size, k as usize) == e;
608
609 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, ns);
610
611 vstd::arithmetic::mul::lemma_mul_inequality(k + 1, count, ns);
612 }
613 }
614
615 pub proof fn split_while_huge_refinement(self, size: usize, m: Mapping)
616 requires
617 self.inv(),
618 size >= PAGE_SIZE,
619 self.split_while_huge(size).mappings.contains(m),
620 ensures
621 self.mappings.contains(m) || exists|parent: Mapping| #[trigger]
622 self.mappings.contains(parent) && parent.va_range.start <= m.va_range.start
623 && m.va_range.end <= parent.va_range.end && m.pa_range.start == (
624 parent.pa_range.start + (m.va_range.start - parent.va_range.start)) as Paddr
625 && m.property == parent.property,
626 decreases
627 if self.present() {
628 self.query_mapping().page_size as int
629 } else {
630 0
631 },
632 {
633 if self.present() {
634 let qm = self.query_mapping();
635 if qm.page_size > size {
636 let new_size = qm.page_size / NR_ENTRIES;
637 let new_self = self.split_if_mapped_huge_spec(new_size);
638
639 let f = self.mappings.filter(
640 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
641 );
642 vstd::set::lemma_set_choose_len(f);
643 assert(qm.inv());
644 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
645 if qm.page_size != 2097152 && qm.page_size != 1073741824 {
646 assert(false);
647 }
648 };
649 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
650 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
651
652 new_self.split_while_huge_refinement(size, m);
653
654 if new_self.mappings.contains(m) {
655 } else {
656 let p = choose|p: Mapping| #[trigger]
657 new_self.mappings.contains(p) && p.va_range.start <= m.va_range.start
658 && m.va_range.end <= p.va_range.end && m.pa_range.start == (
659 p.pa_range.start + (m.va_range.start - p.va_range.start)) as Paddr
660 && m.property == p.property;
661 if !self.mappings.contains(p) {
662 }
663 }
664 }
665 }
666 }
667
668 pub proof fn split_while_huge_preserves_empty_prefix(
670 self,
671 split_view: CursorView<C>,
672 size: usize,
673 m: Mapping,
674 )
675 requires
676 self.inv(),
677 size >= PAGE_SIZE,
678 self.cur_va <= split_view.cur_va,
679 self.cur_va < split_view.cur_va ==> !self.present(),
680 self.mappings.filter(|m2: Mapping| self.cur_va <= m2.va_range.start < split_view.cur_va)
681 == Set::<Mapping>::empty(),
682 self.split_while_huge(size).mappings.contains(m),
683 self.cur_va <= m.va_range.start < split_view.cur_va,
684 ensures
685 self.mappings.contains(m),
686 {
687 }
688
689 pub proof fn split_while_huge_disjoint(self, size: usize, other: Set<Mapping>)
699 requires
700 self.inv(),
701 size >= PAGE_SIZE,
702 forall|m: Mapping, x: Mapping| #[trigger]
703 self.mappings.contains(m) && #[trigger] other.contains(x)
704 ==> Mapping::disjoint_vaddrs(m, x),
705 ensures
706 self.split_while_huge(size).mappings.disjoint(other),
707 decreases
708 if self.present() {
709 self.query_mapping().page_size as int
710 } else {
711 0
712 },
713 {
714 if !self.present() {
715 assert forall|x: Mapping|
717 #![trigger other.contains(x)]
718 other.contains(x) implies !self.split_while_huge(size).mappings.contains(x) by {
719 if self.mappings.contains(x) {
720 assert(x.inv());
721 }
722 };
723 return;
724 }
725 let m = self.query_mapping();
726 if m.page_size <= size {
727 assert forall|x: Mapping|
728 #![trigger other.contains(x)]
729 other.contains(x) implies !self.split_while_huge(size).mappings.contains(x) by {
730 if self.mappings.contains(x) {
731 assert(x.inv());
732 }
733 };
734 return;
735 }
736 let new_size = m.page_size / NR_ENTRIES;
737
738 let f = self.mappings.filter(
740 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
741 );
742 vstd::set::lemma_set_choose_len(f);
743 assert(m.inv());
744
745 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
746 if m.page_size == 2097152 {
747 } else if m.page_size == 1073741824 {
748 } else {
749 assert(false);
750 }
751 };
752 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
753 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
754 let new_self = self.split_if_mapped_huge_spec(new_size);
755
756 assert forall|m2: Mapping, x: Mapping| #[trigger]
758 new_self.mappings.contains(m2) && #[trigger] other.contains(
759 x,
760 ) implies Mapping::disjoint_vaddrs(m2, x) by {
761 if self.mappings.contains(m2) {
762 } else {
764 let new_mappings = Set::<int>::range(
766 0int,
767 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 && #[trigger] Self::split_index(
771 m,
772 new_size,
773 k as usize,
774 ) == m2;
775 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(
776 m.page_size as int,
777 new_size as int,
778 );
779 }
780 };
781
782 new_self.split_while_huge_disjoint(size, other);
783 }
784}
785
786impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
787 proof fn query_mapping_from_subtree(self, qm: Mapping)
792 requires
793 self.inv(),
794 self.in_locked_range(),
795 self@.inv(),
796 self@.present(),
797 qm == self@.query_mapping(),
798 ensures
799 PageTableOwner(self.cur_subtree()).view_rec(self.cur_subtree().value().path).contains(
800 qm,
801 ),
802 {
803 let f = self@.mappings.filter(
804 |m2: Mapping| m2.va_range.start <= self@.cur_va < m2.va_range.end,
805 );
806 lemma_set_choose_len(f);
807 self.mapping_covering_cur_va_from_cur_subtree(qm);
808 }
809
810 pub proof fn split_while_huge_node_noop(self)
811 requires
812 self.inv(),
813 self.in_locked_range(),
814 self.cur_entry_owner().is_node(),
815 self.level > 1,
816 ensures
817 self@.split_while_huge(page_size((self.level - 1) as PagingLevel)) == self@,
818 {
819 self.view_preserves_inv();
820 if self@.present() {
821 let subtree = self.cur_subtree();
822 let path = subtree.value().path;
823 let qm = self@.query_mapping();
824 self.query_mapping_from_subtree(qm);
825 PageTableOwner(subtree).view_rec_node_page_size_bound(path, qm);
826 }
827 }
828
829 pub proof fn split_while_huge_absent_noop(self, size: usize)
832 requires
833 self.inv(),
834 self.in_locked_range(),
835 self.cur_entry_owner().is_absent(),
836 ensures
837 self@.split_while_huge(size) == self@,
838 {
839 self.view_preserves_inv();
840 self.cur_entry_absent_not_present();
841 }
842
843 pub proof fn split_while_huge_at_level_noop(self)
844 requires
845 self.inv(),
846 self.in_locked_range(),
847 ensures
848 self@.split_while_huge(page_size(self.level as PagingLevel)) == self@,
849 {
850 self.view_preserves_inv();
851 if self@.present() {
852 self.cur_subtree_inv();
853 let subtree = self.cur_subtree();
854 let path = subtree.value().path;
855 let qm = self@.query_mapping();
856 self.query_mapping_from_subtree(qm);
857 PageTableOwner(subtree).view_rec_page_size_bound(path, qm);
858 }
859 }
860
861 pub proof fn map_branch_frame_split_while_huge(
871 self,
872 owner0: Self,
873 owner_before_frame: Self,
874 level_before_frame: int,
875 )
876 requires
877 self.inv(),
878 owner0.inv(),
879 owner_before_frame.inv(),
880 1 <= level_before_frame - 1,
881 level_before_frame <= NR_LEVELS,
882 self.level == (level_before_frame - 1) as u8,
883 owner_before_frame@ == owner0@.split_while_huge(
884 page_size(level_before_frame as PagingLevel),
885 ),
886 self@ == owner_before_frame@.split_if_mapped_huge_spec(
887 page_size((level_before_frame - 1) as PagingLevel),
888 ),
889 owner_before_frame@.present(),
894 owner_before_frame@.query_mapping().page_size == page_size(
895 level_before_frame as PagingLevel,
896 ),
897 {
898 owner0.view_preserves_inv();
899 owner_before_frame.view_preserves_inv();
900 }
901
902 pub proof fn find_next_split_push_equals_split_while_huge(self, old_view: CursorView<C>)
905 requires
906 self.inv(),
907 old_view.inv(),
908 self.cur_entry_owner().is_frame(),
909 self@.cur_va == old_view.cur_va,
910 old_view.present(),
911 old_view.query_mapping().page_size > page_size(self.level as PagingLevel),
912 old_view.query_mapping().page_size / NR_ENTRIES == page_size(self.level as PagingLevel),
913 old_view.query_mapping().page_size % page_size(self.level as PagingLevel) == 0,
914 self@.mappings =~= old_view.split_if_mapped_huge_spec(
915 page_size(self.level as PagingLevel),
916 ).mappings,
917 ensures
918 self@.mappings == old_view.split_while_huge(
919 page_size(self.level as PagingLevel),
920 ).mappings,
921 {
922 let ps = page_size(self.level as PagingLevel);
923 let m = old_view.query_mapping();
924 let f = old_view.mappings.filter(
925 |m2: Mapping| m2.va_range.start <= old_view.cur_va < m2.va_range.end,
926 );
927 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_spec_values();
928 old_view.split_while_huge_one_step(ps);
929 }
930
931 pub proof fn split_while_huge_cur_va_independent(
939 v1: CursorView<C>,
940 v2: CursorView<C>,
941 size: usize,
942 )
943 requires
944 v1.inv(),
945 v2.inv(),
946 v1.mappings =~= v2.mappings,
947 v1.cur_va <= v2.cur_va,
948 v1.mappings.filter(
950 |m: Mapping| v1.cur_va <= m.va_range.start && m.va_range.start < v2.cur_va,
951 ) =~= Set::<Mapping>::empty(),
952 !v1.present() && v2.present() ==> v2.query_mapping().page_size <= size,
958 v1.cur_va < v2.cur_va ==> !v1.present(),
961 ensures
962 v1.split_while_huge(size).mappings == v2.split_while_huge(size).mappings,
963 {
964 }
965}
966
967}