ostd/specs/mm/page_table/cursor/
page_size_lemmas.rs1use vstd::{
2 arithmetic::{
3 div_mod::lemma_fundamental_div_mod,
4 mul::{lemma_mul_inequality, lemma_mul_is_distributive_sub},
5 power2::{lemma_pow2_adds, lemma_pow2_pos, pow2},
6 },
7 bits::lemma_usize_pow2_no_overflow,
8 prelude::*,
9};
10use vstd_extra::{external::ilog2::lemma_usize_is_pow2_is_ilog2_pow2, prelude::*};
11
12use crate::specs::arch::*;
13use crate::specs::mm::page_table::{nr_pte_index_bits_spec, pte_index_bit_offset_spec};
14
15use crate::arch::mm::PagingConsts;
16use crate::mm::{
17 KERNEL_VADDR_RANGE, Paddr, PagingConstsTrait, PagingLevel, Vaddr, nr_subpage_per_huge,
18 page_size,
19};
20
21verus! {
22
23pub proof fn lemma_page_size_is_pow2_pte_index_bit_offset<C: PagingConstsTrait>(level: PagingLevel)
25 requires
26 1 <= level <= C::NR_LEVELS() + 1,
27 ensures
28 pte_index_bit_offset_spec::<C>(level) < usize::BITS,
29 pte_index_bit_offset_spec::<C>(level) == C::BASE_PAGE_SIZE().ilog2()
30 + nr_pte_index_bits_spec::<C>() * (level - 1),
31 0 < page_size::<C>(level) == pow2(pte_index_bit_offset_spec::<C>(level) as nat),
32{
33 C::lemma_paging_consts_properties();
34 let bits = nr_pte_index_bits_spec::<C>();
35 lemma_usize_is_pow2_is_ilog2_pow2(C::BASE_PAGE_SIZE());
36 lemma_usize_is_pow2_is_ilog2_pow2(nr_subpage_per_huge::<C>());
37 lemma_mul_inequality(level - 1, C::NR_LEVELS() as int, bits as int);
38 lemma_pow2_adds(C::BASE_PAGE_SIZE().ilog2() as nat, (bits * (level - 1)) as nat);
39 lemma_usize_pow2_no_overflow(pte_index_bit_offset_spec::<C>(level) as nat);
40}
41
42pub proof fn lemma_page_size_ratio<C: PagingConstsTrait>(small: PagingLevel, large: PagingLevel)
45 requires
46 1 <= small <= large <= C::NR_LEVELS() + 1,
47 ensures
48 pte_index_bit_offset_spec::<C>(large) == pte_index_bit_offset_spec::<C>(small)
49 + nr_pte_index_bits_spec::<C>() * (large - small),
50 page_size::<C>(large) == page_size::<C>(small) * pow2(
51 (nr_pte_index_bits_spec::<C>() * (large - small)) as nat,
52 ),
53{
54 C::lemma_paging_consts_properties();
55 lemma_page_size_is_pow2_pte_index_bit_offset::<C>(small);
56 lemma_page_size_is_pow2_pte_index_bit_offset::<C>(large);
57 let bits = nr_pte_index_bits_spec::<C>();
58 let delta = (bits * (large - small)) as nat;
59 lemma_mul_is_distributive_sub(bits as int, large as int, small as int);
60 lemma_mul_is_distributive_sub(bits as int, large as int, 1);
61 lemma_mul_is_distributive_sub(bits as int, small as int, 1);
62 lemma_pow2_adds(pte_index_bit_offset_spec::<C>(small) as nat, delta);
63 lemma_pow2_pos(delta);
64}
65
66pub proof fn lemma_page_size_next<C: PagingConstsTrait>(level: PagingLevel)
68 requires
69 1 <= level <= C::NR_LEVELS(),
70 ensures
71 page_size::<C>((level + 1) as PagingLevel) == page_size::<C>(level) * nr_subpage_per_huge::<
72 C,
73 >(),
74 0 < page_size::<C>(level) <= page_size::<C>((level + 1) as PagingLevel),
75{
76 C::lemma_paging_consts_properties();
77 lemma_page_size_is_pow2_pte_index_bit_offset::<C>(level);
78 lemma_page_size_is_pow2_pte_index_bit_offset::<C>((level + 1) as PagingLevel);
79 let bits = nr_pte_index_bits_spec::<C>();
80 lemma_usize_is_pow2_is_ilog2_pow2(nr_subpage_per_huge::<C>());
81 lemma_mul_is_distributive_sub(bits as int, level as int, 1);
82 lemma_pow2_adds(pte_index_bit_offset_spec::<C>(level) as nat, bits as nat);
83 vstd::arithmetic::mul::lemma_mul_left_inequality(
84 page_size::<C>(level) as int,
85 1,
86 nr_subpage_per_huge::<C>() as int,
87 );
88 vstd::arithmetic::mul::lemma_mul_basics(page_size::<C>(level) as int);
89}
90
91pub proof fn lemma_page_size_divides<C: PagingConstsTrait>(small: PagingLevel, large: PagingLevel)
93 requires
94 1 <= small <= large <= C::NR_LEVELS() + 1,
95 ensures
96 0 < page_size::<C>(small) <= page_size::<C>(large),
97 page_size::<C>(large) % page_size::<C>(small) == 0,
98{
99 C::lemma_paging_consts_properties();
100 lemma_page_size_is_pow2_pte_index_bit_offset::<C>(small);
101 lemma_page_size_is_pow2_pte_index_bit_offset::<C>(large);
102 lemma_page_size_ratio::<C>(small, large);
103 let delta = (nr_pte_index_bits_spec::<C>() * (large - small)) as nat;
104 lemma_pow2_pos(delta);
105 let a = page_size::<C>(small) as int;
106 let ratio = pow2(delta) as int;
107 vstd::arithmetic::div_mod::lemma_mod_multiples_basic(ratio, a);
108 vstd::arithmetic::mul::lemma_mul_is_commutative(a, ratio);
109 vstd::arithmetic::mul::lemma_mul_left_inequality(a, 1, ratio);
110 vstd::arithmetic::mul::lemma_mul_basics(a);
111}
112
113pub proof fn lemma_page_size_base<C: PagingConstsTrait>()
115 ensures
116 page_size::<C>(1) == C::BASE_PAGE_SIZE(),
117{
118 reveal(vstd::arithmetic::power::pow);
119 vstd::arithmetic::power2::lemma_pow2(0);
120 assert(pow2(0) == 1);
121 vstd::arithmetic::mul::lemma_mul_basics(nr_pte_index_bits_spec::<C>() as int);
122 vstd::arithmetic::mul::lemma_mul_basics(C::BASE_PAGE_SIZE() as int);
123}
124
125pub proof fn lemma_page_size_ge_base<C: PagingConstsTrait>(level: PagingLevel)
127 requires
128 1 <= level <= C::NR_LEVELS() + 1,
129 ensures
130 C::BASE_PAGE_SIZE() <= page_size::<C>(level),
131{
132 lemma_page_size_base::<C>();
133 lemma_page_size_divides::<C>(1, level);
134}
135
136pub proof fn lemma_page_size_monotone<C: PagingConstsTrait>(l1: PagingLevel, l2: PagingLevel)
138 requires
139 1 <= l1 <= l2 <= C::NR_LEVELS() + 1,
140 ensures
141 page_size::<C>(l1) <= page_size::<C>(l2),
142{
143 lemma_page_size_divides::<C>(l1, l2);
144}
145
146pub proof fn lemma_page_size_div_mul_eq<C: PagingConstsTrait>(level: PagingLevel)
148 requires
149 1 <= level <= C::NR_LEVELS() + 1,
150 ensures
151 (page_size::<C>(level) / C::BASE_PAGE_SIZE()) * C::BASE_PAGE_SIZE() == page_size::<C>(
152 level,
153 ),
154{
155 lemma_page_size_base::<C>();
156 lemma_page_size_divides::<C>(1, level);
157 lemma_fundamental_div_mod(page_size::<C>(level) as int, page_size::<C>(1) as int);
158}
159
160pub proof fn lemma_va_align_page_size<C: PagingConstsTrait>(va: Vaddr, level: PagingLevel)
163 requires
164 1 <= level <= C::NR_LEVELS() + 1,
165 va % C::BASE_PAGE_SIZE() == 0,
166 exists|large_level: PagingLevel|
167 1 <= large_level <= C::NR_LEVELS() + 1 && level <= large_level && va % page_size::<C>(
168 large_level,
169 ) == 0,
170 ensures
171 va % page_size::<C>(level) == 0,
172{
173 let large_level: PagingLevel = choose|l: PagingLevel|
174 1 <= l <= C::NR_LEVELS() + 1 && level <= l && va % page_size::<C>(l) == 0;
175 if level == 1nat {
176 lemma_page_size_base::<C>();
177 } else {
178 let ps_l = page_size::<C>(level) as int;
179 let ps_ll = page_size::<C>(large_level) as int;
180 lemma_page_size_divides::<C>(level, large_level);
181 let k = ps_ll / ps_l;
182 vstd::arithmetic::div_mod::lemma_div_non_zero(ps_ll, ps_l);
183 lemma_fundamental_div_mod(ps_ll, ps_l);
184 vstd::arithmetic::div_mod::lemma_mod_mod(va as int, ps_l, k);
185 assert(va as int % ps_l == 0);
186 }
187}
188
189pub proof fn lemma_va_align_page_size_level_1<C: PagingConstsTrait>(va: Vaddr)
191 requires
192 va % C::BASE_PAGE_SIZE() == 0,
193 ensures
194 va % page_size::<C>(1) == 0,
195{
196 lemma_page_size_base::<C>();
197}
198
199pub proof fn lemma_page_size_spec_values()
201 ensures
202 page_size::<PagingConsts>(1) == 4096,
203 page_size::<PagingConsts>(2) == 2097152,
204 page_size::<PagingConsts>(3) == 1073741824,
205 page_size::<PagingConsts>(4) == 549755813888,
206 page_size::<PagingConsts>(5) == 281474976710656,
207{
208 lemma_page_size_base::<PagingConsts>();
209 vstd_extra::external::ilog2::lemma_usize_ilog2_to32();
210 vstd::arithmetic::power2::lemma2_to64();
211 vstd::arithmetic::power2::lemma2_to64_rest();
212 vstd::bits::lemma_usize_pow2_no_overflow(48);
213}
214
215pub proof fn lemma_split_sub_page_big_j(pa: Paddr, level: PagingLevel, i: usize) -> (big_j: usize)
218 requires
219 2 <= level <= NR_LEVELS,
220 0 < i < NR_ENTRIES,
221 ensures
222 0 < big_j < page_size::<PagingConsts>(level) / PAGE_SIZE,
223 pa + i * page_size::<PagingConsts>((level - 1) as PagingLevel) == pa + big_j * PAGE_SIZE,
224 big_j == i * (page_size::<PagingConsts>((level - 1) as PagingLevel) / PAGE_SIZE),
225{
226 PagingConsts::lemma_paging_consts_properties();
227 let sub_pages_per_entry: int = (page_size::<PagingConsts>((level - 1) as PagingLevel)
228 / PAGE_SIZE) as int;
229 let big_j_int: int = i * sub_pages_per_entry;
230 lemma_page_size_spec_values();
231 lemma_page_size_div_mul_eq::<PagingConsts>((level - 1) as PagingLevel);
232 lemma_page_size_div_mul_eq::<PagingConsts>(level);
233 lemma_page_size_next::<PagingConsts>((level - 1) as PagingLevel);
234 crate::arch::mm::lemma_nr_subpage_per_huge_eq_nr_entries();
235 vstd::arithmetic::mul::lemma_mul_strictly_positive(i as int, sub_pages_per_entry);
236 vstd::arithmetic::mul::lemma_mul_strict_inequality(
237 i as int,
238 NR_ENTRIES as int,
239 sub_pages_per_entry,
240 );
241 vstd::arithmetic::mul::lemma_mul_is_associative(
242 NR_ENTRIES as int,
243 sub_pages_per_entry,
244 PAGE_SIZE as int,
245 );
246 vstd::arithmetic::div_mod::lemma_div_by_multiple(
247 NR_ENTRIES as int * sub_pages_per_entry,
248 PAGE_SIZE as int,
249 );
250 vstd::arithmetic::mul::lemma_mul_is_associative(
251 i as int,
252 sub_pages_per_entry,
253 PAGE_SIZE as int,
254 );
255 big_j_int as usize
256}
257
258pub proof fn lemma_va_plus_page_size_no_overflow(va: Vaddr, len: usize)
261 requires
262 va + len <= KERNEL_VADDR_RANGE.end,
263 ensures
264 va + len <= usize::MAX,
265{
266 assert(KERNEL_VADDR_RANGE.end == 0xffff_ffff_ffff_0000usize) by (compute_only);
267}
268
269}