1use vstd::{prelude::*, set_lib::*};
2use vstd_extra::{arithmetic::*, ghost_tree::*, ownership::*};
3
4use crate::specs::{
5 arch::*,
6 mm::page_table::{cursor::owners::*, owners::PageTableOwner, *},
7};
8
9use crate::arch::mm::PagingConsts;
10use crate::mm::{
11 Paddr, PagingConstsTrait, PagingLevel, Vaddr, page_prop::PageProperty, page_size, page_table::*,
12};
13
14verus! {
15
16broadcast use group_ghost_tree_lemmas;
17
18impl<C: PageTableConfig> CursorView<C> {
19 proof fn lemma_split_index_inv(m: Mapping, new_size: usize, k: int)
20 requires
21 m.inv(),
22 new_size > 0,
23 m.page_size % new_size == 0,
24 set![4096usize, 2097152, 1073741824].contains(new_size),
25 m.va_range.start % new_size as int == 0,
26 0 <= k < m.page_size as int / new_size as int,
27 ensures
28 Self::split_index(m, new_size, k as usize).inv(),
29 m.va_range.start <= Self::split_index(m, new_size, k as usize).va_range.start,
30 Self::split_index(m, new_size, k as usize).va_range.end <= m.va_range.end,
31 {
32 let ps = m.page_size as int;
33 let ns = new_size as int;
34 let count = ps / ns;
35 let sub = Self::split_index(m, new_size, k as usize);
36
37 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps, ns);
38 assert(ps == count * ns) by {
39 vstd::arithmetic::mul::lemma_mul_is_commutative(ns, count);
40 };
41 vstd::arithmetic::mul::lemma_mul_inequality(k + 1, count, ns);
42 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(ns, k, 1);
43
44 vstd::arithmetic::div_mod::lemma_mod_mod(m.pa_range.start as int, ns, count);
45 assert((m.pa_range.start as int) % ns == 0);
46 vstd::arithmetic::div_mod::lemma_mod_multiples_basic(k, ns);
47 vstd::arithmetic::div_mod::lemma_mod_multiples_basic(k + 1, ns);
48 vstd_extra::arithmetic::lemma_mod_0_add(m.pa_range.start as int, k * ns, ns);
49 vstd_extra::arithmetic::lemma_mod_0_add(m.pa_range.start as int, (k + 1) * ns, ns);
50 vstd_extra::arithmetic::lemma_mod_0_add(m.va_range.start, k * ns, ns);
51 vstd_extra::arithmetic::lemma_mod_0_add(m.va_range.start, (k + 1) * ns, ns);
52
53 assert(sub.inv());
54 }
55
56 pub proof fn split_if_mapped_huge_spec_preserves_present(v: Self, new_size: usize)
60 requires
61 v.inv(),
62 v.present(),
63 new_size > 0,
64 v.query_mapping().page_size > 0,
65 v.query_mapping().page_size % new_size == 0,
66 ensures
67 v.split_if_mapped_huge_spec(new_size).present(),
68 {
69 let cur_va = v.cur_va;
70 let m = v.query_mapping();
71 let ps = m.page_size;
72
73 v.lemma_query_mapping();
74
75 let diff: int = cur_va - m.va_range.start;
76 let ki: int = diff / new_size as int;
77 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(diff, new_size as int);
78
79 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, new_size as int);
80 assert(ki < ps as int / new_size as int) by {
81 if ki >= ps as int / new_size as int {
82 vstd::arithmetic::mul::lemma_mul_inequality(
83 ps as int / new_size as int,
84 ki,
85 new_size as int,
86 );
87 }
88 };
89
90 let sub = Self::split_index(m, new_size, ki as usize);
91
92 assert(ki * new_size >= 0);
93 assert((ki + 1) * new_size <= ps) by {
94 vstd::arithmetic::mul::lemma_mul_inequality(
95 ki + 1,
96 ps as int / new_size as int,
97 new_size as int,
98 );
99 };
100
101 vstd::arithmetic::mul::lemma_mul_is_distributive_add(new_size as int, ki, 1 as int);
102
103 let new_self = v.split_if_mapped_huge_spec(new_size);
104 let domain = Set::<int>::range(0int, ps as int / new_size as int);
105 assert(domain.contains(ki));
106
107 let new_filter = new_self.mappings.filter(
108 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end,
109 );
110 vstd::set::lemma_set_contains_len(new_filter, sub);
111 }
112
113 pub proof fn split_if_mapped_huge_spec_decreases_page_size(v: Self, new_size: usize)
120 requires
121 v.inv(),
122 v.present(),
123 new_size > 0,
124 v.query_mapping().page_size > new_size,
125 v.query_mapping().page_size % new_size == 0,
126 ensures
127 v.split_if_mapped_huge_spec(new_size).present(),
128 v.split_if_mapped_huge_spec(new_size).query_mapping().page_size
129 < v.query_mapping().page_size,
130 {
131 Self::split_if_mapped_huge_spec_preserves_present(v, new_size);
132
133 let cur_va = v.cur_va;
134 let m = v.query_mapping();
135 let new_self = v.split_if_mapped_huge_spec(new_size);
136 let m2 = new_self.query_mapping();
137 let ps = m.page_size;
138
139 v.lemma_query_mapping();
140
141 assert(new_self.mappings.contains(m2) && m2.va_range.start <= cur_va && cur_va
142 < m2.va_range.end) by {
143 let f = new_self.mappings.filter(
144 |m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end,
145 );
146 vstd::set::lemma_set_choose_len(f);
147 };
148
149 if v.mappings.contains(m2) && m2 != m {
150 assert(false);
151 }
152 let new_mappings = Set::<int>::range(0int, ps as int / new_size as int).map(
153 |n: int| Self::split_index(m, new_size, n as usize),
154 );
155 let k = choose|k: int|
156 0 <= k < ps as int / new_size as int && #[trigger] Self::split_index(
157 m,
158 new_size,
159 k as usize,
160 ) == m2;
161 }
162
163 #[verifier::rlimit(80)]
169 #[verifier::spinoff_prover]
170 pub proof fn split_if_mapped_huge_spec_preserves_inv(v: Self, new_size: usize)
171 requires
172 v.inv(),
173 v.present(),
174 new_size > 0,
175 v.query_mapping().page_size > new_size,
176 v.query_mapping().page_size % new_size == 0,
177 set![4096usize, 2097152, 1073741824].contains(new_size),
178 ensures
179 v.split_if_mapped_huge_spec(new_size).inv(),
180 {
181 let cur_va = v.cur_va;
182 let m = v.query_mapping();
183 let ps = m.page_size;
184 let ns: int = new_size as int;
185 let count: int = ps as int / ns;
186
187 v.lemma_query_mapping();
189 assert(m.va_range.start % new_size as int == 0) by {
190 vstd::arithmetic::mul::lemma_mul_is_commutative(count, ns);
191 vstd::arithmetic::div_mod::lemma_mod_mod(m.va_range.start as int, ns, count);
192 };
193
194 let domain = Set::<int>::range(0int, count);
195 let new_mappings = domain.map(|n: int| Self::split_index(m, new_size, n as usize));
196 let new_self = v.split_if_mapped_huge_spec(new_size);
197
198 assert forall|m2: Mapping| #[trigger] new_self.mappings.contains(m2) implies m2.inv() by {
199 if v.mappings.contains(m2) && m2 != m {
200 } else {
201 let k = choose|k: int|
202 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == m2;
203 Self::lemma_split_index_inv(m, new_size, k);
204 }
205 };
206
207 assert forall|m2: Mapping| #[trigger] new_self.mappings.contains(m2) implies {
208 &&& page_table_managed_start_spec::<C>() <= m2.va_range.start
209 &&& m2.va_range.end <= page_table_managed_end_spec::<C>()
210 } by {
211 if v.mappings.contains(m2) && m2 != m {
212 } else {
213 let k = choose|k: int|
214 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == m2;
215 Self::lemma_split_index_inv(m, new_size, k);
216 }
217 };
218 }
219
220 pub broadcast proof fn lemma_split_while_huge_preserves_cur_va(self, size: usize)
222 requires
223 self.inv(),
224 size >= PAGE_SIZE,
225 ensures
226 #[trigger] self.split_while_huge(size).cur_va == self.cur_va,
227 decreases
228 if self.present() {
229 self.query_mapping().page_size as int
230 } else {
231 0
232 },
233 {
234 if self.present() {
235 let m = self.query_mapping();
236 if m.page_size > size {
237 let new_size = m.page_size / NR_ENTRIES;
238 let new_self = self.split_if_mapped_huge_spec(new_size);
239 self.lemma_query_mapping();
241 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
243 if m.page_size != 2097152 && m.page_size != 1073741824 {
244 assert(false);
245 }
246 };
247 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
248
249 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
250 Self::lemma_split_while_huge_preserves_cur_va(new_self, size);
251 }
252 }
253 }
254
255 pub proof fn lemma_split_while_huge_preserves_inv(self, size: usize)
257 requires
258 self.inv(),
259 size >= PAGE_SIZE,
260 ensures
261 self.split_while_huge(size).inv(),
262 decreases
263 if self.present() {
264 self.query_mapping().page_size as int
265 } else {
266 0
267 },
268 {
269 if self.present() {
270 let m = self.query_mapping();
271 if m.page_size > size {
272 let new_size = m.page_size / NR_ENTRIES;
273 let new_self = self.split_if_mapped_huge_spec(new_size);
274 self.lemma_query_mapping();
276 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
277 if m.page_size != 2097152 && m.page_size != 1073741824 {
278 assert(false);
279 }
280 };
281 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
282 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
283 new_self.lemma_split_while_huge_preserves_inv(size);
284 }
285 }
286 }
287
288 pub proof fn lemma_split_while_huge_compose(self, s1: usize, s2: usize)
292 requires
293 self.inv(),
294 s1 >= PAGE_SIZE,
295 s2 <= s1,
296 ensures
297 self.split_while_huge(s2) == self.split_while_huge(s1).split_while_huge(s2),
298 decreases
299 if self.present() {
300 self.query_mapping().page_size as int
301 } else {
302 0
303 },
304 {
305 if !self.present() {
306 return;
307 }
308 let m = self.query_mapping();
309 if m.page_size <= s1 {
310 return;
311 }
312 let new_size = m.page_size / NR_ENTRIES;
313 self.lemma_query_mapping();
314 assert(set![4096usize, 2097152, 1073741824].contains(new_size) && m.page_size % new_size
315 == 0) by {
316 if m.page_size == 2097152 {
317 assert(2097152usize % (2097152usize / 512usize) == 0) by (compute_only);
318 } else {
319 assert(1073741824usize % (1073741824usize / 512usize) == 0) by (compute_only);
320 }
321 };
322 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
323 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
324 self.split_if_mapped_huge_spec(new_size).lemma_split_while_huge_compose(s1, s2);
325 }
326
327 pub proof fn split_while_huge_noop_implies_page_size_le(self, size: usize)
330 requires
331 self.inv(),
332 size >= PAGE_SIZE,
333 self.split_while_huge(size) == self,
334 self.present(),
335 ensures
336 self.query_mapping().page_size <= size,
337 {
338 let m = self.query_mapping();
339 if m.page_size > size {
340 let new_size = m.page_size / NR_ENTRIES;
341 self.lemma_query_mapping();
342 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
343 if m.page_size == 2097152 {
344 } else if m.page_size == 1073741824 {
345 } else {
346 assert(false);
347 }
348 };
349 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
350 let new_self = self.split_if_mapped_huge_spec(new_size);
351 new_self.split_while_huge_refinement(size, m);
352 let p = choose|p: Mapping| #[trigger]
353 new_self.mappings.contains(p) && p.va_range.start <= m.va_range.start
354 && m.va_range.end <= p.va_range.end && m.pa_range.start == (p.pa_range.start + (
355 m.va_range.start - p.va_range.start)) as Paddr && m.property == p.property;
356 if self.mappings.contains(p) {
357 } else {
358 let new_mappings = Set::<int>::range(
359 0int,
360 m.page_size as int / new_size as int,
361 ).map(|n: int| Self::split_index(m, new_size, n as usize));
362 let k = choose|k: int|
363 0 <= k < m.page_size as int / new_size as int && #[trigger] Self::split_index(
364 m,
365 new_size,
366 k as usize,
367 ) == p;
368 }
369 }
370 }
371
372 pub proof fn split_while_huge_one_step(self, size: usize)
382 requires
383 self.inv(),
384 self.present(),
385 self.query_mapping().page_size > size,
386 self.query_mapping().page_size / NR_ENTRIES == size,
387 self.query_mapping().page_size % size == 0,
388 set![4096usize, 2097152, 1073741824].contains(size),
389 ensures
390 self.split_while_huge(size).mappings == self.split_if_mapped_huge_spec(size).mappings,
391 {
392 let m = self.query_mapping();
393 let new_size = m.page_size / NR_ENTRIES;
394 self.lemma_query_mapping();
395 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
396 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
397 let new_self = self.split_if_mapped_huge_spec(new_size);
398
399 assert(new_self.query_mapping().page_size == new_size) by {
400 let new_m = new_self.query_mapping();
401 new_self.lemma_query_mapping();
402 if self.mappings.contains(new_m) && new_m != m {
403 assert(false);
404 }
405 let new_mappings = Set::<int>::range(0int, m.page_size as int / new_size as int).map(
406 |n: int| Self::split_index(m, new_size, n as usize),
407 );
408 };
409 assert(new_self.split_while_huge(size) == new_self);
410 }
411
412 #[verifier::rlimit(80)]
415 pub proof fn split_while_huge_locality(self, size: usize, m2: Mapping)
416 requires
417 self.inv(),
418 size >= PAGE_SIZE,
419 self.mappings.contains(m2),
420 !(m2.va_range.start <= self.cur_va < m2.va_range.end),
421 ensures
422 self.split_while_huge(size).mappings.contains(m2),
423 decreases
424 if self.present() {
425 self.query_mapping().page_size as int
426 } else {
427 0
428 },
429 {
430 if self.present() {
431 let m = self.query_mapping();
432 if m.page_size > size {
433 let new_size = m.page_size / NR_ENTRIES;
434 self.lemma_query_mapping();
436 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
438 if m.page_size != 2097152 && m.page_size != 1073741824 {
439 assert(false);
440 }
441 };
442 let new_self = self.split_if_mapped_huge_spec(new_size);
443 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
444 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
445 new_self.split_while_huge_locality(size, m2);
446 }
447 }
448 }
449
450 pub proof fn split_if_mapped_huge_spec_refinement(self, new_size: usize, e: Mapping)
455 requires
456 self.inv(),
457 self.present(),
458 new_size > 0,
459 self.query_mapping().page_size > new_size,
460 self.query_mapping().page_size % new_size == 0,
461 self.split_if_mapped_huge_spec(new_size).mappings.contains(e),
462 ensures
463 self.mappings.contains(e) || {
464 let parent = self.query_mapping();
465 &&& self.mappings.contains(parent)
466 &&& parent.va_range.start <= e.va_range.start
467 &&& e.va_range.end <= parent.va_range.end
468 &&& e.pa_range.start == (parent.pa_range.start + (e.va_range.start
469 - parent.va_range.start)) as Paddr
470 &&& e.property == parent.property
471 },
472 {
473 let qm = self.query_mapping();
474 let ps = qm.page_size;
475 let ns: int = new_size as int;
476 let count: int = ps as int / ns;
477 let new_self = self.split_if_mapped_huge_spec(new_size);
478 let domain = Set::<int>::range(0int, count);
479 let new_mappings = domain.map(|n: int| Self::split_index(qm, new_size, n as usize));
480
481 self.lemma_query_mapping();
483
484 if self.mappings.remove(qm).contains(e) {
485 } else {
486 assert(new_mappings.contains(e));
487 let k = choose|k: int|
488 0 <= k < count && #[trigger] Self::split_index(qm, new_size, k as usize) == e;
489
490 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, ns);
491 vstd::arithmetic::div_mod::lemma_div_nonincreasing(ps as int, ns);
492
493 vstd::arithmetic::mul::lemma_mul_inequality(k + 1, count, ns);
494 }
495 }
496
497 pub proof fn split_while_huge_refinement(self, size: usize, m: Mapping)
498 requires
499 self.inv(),
500 size >= PAGE_SIZE,
501 self.split_while_huge(size).mappings.contains(m),
502 ensures
503 self.mappings.contains(m) || exists|parent: Mapping| #[trigger]
504 self.mappings.contains(parent) && parent.va_range.start <= m.va_range.start
505 && m.va_range.end <= parent.va_range.end && m.pa_range.start == (
506 parent.pa_range.start + (m.va_range.start - parent.va_range.start)) as Paddr
507 && m.property == parent.property,
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 let qm = self.query_mapping();
517 if qm.page_size > size {
518 let new_size = qm.page_size / NR_ENTRIES;
519 let new_self = self.split_if_mapped_huge_spec(new_size);
520
521 self.lemma_query_mapping();
522 assert(self.mappings.filter(
523 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
524 ).contains(qm));
525 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
526 if qm.page_size != 2097152 && qm.page_size != 1073741824 {
527 assert(false);
528 }
529 };
530 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
531 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
532
533 new_self.split_while_huge_refinement(size, m);
534 new_self.lemma_split_while_huge_preserves_inv(size);
535
536 if new_self.mappings.contains(m) {
537 self.split_if_mapped_huge_spec_refinement(new_size, m);
538 } else {
539 let p = choose|p: Mapping| #[trigger]
540 new_self.mappings.contains(p) && p.va_range.start <= m.va_range.start
541 && m.va_range.end <= p.va_range.end && m.pa_range.start == (
542 p.pa_range.start + (m.va_range.start - p.va_range.start)) as Paddr
543 && m.property == p.property;
544 self.split_if_mapped_huge_spec_refinement(new_size, p);
545 if !self.mappings.contains(p) {
546 assert(exists|parent: Mapping| #[trigger]
547 self.mappings.contains(parent) && parent.va_range.start
548 <= m.va_range.start && m.va_range.end <= parent.va_range.end
549 && m.pa_range.start == (parent.pa_range.start + (m.va_range.start
550 - parent.va_range.start)) as Paddr && m.property == parent.property)
551 by {
552 let parent = qm;
553 }
554 } else {
555 assert(exists|parent: Mapping| #[trigger]
556 self.mappings.contains(parent) && parent.va_range.start
557 <= m.va_range.start && m.va_range.end <= parent.va_range.end
558 && m.pa_range.start == (parent.pa_range.start + (m.va_range.start
559 - parent.va_range.start)) as Paddr && m.property == parent.property)
560 by {
561 let parent = p;
562 }
563 }
564 }
565 }
566 }
567 }
568
569 pub proof fn split_while_huge_disjoint(self, size: usize, other: Set<Mapping>)
579 requires
580 self.inv(),
581 size >= PAGE_SIZE,
582 forall|m: Mapping, x: Mapping| #[trigger]
583 self.mappings.contains(m) && #[trigger] other.contains(x)
584 ==> Mapping::disjoint_vaddrs(m, x),
585 ensures
586 self.split_while_huge(size).mappings.disjoint(other),
587 decreases
588 if self.present() {
589 self.query_mapping().page_size as int
590 } else {
591 0
592 },
593 {
594 if !self.present() {
595 assert forall|x: Mapping|
597 #![trigger other.contains(x)]
598 other.contains(x) implies !self.split_while_huge(size).mappings.contains(x) by {
599 if self.mappings.contains(x) {
600 assert(x.inv());
601 }
602 };
603 return;
604 }
605 let m = self.query_mapping();
606 if m.page_size <= size {
607 assert forall|x: Mapping|
608 #![trigger other.contains(x)]
609 other.contains(x) implies !self.split_while_huge(size).mappings.contains(x) by {
610 if self.mappings.contains(x) {
611 assert(x.inv());
612 }
613 };
614 return;
615 }
616 let new_size = m.page_size / NR_ENTRIES;
617
618 self.lemma_query_mapping();
620
621 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
622 if m.page_size == 2097152 {
623 } else if m.page_size == 1073741824 {
624 } else {
625 assert(false);
626 }
627 };
628 assert(m.page_size % new_size == 0) by {
629 assert(2097152usize % (2097152usize / 512usize) == 0) by (compute_only);
630 assert(1073741824usize % (1073741824usize / 512usize) == 0) by (compute_only);
631 };
632 assert(m.page_size > new_size) by {
633 assert(2097152usize > 2097152usize / 512usize) by (compute_only);
634 assert(1073741824usize > 1073741824usize / 512usize) by (compute_only);
635 };
636 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
637 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
638 let new_self = self.split_if_mapped_huge_spec(new_size);
639
640 assert forall|m2: Mapping, x: Mapping| #[trigger]
642 new_self.mappings.contains(m2) && #[trigger] other.contains(
643 x,
644 ) implies Mapping::disjoint_vaddrs(m2, x) by {
645 if self.mappings.contains(m2) {
646 } else {
648 Self::split_if_mapped_huge_spec_refinement(self, new_size, m2);
651 assert(Mapping::disjoint_vaddrs(m, x));
652 }
653 };
654
655 new_self.split_while_huge_disjoint(size, other);
656 }
657}
658
659impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
660 pub proof fn query_mapping_from_subtree(self, qm: Mapping)
665 requires
666 self.inv(),
667 self.in_barrier_va(),
668 self@.inv(),
669 self@.present(),
670 qm == self@.query_mapping(),
671 ensures
672 PageTableOwner(self.cur_subtree()).view_rec(self.cur_subtree().value().path).contains(
673 qm,
674 ),
675 {
676 self@.lemma_query_mapping();
677 self.mapping_covering_cur_va_from_cur_subtree(qm);
678 }
679
680 pub proof fn split_while_huge_node_noop(self)
681 requires
682 self.inv(),
683 self.in_barrier_va(),
684 self.cur_entry_owner().is_node(),
685 self.level > 1,
686 ensures
687 self@.split_while_huge(page_size::<PagingConsts>((self.level - 1) as PagingLevel))
688 == self@,
689 {
690 self.view_preserves_inv();
691 if self@.present() {
692 let subtree = self.cur_subtree();
693 let path = subtree.value().path;
694 let qm = self@.query_mapping();
695 self.query_mapping_from_subtree(qm);
696 PageTableOwner(subtree).lemma_view_rec_node_page_size_bound(path, qm);
697 }
698 }
699
700 pub proof fn split_while_huge_absent_noop(self, size: usize)
703 requires
704 self.inv(),
705 self.in_barrier_va(),
706 self.cur_entry_owner().is_absent(),
707 ensures
708 self@.split_while_huge(size) == self@,
709 {
710 self.view_preserves_inv();
711 self.lemma_cur_entry_absent_not_present();
712 }
713
714 pub proof fn lemma_split_while_huge_at_level_noop(self)
715 requires
716 self.inv(),
717 self.in_barrier_va(),
718 ensures
719 self@.split_while_huge(page_size::<PagingConsts>(self.level as PagingLevel)) == self@,
720 {
721 self.view_preserves_inv();
722 if self@.present() {
723 self.lemma_cur_subtree_inv();
724 let subtree = self.cur_subtree();
725 let path = subtree.value().path;
726 let qm = self@.query_mapping();
727 self.query_mapping_from_subtree(qm);
728 PageTableOwner(subtree).lemma_view_rec_page_size_bound(path, qm);
729 }
730 }
731
732 pub proof fn find_next_split_push_equals_split_while_huge(self, old_view: CursorView<C>)
735 requires
736 self.inv(),
737 old_view.inv(),
738 self.cur_entry_owner().is_frame(),
739 self@.cur_va == old_view.cur_va,
740 old_view.present(),
741 old_view.query_mapping().page_size > page_size::<PagingConsts>(
742 self.level as PagingLevel,
743 ),
744 old_view.query_mapping().page_size / NR_ENTRIES == page_size::<PagingConsts>(
745 self.level as PagingLevel,
746 ),
747 old_view.query_mapping().page_size % page_size::<PagingConsts>(
748 self.level as PagingLevel,
749 ) == 0,
750 self@.mappings =~= old_view.split_if_mapped_huge_spec(
751 page_size::<PagingConsts>(self.level as PagingLevel),
752 ).mappings,
753 ensures
754 self@ == old_view.split_while_huge(
755 page_size::<PagingConsts>(self.level as PagingLevel),
756 ),
757 {
758 let ps = page_size::<PagingConsts>(self.level as PagingLevel);
759 let m = old_view.query_mapping();
760 let f = old_view.mappings.filter(
761 |m2: Mapping| m2.va_range.start <= old_view.cur_va < m2.va_range.end,
762 );
763 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_spec_values();
764 old_view.split_while_huge_one_step(ps);
765 old_view.lemma_split_while_huge_preserves_cur_va(ps);
766 }
767}
768
769}