1use vstd::{prelude::*, set::lemma_set_choose_len, set_lib::*};
2use vstd_extra::{arithmetic::*, ghost_tree::*, ownership::*};
3
4use crate::specs::{
5 arch::{MAX_PADDR, NR_ENTRIES, NR_LEVELS, PAGE_SIZE},
6 mm::page_table::{Mapping, cursor::owners::*, owners::PageTableOwner, vaddr_range_spec},
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 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
74 let f = v.mappings.filter(
75 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
76 );
77 vstd::set::lemma_set_choose_len(f);
78 };
79 assert(m.inv());
80
81 let diff: int = cur_va - m.va_range.start;
82 let ki: int = diff / new_size as int;
83 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(diff, new_size as int);
84
85 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, new_size as int);
86 assert(ki < ps as int / new_size as int) by {
87 if ki >= ps as int / new_size as int {
88 vstd::arithmetic::mul::lemma_mul_inequality(
89 ps as int / new_size as int,
90 ki,
91 new_size as int,
92 );
93 }
94 };
95
96 let sub = Self::split_index(m, new_size, ki as usize);
97
98 assert(ki * new_size >= 0);
99 assert((ki + 1) * new_size <= ps) by {
100 vstd::arithmetic::mul::lemma_mul_inequality(
101 ki + 1,
102 ps as int / new_size as int,
103 new_size as int,
104 );
105 };
106
107 vstd::arithmetic::mul::lemma_mul_is_distributive_add(new_size as int, ki, 1 as int);
108
109 let new_self = v.split_if_mapped_huge_spec(new_size);
110 let domain = Set::<int>::range(0int, ps as int / new_size as int);
111 assert(domain.contains(ki));
112
113 let new_filter = new_self.mappings.filter(
114 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end,
115 );
116 vstd::set::lemma_set_contains_len(new_filter, sub);
117 }
118
119 pub proof fn split_if_mapped_huge_spec_decreases_page_size(v: Self, new_size: usize)
126 requires
127 v.inv(),
128 v.present(),
129 new_size > 0,
130 v.query_mapping().page_size > new_size,
131 v.query_mapping().page_size % new_size == 0,
132 ensures
133 v.split_if_mapped_huge_spec(new_size).present(),
134 v.split_if_mapped_huge_spec(new_size).query_mapping().page_size
135 < v.query_mapping().page_size,
136 {
137 Self::split_if_mapped_huge_spec_preserves_present(v, new_size);
138
139 let cur_va = v.cur_va;
140 let m = v.query_mapping();
141 let new_self = v.split_if_mapped_huge_spec(new_size);
142 let m2 = new_self.query_mapping();
143 let ps = m.page_size;
144
145 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
146 let f = v.mappings.filter(
147 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
148 );
149 vstd::set::lemma_set_choose_len(f);
150 };
151
152 assert(new_self.mappings.contains(m2) && m2.va_range.start <= cur_va && cur_va
153 < m2.va_range.end) by {
154 let f = new_self.mappings.filter(
155 |m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end,
156 );
157 vstd::set::lemma_set_choose_len(f);
158 };
159
160 if v.mappings.contains(m2) && m2 != m {
161 assert(false);
162 }
163 let new_mappings = Set::<int>::range(0int, ps as int / new_size as int).map(
164 |n: int| Self::split_index(m, new_size, n as usize),
165 );
166 let k = choose|k: int|
167 0 <= k < ps as int / new_size as int && #[trigger] Self::split_index(
168 m,
169 new_size,
170 k as usize,
171 ) == m2;
172 }
173
174 #[verifier::rlimit(80)]
180 #[verifier::spinoff_prover]
181 pub proof fn split_if_mapped_huge_spec_preserves_inv(v: Self, new_size: usize)
182 requires
183 v.inv(),
184 v.present(),
185 new_size > 0,
186 v.query_mapping().page_size > new_size,
187 v.query_mapping().page_size % new_size == 0,
188 set![4096usize, 2097152, 1073741824].contains(new_size),
189 ensures
190 v.split_if_mapped_huge_spec(new_size).inv(),
191 {
192 let cur_va = v.cur_va;
193 let m = v.query_mapping();
194 let ps = m.page_size;
195 let ns: int = new_size as int;
196 let count: int = ps as int / ns;
197
198 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
200 let f = v.mappings.filter(
201 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
202 );
203 vstd::set::lemma_set_choose_len(f);
204 };
205 assert(m.inv());
206 assert(m.va_range.start % new_size as int == 0) by {
207 vstd::arithmetic::mul::lemma_mul_is_commutative(count, ns);
208 vstd::arithmetic::div_mod::lemma_mod_mod(m.va_range.start as int, ns, count);
209 };
210
211 let domain = Set::<int>::range(0int, count);
212 let new_mappings = domain.map(|n: int| Self::split_index(m, new_size, n as usize));
213 let new_self = v.split_if_mapped_huge_spec(new_size);
214
215 assert forall|m2: Mapping| #[trigger] new_self.mappings.contains(m2) implies m2.inv() by {
216 if v.mappings.contains(m2) && m2 != m {
217 } else {
218 let k = choose|k: int|
219 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == m2;
220 Self::lemma_split_index_inv(m, new_size, k);
221 }
222 };
223
224 assert forall|m2: Mapping| #[trigger] new_self.mappings.contains(m2) implies {
225 &&& vaddr_range_spec::<C>().start <= m2.va_range.start
226 &&& m2.va_range.end <= vaddr_range_spec::<C>().end + 1
227 } by {
228 if v.mappings.contains(m2) && m2 != m {
229 } else {
230 let k = choose|k: int|
231 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == m2;
232 Self::lemma_split_index_inv(m, new_size, k);
233 }
234 };
235 }
236
237 pub broadcast proof fn lemma_split_while_huge_preserves_cur_va(self, size: usize)
239 requires
240 self.inv(),
241 size >= PAGE_SIZE,
242 ensures
243 #[trigger] self.split_while_huge(size).cur_va == self.cur_va,
244 decreases
245 if self.present() {
246 self.query_mapping().page_size as int
247 } else {
248 0
249 },
250 {
251 if self.present() {
252 let m = self.query_mapping();
253 if m.page_size > size {
254 let new_size = m.page_size / NR_ENTRIES;
255 let new_self = self.split_if_mapped_huge_spec(new_size);
256 let f = self.mappings.filter(
258 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
259 );
260 vstd::set::lemma_set_choose_len(f);
261 assert(m.inv());
262 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
264 if m.page_size != 2097152 && m.page_size != 1073741824 {
265 assert(false);
266 }
267 };
268 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
269
270 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
271 Self::lemma_split_while_huge_preserves_cur_va(new_self, size);
272 }
273 }
274 }
275
276 pub proof fn lemma_split_while_huge_preserves_inv(self, size: usize)
278 requires
279 self.inv(),
280 size >= PAGE_SIZE,
281 ensures
282 self.split_while_huge(size).inv(),
283 decreases
284 if self.present() {
285 self.query_mapping().page_size as int
286 } else {
287 0
288 },
289 {
290 if self.present() {
291 let m = self.query_mapping();
292 if m.page_size > size {
293 let new_size = m.page_size / NR_ENTRIES;
294 let new_self = self.split_if_mapped_huge_spec(new_size);
295 let f = self.mappings.filter(
297 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
298 );
299 vstd::set::lemma_set_choose_len(f);
300 assert(m.inv());
301 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
302 if m.page_size != 2097152 && m.page_size != 1073741824 {
303 assert(false);
304 }
305 };
306 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
307 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
308 new_self.lemma_split_while_huge_preserves_inv(size);
309 }
310 }
311 }
312
313 pub proof fn split_while_huge_compose(self, s1: usize, s2: usize)
317 requires
318 self.inv(),
319 s1 >= PAGE_SIZE,
320 s2 <= s1,
321 ensures
322 self.split_while_huge(s2) == self.split_while_huge(s1).split_while_huge(s2),
323 decreases
324 if self.present() {
325 self.query_mapping().page_size as int
326 } else {
327 0
328 },
329 {
330 if !self.present() {
331 return;
332 }
333 let m = self.query_mapping();
334 if m.page_size <= s1 {
335 return;
336 }
337 let new_size = m.page_size / NR_ENTRIES;
338 let f = self.mappings.filter(
339 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
340 );
341 vstd::set::lemma_set_choose_len(f);
342 assert(m.inv());
343 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
344 if m.page_size == 2097152 {
345 } else {
346 }
347 };
348 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
349 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
350 self.split_if_mapped_huge_spec(new_size).split_while_huge_compose(s1, s2);
351 }
352
353 pub proof fn split_while_huge_noop_implies_page_size_le(self, size: usize)
356 requires
357 self.inv(),
358 size >= PAGE_SIZE,
359 self.split_while_huge(size) == self,
360 self.present(),
361 ensures
362 self.query_mapping().page_size <= size,
363 {
364 let m = self.query_mapping();
365 if m.page_size > size {
366 let new_size = m.page_size / NR_ENTRIES;
367 let f = self.mappings.filter(
368 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
369 );
370 vstd::set::lemma_set_choose_len(f);
371 assert(m.inv());
372 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
373 if m.page_size == 2097152 {
374 } else if m.page_size == 1073741824 {
375 } else {
376 assert(false);
377 }
378 };
379 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
380 let new_self = self.split_if_mapped_huge_spec(new_size);
381 new_self.split_while_huge_refinement(size, m);
382 let p = choose|p: Mapping| #[trigger]
383 new_self.mappings.contains(p) && p.va_range.start <= m.va_range.start
384 && m.va_range.end <= p.va_range.end && m.pa_range.start == (p.pa_range.start + (
385 m.va_range.start - p.va_range.start)) as Paddr && m.property == p.property;
386 if self.mappings.contains(p) {
387 } else {
388 let new_mappings = Set::<int>::range(
389 0int,
390 m.page_size as int / new_size as int,
391 ).map(|n: int| Self::split_index(m, new_size, n as usize));
392 let k = choose|k: int|
393 0 <= k < m.page_size as int / new_size as int && #[trigger] Self::split_index(
394 m,
395 new_size,
396 k as usize,
397 ) == p;
398 }
399 }
400 }
401
402 pub proof fn split_while_huge_one_step(self, size: usize)
412 requires
413 self.inv(),
414 self.present(),
415 self.query_mapping().page_size > size,
416 self.query_mapping().page_size / NR_ENTRIES == size,
417 self.query_mapping().page_size % size == 0,
418 set![4096usize, 2097152, 1073741824].contains(size),
419 ensures
420 self.split_while_huge(size).mappings == self.split_if_mapped_huge_spec(size).mappings,
421 {
422 let m = self.query_mapping();
423 let new_size = m.page_size / NR_ENTRIES;
424 let f0 = self.mappings.filter(
425 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
426 );
427 vstd::set::lemma_set_choose_len(f0);
428 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
429 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
430 let new_self = self.split_if_mapped_huge_spec(new_size);
431
432 assert(new_self.query_mapping().page_size == new_size) by {
433 let new_m = new_self.query_mapping();
434 let f = new_self.mappings.filter(
435 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end,
436 );
437 vstd::set::lemma_set_choose_len(f);
438 if self.mappings.contains(new_m) && new_m != m {
439 assert(false);
440 }
441 let new_mappings = Set::<int>::range(0int, m.page_size as int / new_size as int).map(
442 |n: int| Self::split_index(m, new_size, n as usize),
443 );
444 };
445 assert(new_self.split_while_huge(size) == new_self);
446 }
447
448 #[verifier::rlimit(80)]
451 pub proof fn split_while_huge_locality(self, size: usize, m2: Mapping)
452 requires
453 self.inv(),
454 size >= PAGE_SIZE,
455 self.mappings.contains(m2),
456 !(m2.va_range.start <= self.cur_va < m2.va_range.end),
457 ensures
458 self.split_while_huge(size).mappings.contains(m2),
459 decreases
460 if self.present() {
461 self.query_mapping().page_size as int
462 } else {
463 0
464 },
465 {
466 if self.present() {
467 let m = self.query_mapping();
468 if m.page_size > size {
469 let new_size = m.page_size / NR_ENTRIES;
470 let f = self.mappings.filter(
472 |m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end,
473 );
474 vstd::set::lemma_set_choose_len(f);
475 assert(m.inv());
476 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
478 if m.page_size != 2097152 && m.page_size != 1073741824 {
479 assert(false);
480 }
481 };
482 let new_self = self.split_if_mapped_huge_spec(new_size);
483 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
484 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
485 new_self.split_while_huge_locality(size, m2);
486 }
487 }
488 }
489
490 pub proof fn split_if_mapped_huge_spec_refinement(self, new_size: usize, e: Mapping)
495 requires
496 self.inv(),
497 self.present(),
498 new_size > 0,
499 self.query_mapping().page_size > new_size,
500 self.query_mapping().page_size % new_size == 0,
501 self.split_if_mapped_huge_spec(new_size).mappings.contains(e),
502 ensures
503 self.mappings.contains(e) || {
504 let parent = self.query_mapping();
505 &&& self.mappings.contains(parent)
506 &&& parent.va_range.start <= e.va_range.start
507 &&& e.va_range.end <= parent.va_range.end
508 &&& e.pa_range.start == (parent.pa_range.start + (e.va_range.start
509 - parent.va_range.start)) as Paddr
510 &&& e.property == parent.property
511 },
512 {
513 let qm = self.query_mapping();
514 let ps = qm.page_size;
515 let ns: int = new_size as int;
516 let count: int = ps as int / ns;
517 let new_self = self.split_if_mapped_huge_spec(new_size);
518 let domain = Set::<int>::range(0int, count);
519 let new_mappings = domain.map(|n: int| Self::split_index(qm, new_size, n as usize));
520
521 let f = self.mappings.filter(
523 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
524 );
525 vstd::set::lemma_set_choose_len(f);
526 assert(qm.inv());
527
528 if self.mappings.remove(qm).contains(e) {
529 } else {
530 let k = choose|k: int|
531 0 <= k < count && #[trigger] Self::split_index(qm, new_size, k as usize) == e;
532
533 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, ns);
534
535 vstd::arithmetic::mul::lemma_mul_inequality(k + 1, count, ns);
536 }
537 }
538
539 pub proof fn split_while_huge_refinement(self, size: usize, m: Mapping)
540 requires
541 self.inv(),
542 size >= PAGE_SIZE,
543 self.split_while_huge(size).mappings.contains(m),
544 ensures
545 self.mappings.contains(m) || exists|parent: Mapping| #[trigger]
546 self.mappings.contains(parent) && parent.va_range.start <= m.va_range.start
547 && m.va_range.end <= parent.va_range.end && m.pa_range.start == (
548 parent.pa_range.start + (m.va_range.start - parent.va_range.start)) as Paddr
549 && m.property == parent.property,
550 decreases
551 if self.present() {
552 self.query_mapping().page_size as int
553 } else {
554 0
555 },
556 {
557 if self.present() {
558 let qm = self.query_mapping();
559 if qm.page_size > size {
560 let new_size = qm.page_size / NR_ENTRIES;
561 let new_self = self.split_if_mapped_huge_spec(new_size);
562
563 let f = self.mappings.filter(
564 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
565 );
566 vstd::set::lemma_set_choose_len(f);
567 assert(qm.inv());
568 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
569 if qm.page_size != 2097152 && qm.page_size != 1073741824 {
570 assert(false);
571 }
572 };
573 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
574 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
575
576 new_self.split_while_huge_refinement(size, m);
577
578 if new_self.mappings.contains(m) {
579 } else {
580 let p = choose|p: Mapping| #[trigger]
581 new_self.mappings.contains(p) && p.va_range.start <= m.va_range.start
582 && m.va_range.end <= p.va_range.end && m.pa_range.start == (
583 p.pa_range.start + (m.va_range.start - p.va_range.start)) as Paddr
584 && m.property == p.property;
585 if !self.mappings.contains(p) {
586 }
587 }
588 }
589 }
590 }
591
592 pub proof fn split_while_huge_disjoint(self, size: usize, other: Set<Mapping>)
602 requires
603 self.inv(),
604 size >= PAGE_SIZE,
605 forall|m: Mapping, x: Mapping| #[trigger]
606 self.mappings.contains(m) && #[trigger] other.contains(x)
607 ==> Mapping::disjoint_vaddrs(m, x),
608 ensures
609 self.split_while_huge(size).mappings.disjoint(other),
610 decreases
611 if self.present() {
612 self.query_mapping().page_size as int
613 } else {
614 0
615 },
616 {
617 if !self.present() {
618 assert forall|x: Mapping|
620 #![trigger other.contains(x)]
621 other.contains(x) implies !self.split_while_huge(size).mappings.contains(x) by {
622 if self.mappings.contains(x) {
623 assert(x.inv());
624 }
625 };
626 return;
627 }
628 let m = self.query_mapping();
629 if m.page_size <= size {
630 assert forall|x: Mapping|
631 #![trigger other.contains(x)]
632 other.contains(x) implies !self.split_while_huge(size).mappings.contains(x) by {
633 if self.mappings.contains(x) {
634 assert(x.inv());
635 }
636 };
637 return;
638 }
639 let new_size = m.page_size / NR_ENTRIES;
640
641 let f = self.mappings.filter(
643 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
644 );
645 vstd::set::lemma_set_choose_len(f);
646 assert(m.inv());
647
648 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
649 if m.page_size == 2097152 {
650 } else if m.page_size == 1073741824 {
651 } else {
652 assert(false);
653 }
654 };
655 assert(m.page_size % new_size == 0) by {
656 assert(2097152usize % (2097152usize / 512usize) == 0) by (compute_only);
657 assert(1073741824usize % (1073741824usize / 512usize) == 0) by (compute_only);
658 };
659 assert(m.page_size > new_size) by {
660 assert(2097152usize > 2097152usize / 512usize) by (compute_only);
661 assert(1073741824usize > 1073741824usize / 512usize) by (compute_only);
662 };
663 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
664 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
665 let new_self = self.split_if_mapped_huge_spec(new_size);
666
667 assert forall|m2: Mapping, x: Mapping| #[trigger]
669 new_self.mappings.contains(m2) && #[trigger] other.contains(
670 x,
671 ) implies Mapping::disjoint_vaddrs(m2, x) by {
672 if self.mappings.contains(m2) {
673 } else {
675 Self::split_if_mapped_huge_spec_refinement(self, new_size, m2);
678 assert(Mapping::disjoint_vaddrs(m, x));
679 }
680 };
681
682 new_self.split_while_huge_disjoint(size, other);
683 }
684}
685
686impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
687 proof fn query_mapping_from_subtree(self, qm: Mapping)
692 requires
693 self.inv(),
694 self.in_locked_range(),
695 self@.inv(),
696 self@.present(),
697 qm == self@.query_mapping(),
698 ensures
699 PageTableOwner(self.cur_subtree()).view_rec(self.cur_subtree().value().path).contains(
700 qm,
701 ),
702 {
703 let f = self@.mappings.filter(
704 |m2: Mapping| m2.va_range.start <= self@.cur_va < m2.va_range.end,
705 );
706 lemma_set_choose_len(f);
707 self.mapping_covering_cur_va_from_cur_subtree(qm);
708 }
709
710 pub proof fn split_while_huge_node_noop(self)
711 requires
712 self.inv(),
713 self.in_locked_range(),
714 self.cur_entry_owner().is_node(),
715 self.level > 1,
716 ensures
717 self@.split_while_huge(page_size::<PagingConsts>((self.level - 1) as PagingLevel))
718 == self@,
719 {
720 self.view_preserves_inv();
721 if self@.present() {
722 let subtree = self.cur_subtree();
723 let path = subtree.value().path;
724 let qm = self@.query_mapping();
725 self.query_mapping_from_subtree(qm);
726 PageTableOwner(subtree).view_rec_node_page_size_bound(path, qm);
727 }
728 }
729
730 pub proof fn split_while_huge_absent_noop(self, size: usize)
733 requires
734 self.inv(),
735 self.in_locked_range(),
736 self.cur_entry_owner().is_absent(),
737 ensures
738 self@.split_while_huge(size) == self@,
739 {
740 self.view_preserves_inv();
741 self.lemma_cur_entry_absent_not_present();
742 }
743
744 pub proof fn split_while_huge_at_level_noop(self)
745 requires
746 self.inv(),
747 self.in_locked_range(),
748 ensures
749 self@.split_while_huge(page_size::<PagingConsts>(self.level as PagingLevel)) == self@,
750 {
751 self.view_preserves_inv();
752 if self@.present() {
753 self.lemma_cur_subtree_inv();
754 let subtree = self.cur_subtree();
755 let path = subtree.value().path;
756 let qm = self@.query_mapping();
757 self.query_mapping_from_subtree(qm);
758 PageTableOwner(subtree).view_rec_page_size_bound(path, qm);
759 }
760 }
761
762 pub proof fn find_next_split_push_equals_split_while_huge(self, old_view: CursorView<C>)
765 requires
766 self.inv(),
767 old_view.inv(),
768 self.cur_entry_owner().is_frame(),
769 self@.cur_va == old_view.cur_va,
770 old_view.present(),
771 old_view.query_mapping().page_size > page_size::<PagingConsts>(
772 self.level as PagingLevel,
773 ),
774 old_view.query_mapping().page_size / NR_ENTRIES == page_size::<PagingConsts>(
775 self.level as PagingLevel,
776 ),
777 old_view.query_mapping().page_size % page_size::<PagingConsts>(
778 self.level as PagingLevel,
779 ) == 0,
780 self@.mappings =~= old_view.split_if_mapped_huge_spec(
781 page_size::<PagingConsts>(self.level as PagingLevel),
782 ).mappings,
783 ensures
784 self@.mappings == old_view.split_while_huge(
785 page_size::<PagingConsts>(self.level as PagingLevel),
786 ).mappings,
787 {
788 let ps = page_size::<PagingConsts>(self.level as PagingLevel);
789 let m = old_view.query_mapping();
790 let f = old_view.mappings.filter(
791 |m2: Mapping| m2.va_range.start <= old_view.cur_va < m2.va_range.end,
792 );
793 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_spec_values();
794 old_view.split_while_huge_one_step(ps);
795 }
796}
797
798}