ostd/specs/mm/page_table/cursor/
page_size_lemmas.rs1use vstd::arithmetic::power2::pow2;
2use vstd::prelude::*;
3
4use crate::mm::page_table::{page_size, page_size_spec};
5use crate::mm::PagingLevel;
6use crate::mm::{nr_subpage_per_huge, Paddr, Vaddr, MAX_PADDR};
7use crate::specs::arch::mm::{KERNEL_VADDR_RANGE, NR_LEVELS, PAGE_SIZE};
8use crate::specs::arch::paging_consts::PagingConsts;
9
10verus! {
11
12pub proof fn lemma_page_size_spec_level1()
17 ensures
18 page_size_spec(1) == PAGE_SIZE,
19{
20 vstd::arithmetic::mul::lemma_mul_by_zero_is_zero(
21 nr_subpage_per_huge::<PagingConsts>().ilog2() as int,
22 );
23 broadcast use vstd::arithmetic::power2::lemma_pow2;
24 vstd::arithmetic::power::lemma_pow0(2int);
25}
26
27pub proof fn lemma_va_align_page_size(va: Vaddr, level: PagingLevel)
32 requires
33 1 <= level <= NR_LEVELS + 1,
34 va % PAGE_SIZE == 0,
35 exists|large_level: PagingLevel|
36 1 <= large_level <= NR_LEVELS + 1 && level <= large_level && va % page_size_spec(
37 large_level,
38 ) == 0,
39 ensures
40 va % page_size_spec(level) == 0,
41{
42 let large_level: PagingLevel = choose|l: PagingLevel|
43 1 <= l <= NR_LEVELS + 1 && level <= l && va % page_size_spec(l) == 0;
44 if level == 1nat {
45 lemma_page_size_spec_level1();
46 } else {
47 let ps_l = page_size_spec(level) as int;
48 let ps_ll = page_size_spec(large_level) as int;
49 lemma_page_size_ge_page_size(level);
50 lemma_page_size_ge_page_size(large_level);
51 lemma_page_size_divides(level, large_level);
52 assert(ps_ll >= ps_l) by {
53 if ps_ll < ps_l {
54 vstd::arithmetic::div_mod::lemma_small_mod(ps_ll as nat, ps_l as nat);
55 }
56 };
57 let k = ps_ll / ps_l;
58 vstd::arithmetic::div_mod::lemma_div_non_zero(ps_ll, ps_l);
59 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps_ll, ps_l);
60 vstd::arithmetic::div_mod::lemma_mod_mod(va as int, ps_l, k);
61 assert(va as int % ps_l == 0);
62 }
63}
64
65pub proof fn lemma_va_align_page_size_level_1(va: Vaddr)
68 requires
69 va % PAGE_SIZE == 0,
70 ensures
71 va % page_size_spec(1) == 0,
72{
73 lemma_page_size_spec_level1();
74}
75
76pub proof fn lemma_page_size_multiple_of_page_size(level: PagingLevel)
78 requires
79 1 <= level <= NR_LEVELS,
80 ensures
81 page_size_spec(level) % PAGE_SIZE == 0,
82{
83 lemma_page_size_spec_values();
84}
85
86pub proof fn lemma_page_size_ge_page_size(level: PagingLevel)
90 requires
91 1 <= level <= NR_LEVELS + 1,
92 ensures
93 page_size(level) >= PAGE_SIZE,
94{
95 lemma_page_size_spec_values();
96 if level == 1 {
100 } else if level == 2 {
101 } else if level == 3 {
102 } else if level == 4 {
103 } else {
104 }
105}
106
107pub proof fn lemma_page_size_monotone(l1: PagingLevel, l2: PagingLevel)
111 requires
112 1 <= l1 <= NR_LEVELS + 1,
113 1 <= l2 <= NR_LEVELS + 1,
114 l1 <= l2,
115 ensures
116 page_size(l1) <= page_size(l2),
117{
118 if l1 != l2 {
119 let ps1 = page_size(l1);
120 let ps2 = page_size(l2);
121
122 lemma_page_size_ge_page_size(l1);
123 lemma_page_size_ge_page_size(l2);
124 lemma_page_size_divides(l1, l2);
125
126 assert(ps1 <= ps2) by {
127 if ps2 < ps1 {
128 vstd::arithmetic::div_mod::lemma_small_mod(ps2 as nat, ps1 as nat);
129 }
130 };
131 }
132}
133
134pub proof fn lemma_page_size_spec_values()
135 ensures
136 page_size_spec(1) == 4096,
137 page_size_spec(2) == 2097152,
138 page_size_spec(3) == 1073741824,
139 page_size_spec(4) == 549755813888,
140 page_size_spec(5) == 281474976710656,
141{
142 lemma_page_size_spec_level1();
143 vstd_extra::external::ilog2::lemma_usize_ilog2_to32();
144 vstd::arithmetic::power2::lemma2_to64();
145 vstd::arithmetic::power2::lemma2_to64_rest();
146 vstd::bits::lemma_usize_pow2_no_overflow(48);
147}
148
149pub proof fn lemma_page_size_div_mul_eq(level: PagingLevel)
152 requires
153 1 <= level <= NR_LEVELS + 1,
154 ensures
155 (page_size_spec(level) / PAGE_SIZE) * PAGE_SIZE == page_size_spec(level),
156{
157 lemma_page_size_spec_values();
158}
159
160pub proof fn lemma_nr_entries_times_sub_page_size(level: PagingLevel)
163 requires
164 2 <= level <= NR_LEVELS + 1,
165 ensures
166 crate::specs::arch::mm::NR_ENTRIES as int * page_size_spec((level - 1) as PagingLevel) as int
167 == page_size_spec(level) as int,
168{
169 lemma_page_size_spec_values();
170 crate::specs::arch::paging_consts::lemma_nr_subpage_per_huge_eq_nr_entries();
171}
172
173pub proof fn lemma_split_sub_page_big_j(
184 pa: Paddr,
185 level: PagingLevel,
186 i: usize,
187) -> (big_j: usize)
188 requires
189 2 <= level <= NR_LEVELS,
190 0 < i < crate::specs::arch::mm::NR_ENTRIES,
191 ensures
192 0 < big_j < page_size_spec(level) / PAGE_SIZE,
193 (pa + i * page_size_spec((level - 1) as PagingLevel)) as int
194 == pa as int + big_j as int * PAGE_SIZE as int,
195 big_j as int == i as int * (page_size_spec((level - 1) as PagingLevel) / PAGE_SIZE) as int,
196{
197 let sub_pages_per_entry: int =
198 (page_size_spec((level - 1) as PagingLevel) / PAGE_SIZE) as int;
199 let big_j_int: int = i as int * sub_pages_per_entry;
200 lemma_page_size_spec_values();
201 lemma_page_size_div_mul_eq((level - 1) as PagingLevel);
202 lemma_page_size_div_mul_eq(level);
203 lemma_nr_entries_times_sub_page_size(level);
204 vstd::arithmetic::mul::lemma_mul_strictly_positive(
205 i as int, sub_pages_per_entry);
206 vstd::arithmetic::mul::lemma_mul_strict_inequality(
207 i as int, crate::specs::arch::mm::NR_ENTRIES as int, sub_pages_per_entry);
208 vstd::arithmetic::mul::lemma_mul_is_associative(
209 crate::specs::arch::mm::NR_ENTRIES as int, sub_pages_per_entry, PAGE_SIZE as int);
210 vstd::arithmetic::div_mod::lemma_div_by_multiple(
211 crate::specs::arch::mm::NR_ENTRIES as int * sub_pages_per_entry, PAGE_SIZE as int);
212 vstd::arithmetic::mul::lemma_mul_is_associative(
213 i as int, sub_pages_per_entry, PAGE_SIZE as int);
214 big_j_int as usize
215}
216
217pub proof fn lemma_page_size_divides(l1: PagingLevel, l2: PagingLevel)
221 requires
222 1 <= l1 <= l2 <= NR_LEVELS + 1,
223 ensures
224 page_size_spec(l2) % page_size_spec(l1) == 0,
225{
226 lemma_page_size_spec_values();
227}
228
229pub proof fn lemma_pa_plus_page_size_no_overflow(pa: Paddr, level: PagingLevel)
233 requires
234 1 <= level <= NR_LEVELS,
235 pa < MAX_PADDR,
236 ensures
237 pa + page_size(level) < usize::MAX,
238{
239 lemma_page_size_spec_values();
240}
241
242pub proof fn lemma_va_plus_page_size_no_overflow(
251 va: Vaddr,
252 len: usize,
253)
254 requires
255 va + len <= KERNEL_VADDR_RANGE.end,
256 ensures
257 va + len <= usize::MAX,
258{
259 assert(KERNEL_VADDR_RANGE.end == 0xffff_ffff_ffff_0000usize) by (compute_only);
260 assert(va + len <= 0xffff_ffff_ffff_0000usize);
261}
262
263pub proof fn lemma_max_mappings_fit_usize()
266 ensures
267 MAX_PADDR / PAGE_SIZE < usize::MAX,
268{
269 assert(MAX_PADDR / PAGE_SIZE < usize::MAX) by (compute_only);
270}
271
272}