1use vstd::prelude::*;
2use vstd::set::lemma_set_choose_len;
3use vstd::set_lib::*;
4
5use vstd_extra::ghost_tree::*;
6use vstd_extra::ownership::*;
7
8use crate::arch::mm::PagingConsts;
9use crate::mm::page_prop::PageProperty;
10use crate::mm::page_table::*;
11use crate::mm::{Paddr, PagingConstsTrait, PagingLevel, Vaddr, page_size};
12use crate::specs::arch::MAX_PADDR;
13use crate::specs::arch::{NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
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
19verus! {
20
21impl<C: PageTableConfig> CursorView<C> {
22 pub proof fn split_if_mapped_huge_spec_preserves_present(v: Self, new_size: usize)
26 requires
27 v.inv(),
28 v.present(),
29 new_size > 0,
30 v.query_mapping().page_size > 0,
31 v.query_mapping().page_size % new_size == 0,
32 ensures
33 v.split_if_mapped_huge_spec(new_size).present(),
34 {
35 let cur_va = v.cur_va;
36 let m = v.query_mapping();
37 let ps = m.page_size;
38
39 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
40 let f = v.mappings.filter(
41 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
42 );
43 vstd::set::lemma_set_choose_len(f);
44 };
45 assert(m.inv());
46 assert(m.va_range.start + ps == m.va_range.end);
47
48 let diff: int = cur_va - m.va_range.start;
49 let ki: int = diff / new_size as int;
50 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(diff, new_size as int);
51 vstd::arithmetic::div_mod::lemma_mod_division_less_than_divisor(diff, new_size as int);
52 vstd::arithmetic::div_mod::lemma_div_pos_is_pos(diff, new_size as int);
53
54 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, new_size as int);
55 assert(ki < ps as int / new_size as int) by {
56 if ki >= ps as int / new_size as int {
57 vstd::arithmetic::mul::lemma_mul_inequality(
58 ps as int / new_size as int,
59 ki,
60 new_size as int,
61 );
62 }
63 };
64
65 let sub = Self::split_index(m, new_size, ki as usize);
66
67 assert(ki * new_size >= 0) by {
68 vstd::arithmetic::mul::lemma_mul_nonnegative(ki, new_size as int);
69 };
70 assert((ki + 1) * new_size <= ps) by {
71 vstd::arithmetic::mul::lemma_mul_inequality(
72 ki + 1,
73 ps as int / new_size as int,
74 new_size as int,
75 );
76 };
77 assert(m.va_range.start + (ki + 1) * new_size <= m.va_range.end) by {
78 vstd::arithmetic::mul::lemma_mul_is_commutative(ki + 1, new_size as int);
79 vstd::arithmetic::mul::lemma_mul_is_commutative(
80 ps as int / new_size as int,
81 new_size as int,
82 );
83 };
84
85 assert(ki as usize == ki);
86 vstd::arithmetic::mul::lemma_mul_is_distributive_add(new_size as int, ki, 1 as int);
87 assert(cur_va >= m.va_range.start + ki * new_size);
88 assert(cur_va < m.va_range.start + (ki + 1) * new_size);
89 assert(sub.va_range.start <= cur_va);
90
91 let new_self = v.split_if_mapped_huge_spec(new_size);
92 let domain = Set::<int>::range(0int, ps as int / new_size as int);
93 assert(domain.contains(ki));
94 assert(new_self.mappings.contains(sub));
95
96 let new_filter = new_self.mappings.filter(
97 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end,
98 );
99 assert(new_filter.contains(sub));
100 vstd::set::lemma_set_contains_len(new_filter, sub);
101 }
102
103 pub proof fn split_if_mapped_huge_spec_decreases_page_size(v: Self, new_size: usize)
110 requires
111 v.inv(),
112 v.present(),
113 new_size > 0,
114 v.query_mapping().page_size > new_size,
115 v.query_mapping().page_size % new_size == 0,
116 ensures
117 v.split_if_mapped_huge_spec(new_size).present(),
118 v.split_if_mapped_huge_spec(new_size).query_mapping().page_size
119 < v.query_mapping().page_size,
120 {
121 Self::split_if_mapped_huge_spec_preserves_present(v, new_size);
122
123 let cur_va = v.cur_va;
124 let m = v.query_mapping();
125 let new_self = v.split_if_mapped_huge_spec(new_size);
126 let m2 = new_self.query_mapping();
127 let ps = m.page_size;
128
129 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
130 let f = v.mappings.filter(
131 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
132 );
133 vstd::set::lemma_set_choose_len(f);
134 };
135
136 assert(new_self.mappings.contains(m2) && m2.va_range.start <= cur_va && cur_va
137 < m2.va_range.end) by {
138 let f = new_self.mappings.filter(
139 |m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end,
140 );
141 vstd::set::lemma_set_choose_len(f);
142 };
143
144 if v.mappings.contains(m2) && m2 != m {
145 assert(m.va_range.end <= m2.va_range.start || m2.va_range.end <= m.va_range.start);
146 assert(false);
147 }
148 assert(!v.mappings.remove(m).contains(m2));
149 let new_mappings = Set::<int>::range(0int, ps as int / new_size as int).map(
150 |n: int| Self::split_index(m, new_size, n as usize),
151 );
152 assert(new_mappings.contains(m2));
153 let k = choose|k: int|
154 0 <= k < ps as int / new_size as int && #[trigger] Self::split_index(
155 m,
156 new_size,
157 k as usize,
158 ) == m2;
159 assert(m2.page_size == new_size);
160 }
161
162 pub proof fn split_if_mapped_huge_spec_preserves_inv(v: Self, new_size: usize)
168 requires
169 v.inv(),
170 v.present(),
171 new_size > 0,
172 v.query_mapping().page_size > new_size,
173 v.query_mapping().page_size % new_size == 0,
174 set![4096usize, 2097152, 1073741824].contains(new_size),
175 ensures
176 v.split_if_mapped_huge_spec(new_size).inv(),
177 {
178 let cur_va = v.cur_va;
179 let m = v.query_mapping();
180 let ps = m.page_size;
181 let ns: int = new_size as int;
182 let new_self = v.split_if_mapped_huge_spec(new_size);
183 let count: int = ps as int / ns;
184 let domain = Set::<int>::range(0int, count);
185 let new_mappings = domain.map(|n: int| Self::split_index(m, new_size, n as usize));
186
187 assert(v.mappings.contains(m) && m.va_range.start <= cur_va && cur_va < m.va_range.end) by {
189 let f = v.mappings.filter(
190 |m2: Mapping| m2.va_range.start <= v.cur_va < m2.va_range.end,
191 );
192 vstd::set::lemma_set_choose_len(f);
193 };
194 assert(m.inv());
195
196 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, ns);
200 assert(ps == count * ns);
201
202 assert(m.va_range.start % new_size as int == 0) by {
203 vstd::arithmetic::mul::lemma_mul_is_commutative(count, ns);
204 vstd::arithmetic::div_mod::lemma_mod_mod(m.va_range.start as int, ns, count);
205 };
206 assert(m.pa_range.start % new_size == 0) by {
207 vstd::arithmetic::mul::lemma_mul_is_commutative(count, ns);
208 vstd::arithmetic::div_mod::lemma_mod_mod(m.pa_range.start as int, ns, count);
209 };
210
211 assert forall|e: Mapping| new_self.mappings.contains(e) implies #[trigger] e.inv() by {
213 if v.mappings.remove(m).contains(e) {
214 assert(v.mappings.contains(e));
215 } else {
216 assert(new_mappings.contains(e));
217 let k = choose|k: int|
218 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == e;
219 let sub = Self::split_index(m, new_size, k as usize);
220
221 assert(set![4096usize, 2097152, 1073741824].contains(sub.page_size));
223
224 vstd::arithmetic::mul::lemma_mul_is_commutative(k, ns);
227 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
228 k,
229 m.va_range.start as int,
230 ns,
231 );
232 assert(sub.va_range.start % new_size as int == 0);
233 vstd::arithmetic::mul::lemma_mul_is_commutative(k + 1, ns);
234 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
235 k + 1,
236 m.va_range.start as int,
237 ns,
238 );
239 assert(sub.va_range.end % new_size as int == 0);
240
241 vstd::arithmetic::mul::lemma_mul_is_commutative(k, ns);
242 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
243 k,
244 m.pa_range.start as int,
245 ns,
246 );
247 assert(sub.pa_range.start % new_size == 0);
248 vstd::arithmetic::mul::lemma_mul_is_commutative(k + 1, ns);
249 vstd::arithmetic::div_mod::lemma_mod_multiples_vanish(
250 k + 1,
251 m.pa_range.start as int,
252 ns,
253 );
254 assert(sub.pa_range.end % new_size == 0);
255
256 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, k, 1int);
258 assert(sub.va_range.start + new_size == sub.va_range.end);
259 assert(sub.pa_range.start + new_size == sub.pa_range.end);
260
261 vstd::arithmetic::mul::lemma_mul_nonnegative(k, ns);
263 vstd::arithmetic::mul::lemma_mul_inequality(k + 1, count, ns);
264 assert(sub.va_range.start >= m.va_range.start);
266 assert(sub.va_range.end <= m.va_range.end);
267 assert(sub.va_range.start <= sub.va_range.end);
268
269 assert(sub.pa_range.start >= m.pa_range.start);
270 assert(sub.pa_range.end <= m.pa_range.end);
271 assert(sub.pa_range.start <= sub.pa_range.end);
272 }
273 };
274
275 assert forall|e1: Mapping, e2: Mapping| #[trigger]
277 new_self.mappings.contains(e1) && #[trigger] new_self.mappings.contains(e2) && e1
278 != e2 implies e1.va_range.end <= e2.va_range.start || e2.va_range.end
279 <= e1.va_range.start by {
280 if v.mappings.remove(m).contains(e1) && v.mappings.remove(m).contains(e2) {
281 assert(v.mappings.contains(e1));
283 assert(v.mappings.contains(e2));
284 } else if v.mappings.remove(m).contains(e1) && new_mappings.contains(e2) {
285 assert(v.mappings.contains(e1));
287 assert(e1 != m);
288 let k2 = choose|k: int|
289 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == e2;
290 vstd::arithmetic::mul::lemma_mul_nonnegative(k2, ns);
291 vstd::arithmetic::mul::lemma_mul_inequality(k2 + 1, count, ns);
292 assert(e2.va_range.start >= m.va_range.start);
293 assert(e2.va_range.end <= m.va_range.end);
294 } else if new_mappings.contains(e1) && v.mappings.remove(m).contains(e2) {
295 assert(v.mappings.contains(e2));
297 assert(e2 != m);
298 let k1 = choose|k: int|
299 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == e1;
300 vstd::arithmetic::mul::lemma_mul_nonnegative(k1, ns);
301 vstd::arithmetic::mul::lemma_mul_inequality(k1 + 1, count, ns);
302 assert(e1.va_range.start >= m.va_range.start);
303 assert(e1.va_range.end <= m.va_range.end);
304 } else if new_mappings.contains(e1) && new_mappings.contains(e2) {
305 let i = choose|k: int|
307 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == e1;
308 let j = choose|k: int|
309 0 <= k < count && #[trigger] Self::split_index(m, new_size, k as usize) == e2;
310 vstd::arithmetic::mul::lemma_mul_nonnegative(i, ns);
311 vstd::arithmetic::mul::lemma_mul_nonnegative(j, ns);
312 if i < j {
313 vstd::arithmetic::mul::lemma_mul_inequality(i + 1, j, ns);
314 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, i, 1int);
315 } else {
316 vstd::arithmetic::mul::lemma_mul_inequality(j + 1, i, ns);
317 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, j, 1int);
318 }
319 }
320 };
321 }
322
323 pub broadcast proof fn lemma_split_while_huge_preserves_cur_va(self, size: usize)
325 requires
326 self.inv(),
327 size >= PAGE_SIZE,
328 ensures
329 #[trigger] self.split_while_huge(size).cur_va == self.cur_va,
330 decreases
331 if self.present() {
332 self.query_mapping().page_size as int
333 } else {
334 0
335 },
336 {
337 if self.present() {
338 let m = self.query_mapping();
339 if m.page_size > size {
340 let new_size = m.page_size / NR_ENTRIES;
341 let new_self = self.split_if_mapped_huge_spec(new_size);
342 let f = self.mappings.filter(
344 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
345 );
346 vstd::set::lemma_set_choose_len(f);
347 assert(m.inv());
348 assert(NR_ENTRIES == 512usize) by (compute_only);
349 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
351 if m.page_size == 2097152 {
352 assert(2097152usize / 512 == 4096usize);
353 } else if m.page_size == 1073741824 {
354 assert(1073741824usize / 512 == 2097152usize);
355 } else {
356 assert(4096usize / 512 == 8usize);
357 assert(false);
358 } };
360 assert(m.page_size % new_size == 0) by {
361 if m.page_size == 2097152 {
362 assert(2097152usize % 4096 == 0);
363 } else {
364 assert(1073741824usize % 2097152 == 0);
365 }
366 };
367 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
368
369 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
370 Self::lemma_split_while_huge_preserves_cur_va(new_self, size);
371 }
372 }
373 }
374
375 pub proof fn lemma_split_while_huge_preserves_inv(self, size: usize)
377 requires
378 self.inv(),
379 size >= PAGE_SIZE,
380 ensures
381 self.split_while_huge(size).inv(),
382 decreases
383 if self.present() {
384 self.query_mapping().page_size as int
385 } else {
386 0
387 },
388 {
389 if self.present() {
390 let m = self.query_mapping();
391 if m.page_size > size {
392 let new_size = m.page_size / NR_ENTRIES;
393 let new_self = self.split_if_mapped_huge_spec(new_size);
394 let f = self.mappings.filter(
396 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
397 );
398 vstd::set::lemma_set_choose_len(f);
399 assert(m.inv());
400 assert(NR_ENTRIES == 512usize) by (compute_only);
401 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
402 if m.page_size == 2097152 {
403 assert(2097152usize / 512 == 4096usize);
404 } else if m.page_size == 1073741824 {
405 assert(1073741824usize / 512 == 2097152usize);
406 } else {
407 assert(4096usize / 512 == 8usize);
408 assert(false);
409 }
410 };
411 assert(m.page_size % new_size == 0) by {
412 if m.page_size == 2097152 {
413 assert(2097152usize % 4096 == 0);
414 } else {
415 assert(1073741824usize % 2097152 == 0);
416 }
417 };
418 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
419 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
420 new_self.lemma_split_while_huge_preserves_inv(size);
421 }
422 }
423 }
424
425 pub proof fn split_while_huge_compose(self, s1: usize, s2: usize)
429 requires
430 self.inv(),
431 s1 >= PAGE_SIZE,
432 s2 <= s1,
433 ensures
434 self.split_while_huge(s2) == self.split_while_huge(s1).split_while_huge(s2),
435 decreases
436 if self.present() {
437 self.query_mapping().page_size as int
438 } else {
439 0
440 },
441 {
442 if !self.present() {
443 return;
444 }
445 let m = self.query_mapping();
446 if m.page_size <= s1 {
447 return;
448 }
449 let new_size = m.page_size / NR_ENTRIES;
450 let f = self.mappings.filter(
451 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
452 );
453 vstd::set::lemma_set_choose_len(f);
454 assert(m.inv());
455 assert(NR_ENTRIES == 512usize) by (compute_only);
456 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
457 if m.page_size == 2097152 {
458 assert(2097152usize / 512 == 4096usize);
459 } else {
460 assert(1073741824usize / 512 == 2097152usize);
461 }
462 };
463 assert(m.page_size % new_size == 0) by {
464 if m.page_size == 2097152 {
465 assert(2097152usize % 4096 == 0);
466 } else {
467 assert(1073741824usize % 2097152 == 0);
468 }
469 };
470 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
471 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
472 self.split_if_mapped_huge_spec(new_size).split_while_huge_compose(s1, s2);
473 }
474
475 pub proof fn split_while_huge_idempotent(self, size: usize)
478 requires
479 self.inv(),
480 size >= PAGE_SIZE,
481 ensures
482 self.split_while_huge(size).split_while_huge(size) == self.split_while_huge(size),
483 {
484 self.split_while_huge_compose(size, size);
485 }
486
487 pub proof fn split_while_huge_noop_implies_page_size_le(self, size: usize)
490 requires
491 self.inv(),
492 size >= PAGE_SIZE,
493 self.split_while_huge(size) == self,
494 self.present(),
495 ensures
496 self.query_mapping().page_size <= size,
497 {
498 let m = self.query_mapping();
499 if m.page_size > size {
500 let new_size = m.page_size / NR_ENTRIES;
501 let f = self.mappings.filter(
502 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
503 );
504 vstd::set::lemma_set_choose_len(f);
505 assert(m.inv());
506 assert(NR_ENTRIES == 512usize) by (compute_only);
507 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
508 if m.page_size == 2097152 {
509 assert(2097152usize / 512 == 4096usize);
510 } else if m.page_size == 1073741824 {
511 assert(1073741824usize / 512 == 2097152usize);
512 } else {
513 assert(4096usize / 512 == 8usize);
514 assert(false);
515 }
516 };
517 assert(m.page_size % new_size == 0) by {
518 if m.page_size == 2097152 {
519 assert(2097152usize % 4096 == 0);
520 } else {
521 assert(1073741824usize % 2097152 == 0);
522 }
523 };
524 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
525 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
526 let new_self = self.split_if_mapped_huge_spec(new_size);
527 new_self.split_while_huge_refinement(size, m);
528 assert(!new_self.mappings.contains(m)) by {
529 let new_mappings = Set::<int>::range(
530 0int,
531 m.page_size as int / new_size as int,
532 ).map(|n: int| Self::split_index(m, new_size, n as usize));
533 if new_mappings.contains(m) {
534 let k = choose|k: int|
535 0 <= k < m.page_size as int / new_size as int
536 && #[trigger] Self::split_index(m, new_size, k as usize) == m;
537 }
538 };
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 == (p.pa_range.start + (
542 m.va_range.start - p.va_range.start)) as Paddr && m.property == p.property;
543 if self.mappings.contains(p) {
544 assert(p.va_range.start <= self.cur_va < p.va_range.end);
545 } else {
546 let new_mappings = Set::<int>::range(
547 0int,
548 m.page_size as int / new_size as int,
549 ).map(|n: int| Self::split_index(m, new_size, n as usize));
550 let k = choose|k: int|
551 0 <= k < m.page_size as int / new_size as int && #[trigger] Self::split_index(
552 m,
553 new_size,
554 k as usize,
555 ) == p;
556 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(
557 m.page_size as int,
558 new_size as int,
559 );
560 vstd::arithmetic::mul::lemma_mul_inequality(
561 (k + 1) as int,
562 m.page_size as int / new_size as int,
563 new_size as int,
564 );
565 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
566 new_size as int,
567 k,
568 1int,
569 );
570 }
571 }
572 }
573
574 pub proof fn split_while_huge_one_step(self, size: usize)
584 requires
585 self.inv(),
586 self.present(),
587 self.query_mapping().page_size > size,
588 self.query_mapping().page_size / NR_ENTRIES == size,
589 self.query_mapping().page_size % size == 0,
590 set![4096usize, 2097152, 1073741824].contains(size),
591 ensures
592 self.split_while_huge(size).mappings == self.split_if_mapped_huge_spec(size).mappings,
593 {
594 let m = self.query_mapping();
595 let new_size = m.page_size / NR_ENTRIES;
596 let f0 = self.mappings.filter(
597 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
598 );
599 vstd::set::lemma_set_choose_len(f0);
600 assert(m.inv());
601 assert(NR_ENTRIES == 512usize) by (compute_only);
602 Self::split_if_mapped_huge_spec_preserves_present(self, new_size);
603 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
604 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
605 let new_self = self.split_if_mapped_huge_spec(new_size);
606
607 assert(new_self.query_mapping().page_size == new_size) by {
608 let new_m = new_self.query_mapping();
609 let f = new_self.mappings.filter(
610 |m2: Mapping| m2.va_range.start <= new_self.cur_va < m2.va_range.end,
611 );
612 vstd::set::lemma_set_choose_len(f);
613 if self.mappings.contains(new_m) && new_m != m {
614 assert(false);
615 }
616 let new_mappings = Set::<int>::range(0int, m.page_size as int / new_size as int).map(
617 |n: int| Self::split_index(m, new_size, n as usize),
618 );
619 assert(new_mappings.contains(new_m));
620 };
621 assert(new_self.split_while_huge(size) == new_self);
622 }
623
624 pub proof fn split_if_mapped_huge_spec_locality(self, new_size: usize, m2: Mapping)
627 requires
628 self.inv(),
629 self.present(),
630 new_size > 0,
631 self.query_mapping().page_size % new_size == 0,
632 Mapping::disjoint_vaddrs(m2, self.query_mapping()),
633 ensures
634 self.split_if_mapped_huge_spec(new_size).mappings.contains(m2)
635 == self.mappings.contains(m2),
636 {
637 let m = self.query_mapping();
638 let size = m.page_size;
639 let new_mappings = Set::<int>::range(0int, (size / new_size) as int).map(
640 |n: int| Self::split_index(m, new_size, n as usize),
641 );
642
643 let f = self.mappings.filter(
645 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
646 );
647 vstd::set::lemma_set_choose_len(f);
648 assert(m.inv());
649
650 assert(!new_mappings.contains(m2)) by {
651 if new_mappings.contains(m2) {
652 let k = choose|k: int|
653 0 <= k < size as int / new_size as int && #[trigger] Self::split_index(
654 m,
655 new_size,
656 k as usize,
657 ) == m2;
658 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(size as int, new_size as int);
659 vstd::arithmetic::mul::lemma_mul_inequality(
660 (k + 1) as int,
661 size as int / new_size as int,
662 new_size as int,
663 );
664 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
665 new_size as int,
666 k,
667 1int,
668 );
669 vstd::arithmetic::mul::lemma_mul_nonnegative(k, new_size as int);
670 }
671 };
672 }
673
674 #[verifier::rlimit(80)]
681 pub proof fn split_while_huge_locality(self, size: usize, m2: Mapping)
682 requires
683 self.inv(),
684 size >= PAGE_SIZE,
685 self.mappings.contains(m2),
686 !(m2.va_range.start <= self.cur_va < m2.va_range.end),
687 ensures
688 self.split_while_huge(size).mappings.contains(m2),
689 decreases
690 if self.present() {
691 self.query_mapping().page_size as int
692 } else {
693 0
694 },
695 {
696 if self.present() {
697 let m = self.query_mapping();
698 if m.page_size > size {
699 let new_size = m.page_size / NR_ENTRIES;
700 let f = self.mappings.filter(
702 |m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end,
703 );
704 vstd::set::lemma_set_choose_len(f);
705 assert(self.mappings.contains(m));
706 assert(m.va_range.start <= self.cur_va < m.va_range.end);
707 assert(m.inv());
708 assert(Mapping::disjoint_vaddrs(m2, m));
710 assert(NR_ENTRIES == 512usize);
712 assert(m.page_size % new_size == 0) by {
713 if m.page_size == 4096 {
714 assert(4096usize % (4096usize / 512usize) == 0);
715 } else if m.page_size == 2097152 {
716 assert(2097152usize % (2097152usize / 512usize) == 0);
717 } else {
718 assert(1073741824usize % (1073741824usize / 512usize) == 0);
719 }
720 };
721 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
722 if m.page_size == 2097152 {
723 assert(2097152usize / 512 == 4096usize);
724 } else if m.page_size == 1073741824 {
725 assert(1073741824usize / 512 == 2097152usize);
726 } else {
727 assert(4096usize / 512 == 8usize);
728 assert(false);
729 }
730 };
731 self.split_if_mapped_huge_spec_locality(new_size, m2);
732 let new_self = self.split_if_mapped_huge_spec(new_size);
733 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
734 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
735 new_self.split_while_huge_locality(size, m2);
736 }
737 }
738 }
739
740 #[verifier::rlimit(120)]
748 pub proof fn split_while_huge_locality_absent(self, size: usize, m2: Mapping)
749 requires
750 self.inv(),
751 size >= PAGE_SIZE,
752 !self.mappings.contains(m2),
753 self.present() ==> Mapping::disjoint_vaddrs(m2, self.query_mapping()),
754 ensures
755 !self.split_while_huge(size).mappings.contains(m2),
756 decreases
757 if self.present() {
758 self.query_mapping().page_size as int
759 } else {
760 0
761 },
762 {
763 if self.present() {
764 let m = self.query_mapping();
765 if m.page_size > size {
766 let new_size = m.page_size / NR_ENTRIES;
767 let f = self.mappings.filter(
769 |m3: Mapping| m3.va_range.start <= self.cur_va < m3.va_range.end,
770 );
771 vstd::set::lemma_set_choose_len(f);
772 assert(self.mappings.contains(m));
773 assert(m.inv());
775 assert(m.page_size % new_size == 0) by {
776 assert(set![4096usize, 2097152usize, 1073741824usize].contains(m.page_size));
777 assert(4096usize % (4096usize / 512usize) == 0) by (compute_only);
778 assert(2097152usize % (2097152usize / 512usize) == 0) by (compute_only);
779 assert(1073741824usize % (1073741824usize / 512usize) == 0) by (compute_only);
780 };
781 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
782 if m.page_size == 2097152 {
783 assert(2097152usize / 512 == 4096usize);
784 } else if m.page_size == 1073741824 {
785 assert(1073741824usize / 512 == 2097152usize);
786 } else {
787 assert(4096usize / 512 == 8usize);
788 assert(false);
789 }
790 };
791 self.split_if_mapped_huge_spec_locality(new_size, m2);
792 let new_self = self.split_if_mapped_huge_spec(new_size);
793 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
794 Self::split_if_mapped_huge_spec_preserves_present(self, new_size);
795 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
796 assert(new_self.present() ==> Mapping::disjoint_vaddrs(
797 m2,
798 new_self.query_mapping(),
799 )) by {
800 if new_self.present() {
801 let new_m = new_self.query_mapping();
802 let nf = new_self.mappings.filter(
803 |m3: Mapping| m3.va_range.start <= new_self.cur_va < m3.va_range.end,
804 );
805 vstd::set::lemma_set_choose_len(nf);
806 if self.mappings.contains(new_m) && new_m != m {
807 assert(false);
808 }
809 let new_mappings = Set::<int>::range(
810 0int,
811 m.page_size as int / new_size as int,
812 ).map(|n: int| Self::split_index(m, new_size, n as usize));
813 let k = choose|k: int|
814 0 <= k < m.page_size as int / new_size as int
815 && #[trigger] Self::split_index(m, new_size, k as usize) == new_m;
816 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(
817 m.page_size as int,
818 new_size as int,
819 );
820 vstd::arithmetic::mul::lemma_mul_inequality(
821 (k + 1) as int,
822 m.page_size as int / new_size as int,
823 new_size as int,
824 );
825 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
826 new_size as int,
827 k,
828 1int,
829 );
830 vstd::arithmetic::mul::lemma_mul_nonnegative(k, new_size as int);
831 }
832 };
833 new_self.split_while_huge_locality_absent(size, m2);
834 }
835 }
836 }
837
838 pub proof fn split_if_mapped_huge_spec_refinement(self, new_size: usize, e: Mapping)
843 requires
844 self.inv(),
845 self.present(),
846 new_size > 0,
847 self.query_mapping().page_size > new_size,
848 self.query_mapping().page_size % new_size == 0,
849 self.split_if_mapped_huge_spec(new_size).mappings.contains(e),
850 ensures
851 self.mappings.contains(e) || {
852 let parent = self.query_mapping();
853 &&& self.mappings.contains(parent)
854 &&& parent.va_range.start <= e.va_range.start
855 &&& e.va_range.end <= parent.va_range.end
856 &&& e.pa_range.start == (parent.pa_range.start + (e.va_range.start
857 - parent.va_range.start)) as Paddr
858 &&& e.property == parent.property
859 },
860 {
861 let qm = self.query_mapping();
862 let ps = qm.page_size;
863 let ns: int = new_size as int;
864 let count: int = ps as int / ns;
865 let new_self = self.split_if_mapped_huge_spec(new_size);
866 let domain = Set::<int>::range(0int, count);
867 let new_mappings = domain.map(|n: int| Self::split_index(qm, new_size, n as usize));
868
869 let f = self.mappings.filter(
871 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
872 );
873 vstd::set::lemma_set_choose_len(f);
874 assert(self.mappings.contains(qm));
875 assert(qm.inv());
876
877 if self.mappings.remove(qm).contains(e) {
878 assert(self.mappings.contains(e));
879 } else {
880 assert(new_mappings.contains(e));
881 let k = choose|k: int|
882 0 <= k < count && #[trigger] Self::split_index(qm, new_size, k as usize) == e;
883
884 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps as int, ns);
885 assert(ps == count * ns);
886
887 vstd::arithmetic::mul::lemma_mul_nonnegative(k, ns);
888 vstd::arithmetic::mul::lemma_mul_inequality(k + 1, count, ns);
889
890 assert(k as usize == k);
891 let ku = k as usize;
892 assert(e == Self::split_index(qm, new_size, ku));
893 vstd::arithmetic::mul::lemma_mul_is_distributive_add(ns, k, 1int);
894
895 assert(e.va_range.start == qm.va_range.start + k * ns);
896 assert(e.va_range.start >= qm.va_range.start);
897 assert(e.va_range.end == qm.va_range.start + (k + 1) * ns);
898 assert(e.va_range.end <= qm.va_range.end);
899 assert(e.pa_range.start == qm.pa_range.start + k * ns);
900 assert(e.va_range.start - qm.va_range.start == k * ns);
901 assert(e.pa_range.start == (qm.pa_range.start + (e.va_range.start
902 - qm.va_range.start)) as Paddr);
903 assert(e.property == qm.property);
904 }
905 }
906
907 pub proof fn split_while_huge_refinement(self, size: usize, m: Mapping)
908 requires
909 self.inv(),
910 size >= PAGE_SIZE,
911 self.split_while_huge(size).mappings.contains(m),
912 ensures
913 self.mappings.contains(m) || exists|parent: Mapping| #[trigger]
914 self.mappings.contains(parent) && parent.va_range.start <= m.va_range.start
915 && m.va_range.end <= parent.va_range.end && m.pa_range.start == (
916 parent.pa_range.start + (m.va_range.start - parent.va_range.start)) as Paddr
917 && m.property == parent.property,
918 decreases
919 if self.present() {
920 self.query_mapping().page_size as int
921 } else {
922 0
923 },
924 {
925 if self.present() {
926 let qm = self.query_mapping();
927 if qm.page_size > size {
928 let new_size = qm.page_size / NR_ENTRIES;
929 let new_self = self.split_if_mapped_huge_spec(new_size);
930
931 let f = self.mappings.filter(
932 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
933 );
934 vstd::set::lemma_set_choose_len(f);
935 assert(qm.inv());
936 assert(NR_ENTRIES == 512usize) by (compute_only);
937 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
938 if qm.page_size == 2097152 {
939 assert(2097152usize / 512 == 4096usize);
940 } else if qm.page_size == 1073741824 {
941 assert(1073741824usize / 512 == 2097152usize);
942 } else {
943 assert(4096usize / 512 == 8usize);
944 assert(false);
945 }
946 };
947 assert(qm.page_size % new_size == 0) by {
948 if qm.page_size == 2097152 {
949 assert(2097152usize % 4096 == 0);
950 } else {
951 assert(1073741824usize % 2097152 == 0);
952 }
953 };
954 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
955 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
956
957 new_self.split_while_huge_refinement(size, m);
958
959 if new_self.mappings.contains(m) {
960 self.split_if_mapped_huge_spec_refinement(new_size, m);
961 } else {
962 let p = choose|p: Mapping| #[trigger]
963 new_self.mappings.contains(p) && p.va_range.start <= m.va_range.start
964 && m.va_range.end <= p.va_range.end && m.pa_range.start == (
965 p.pa_range.start + (m.va_range.start - p.va_range.start)) as Paddr
966 && m.property == p.property;
967 self.split_if_mapped_huge_spec_refinement(new_size, p);
968 if !self.mappings.contains(p) {
969 assert(qm.va_range.start <= m.va_range.start);
970 assert(m.va_range.end <= qm.va_range.end);
971 new_self.lemma_split_while_huge_preserves_inv(size);
974 assert(new_self.split_while_huge(size).inv());
975 assert(m.inv());
976 assert(new_self.inv());
977 assert(p.inv());
978 assert(m.va_range.start + m.page_size == m.va_range.end);
980 assert(qm.va_range.start + qm.page_size == qm.va_range.end);
981 assert(m.va_range.start - qm.va_range.start <= qm.page_size - m.page_size);
983 assert(qm.pa_range.start + qm.page_size == qm.pa_range.end);
985 assert(qm.pa_range.end <= MAX_PADDR);
986 assert(p.pa_range.start == qm.pa_range.start + (p.va_range.start
987 - qm.va_range.start));
988 assert(m.pa_range.start == p.pa_range.start + (m.va_range.start
989 - p.va_range.start));
990 assert(m.pa_range.start == qm.pa_range.start + (m.va_range.start
991 - qm.va_range.start));
992 assert(qm.pa_range.start + (m.va_range.start - qm.va_range.start)
994 <= qm.pa_range.end);
995 assert(m.pa_range.start == (qm.pa_range.start + (m.va_range.start
996 - qm.va_range.start)) as Paddr);
997 assert(m.property == qm.property);
998 }
999 }
1000 }
1001 }
1002 }
1003
1004 pub proof fn split_while_huge_preserves_empty_prefix(
1006 self,
1007 split_view: CursorView<C>,
1008 size: usize,
1009 m: Mapping,
1010 )
1011 requires
1012 self.inv(),
1013 size >= PAGE_SIZE,
1014 self.cur_va <= split_view.cur_va,
1015 self.cur_va < split_view.cur_va ==> !self.present(),
1016 self.mappings.filter(|m2: Mapping| self.cur_va <= m2.va_range.start < split_view.cur_va)
1017 == Set::<Mapping>::empty(),
1018 self.split_while_huge(size).mappings.contains(m),
1019 self.cur_va <= m.va_range.start < split_view.cur_va,
1020 ensures
1021 self.mappings.contains(m),
1022 {
1023 }
1024
1025 pub proof fn split_while_huge_disjoint(self, size: usize, other: Set<Mapping>)
1035 requires
1036 self.inv(),
1037 size >= PAGE_SIZE,
1038 forall|m: Mapping, x: Mapping| #[trigger]
1039 self.mappings.contains(m) && #[trigger] other.contains(x)
1040 ==> Mapping::disjoint_vaddrs(m, x),
1041 ensures
1042 self.split_while_huge(size).mappings.disjoint(other),
1043 decreases
1044 if self.present() {
1045 self.query_mapping().page_size as int
1046 } else {
1047 0
1048 },
1049 {
1050 if !self.present() {
1051 assert forall|x: Mapping|
1053 #![trigger other.contains(x)]
1054 other.contains(x) implies !self.split_while_huge(size).mappings.contains(x) by {
1055 if self.mappings.contains(x) {
1056 assert(Mapping::disjoint_vaddrs(x, x));
1057 assert(x.inv());
1058 }
1059 };
1060 return;
1061 }
1062 let m = self.query_mapping();
1063 if m.page_size <= size {
1064 assert forall|x: Mapping|
1065 #![trigger other.contains(x)]
1066 other.contains(x) implies !self.split_while_huge(size).mappings.contains(x) by {
1067 if self.mappings.contains(x) {
1068 assert(Mapping::disjoint_vaddrs(x, x));
1069 assert(x.inv());
1070 }
1071 };
1072 return;
1073 }
1074 let new_size = m.page_size / NR_ENTRIES;
1075
1076 let f = self.mappings.filter(
1078 |m2: Mapping| m2.va_range.start <= self.cur_va < m2.va_range.end,
1079 );
1080 vstd::set::lemma_set_choose_len(f);
1081 assert(self.mappings.contains(m));
1082 assert(m.inv());
1083
1084 assert(NR_ENTRIES == 512usize) by (compute_only);
1085 assert(set![4096usize, 2097152, 1073741824].contains(new_size)) by {
1086 if m.page_size == 2097152 {
1087 assert(2097152usize / 512 == 4096usize);
1088 } else if m.page_size == 1073741824 {
1089 assert(1073741824usize / 512 == 2097152usize);
1090 } else {
1091 assert(4096usize / 512 == 8usize);
1092 assert(false);
1093 }
1094 };
1095 assert(m.page_size % new_size == 0) by {
1096 if m.page_size == 2097152 {
1097 assert(2097152usize % 4096 == 0);
1098 } else {
1099 assert(1073741824usize % 2097152 == 0);
1100 }
1101 };
1102 Self::split_if_mapped_huge_spec_preserves_inv(self, new_size);
1103 Self::split_if_mapped_huge_spec_decreases_page_size(self, new_size);
1104 let new_self = self.split_if_mapped_huge_spec(new_size);
1105
1106 assert forall|m2: Mapping, x: Mapping| #[trigger]
1108 new_self.mappings.contains(m2) && #[trigger] other.contains(
1109 x,
1110 ) implies Mapping::disjoint_vaddrs(m2, x) by {
1111 if self.mappings.contains(m2) {
1112 } else {
1114 let new_mappings = Set::<int>::range(
1116 0int,
1117 m.page_size as int / new_size as int,
1118 ).map(|n: int| Self::split_index(m, new_size, n as usize));
1119 assert(new_mappings.contains(m2));
1120 let k = choose|k: int|
1121 0 <= k < m.page_size as int / new_size as int && #[trigger] Self::split_index(
1122 m,
1123 new_size,
1124 k as usize,
1125 ) == m2;
1126 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(
1127 m.page_size as int,
1128 new_size as int,
1129 );
1130 vstd::arithmetic::mul::lemma_mul_inequality(
1131 k + 1,
1132 m.page_size as int / new_size as int,
1133 new_size as int,
1134 );
1135 vstd::arithmetic::mul::lemma_mul_is_distributive_add_other_way(
1136 new_size as int,
1137 k,
1138 1int,
1139 );
1140 vstd::arithmetic::mul::lemma_mul_nonnegative(k, new_size as int);
1141 assert(Mapping::disjoint_vaddrs(m, x));
1143 }
1144 };
1145
1146 new_self.split_while_huge_disjoint(size, other);
1147 }
1148}
1149
1150impl<'rcu, C: PageTableConfig> CursorOwner<'rcu, C> {
1151 proof fn query_mapping_from_subtree(self, qm: Mapping)
1156 requires
1157 self.inv(),
1158 self.in_locked_range(),
1159 self@.inv(),
1160 self@.present(),
1161 qm == self@.query_mapping(),
1162 ensures
1163 PageTableOwner(self.cur_subtree()).view_rec(self.cur_subtree().value.path).contains(qm),
1164 {
1165 let f = self@.mappings.filter(
1166 |m2: Mapping| m2.va_range.start <= self@.cur_va < m2.va_range.end,
1167 );
1168 lemma_set_choose_len(f);
1169 self.mapping_covering_cur_va_from_cur_subtree(qm);
1170 }
1171
1172 pub proof fn split_while_huge_node_noop(self)
1173 requires
1174 self.inv(),
1175 self.in_locked_range(),
1176 self.cur_entry_owner().is_node(),
1177 self.level > 1,
1178 ensures
1179 self@.split_while_huge(page_size((self.level - 1) as PagingLevel)) == self@,
1180 {
1181 self.view_preserves_inv();
1182 if self@.present() {
1183 self.cur_subtree_inv();
1184 let subtree = self.cur_subtree();
1185 let path = subtree.value.path;
1186 let qm = self@.query_mapping();
1187 self.query_mapping_from_subtree(qm);
1188 let cont = self.continuations[self.level - 1];
1189 cont.path().push_tail_property_len(cont.idx as usize);
1190 PageTableOwner(subtree).view_rec_node_page_size_bound(path, qm);
1191 }
1192 }
1193
1194 pub proof fn split_while_huge_absent_noop(self, size: usize)
1197 requires
1198 self.inv(),
1199 self.in_locked_range(),
1200 self.cur_entry_owner().is_absent(),
1201 ensures
1202 self@.split_while_huge(size) == self@,
1203 {
1204 self.view_preserves_inv();
1205 self.cur_entry_absent_not_present();
1206 }
1207
1208 pub proof fn split_while_huge_at_level_noop(self)
1209 requires
1210 self.inv(),
1211 self.in_locked_range(),
1212 ensures
1213 self@.split_while_huge(page_size(self.level as PagingLevel)) == self@,
1214 {
1215 self.view_preserves_inv();
1216 if self@.present() {
1217 self.cur_subtree_inv();
1218 let subtree = self.cur_subtree();
1219 let path = subtree.value.path;
1220 let qm = self@.query_mapping();
1221 self.query_mapping_from_subtree(qm);
1222 let cont = self.continuations[self.level - 1];
1223 cont.path().push_tail_property_len(cont.idx as usize);
1224 PageTableOwner(subtree).view_rec_page_size_bound(path, qm);
1225 }
1226 }
1227
1228 pub proof fn map_branch_frame_split_while_huge(
1238 self,
1239 owner0: Self,
1240 owner_before_frame: Self,
1241 level_before_frame: int,
1242 )
1243 requires
1244 self.inv(),
1245 owner0.inv(),
1246 owner_before_frame.inv(),
1247 1 <= level_before_frame - 1,
1248 level_before_frame <= NR_LEVELS,
1249 self.level == (level_before_frame - 1) as u8,
1250 owner_before_frame@ == owner0@.split_while_huge(
1251 page_size(level_before_frame as PagingLevel),
1252 ),
1253 self@ == owner_before_frame@.split_if_mapped_huge_spec(
1254 page_size((level_before_frame - 1) as PagingLevel),
1255 ),
1256 owner_before_frame@.present(),
1261 owner_before_frame@.query_mapping().page_size == page_size(
1262 level_before_frame as PagingLevel,
1263 ),
1264 {
1265 owner0.view_preserves_inv();
1266 owner_before_frame.view_preserves_inv();
1267 let s_top = page_size(level_before_frame as PagingLevel);
1268 let s_low = page_size((level_before_frame - 1) as PagingLevel);
1269
1270 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_spec_values();
1274 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_ge_page_size(
1275 level_before_frame as PagingLevel,
1276 );
1277 assert(NR_ENTRIES == 512usize) by (compute_only);
1278
1279 owner0@.split_while_huge_compose(s_top, s_low);
1283
1284 owner_before_frame@.split_while_huge_one_step(s_low);
1287 }
1288
1289 pub proof fn find_next_split_push_equals_split_while_huge(self, old_view: CursorView<C>)
1292 requires
1293 self.inv(),
1294 old_view.inv(),
1295 self.cur_entry_owner().is_frame(),
1296 self@.cur_va == old_view.cur_va,
1297 old_view.present(),
1298 old_view.query_mapping().page_size > page_size(self.level as PagingLevel),
1299 old_view.query_mapping().page_size / NR_ENTRIES == page_size(self.level as PagingLevel),
1300 old_view.query_mapping().page_size % page_size(self.level as PagingLevel) == 0,
1301 self@.mappings =~= old_view.split_if_mapped_huge_spec(
1302 page_size(self.level as PagingLevel),
1303 ).mappings,
1304 ensures
1305 self@.mappings == old_view.split_while_huge(
1306 page_size(self.level as PagingLevel),
1307 ).mappings,
1308 {
1309 let ps = page_size(self.level as PagingLevel);
1310 let m = old_view.query_mapping();
1311 let f = old_view.mappings.filter(
1312 |m2: Mapping| m2.va_range.start <= old_view.cur_va < m2.va_range.end,
1313 );
1314 vstd::set::lemma_set_choose_len(f);
1315 assert(m.inv());
1316 assert(NR_ENTRIES == 512usize) by (compute_only);
1317 crate::specs::mm::page_table::cursor::page_size_lemmas::lemma_page_size_spec_values();
1318 assert(set![4096usize, 2097152, 1073741824].contains(ps)) by {
1319 if m.page_size == 2097152 {
1320 assert(2097152usize / 512 == 4096usize);
1321 } else {
1322 assert(1073741824usize / 512 == 2097152usize);
1323 }
1324 };
1325 old_view.split_while_huge_one_step(ps);
1326 }
1327
1328 pub proof fn split_while_huge_cur_va_independent(
1336 v1: CursorView<C>,
1337 v2: CursorView<C>,
1338 size: usize,
1339 )
1340 requires
1341 v1.inv(),
1342 v2.inv(),
1343 v1.mappings =~= v2.mappings,
1344 v1.cur_va <= v2.cur_va,
1345 v1.mappings.filter(
1347 |m: Mapping| v1.cur_va <= m.va_range.start && m.va_range.start < v2.cur_va,
1348 ) =~= Set::<Mapping>::empty(),
1349 !v1.present() && v2.present() ==> v2.query_mapping().page_size <= size,
1355 v1.cur_va < v2.cur_va ==> !v1.present(),
1358 ensures
1359 v1.split_while_huge(size).mappings == v2.split_while_huge(size).mappings,
1360 {
1361 if v1.cur_va == v2.cur_va {
1362 assert(v1 == v2);
1363 }
1364 }
1365}
1366
1367}