ostd/specs/mm/page_table/cursor/
page_size_lemmas.rs1use crate::specs::arch::*;
2
3use vstd::prelude::*;
4
5use crate::arch::mm::PagingConsts;
6use crate::mm::PagingLevel;
7use crate::mm::{KERNEL_VADDR_RANGE, Paddr, Vaddr, nr_subpage_per_huge, page_size};
8
9verus! {
10
11pub proof fn lemma_page_size_spec_level1()
14 ensures
15 page_size(1) == PAGE_SIZE,
16{
17 vstd::arithmetic::mul::lemma_mul_by_zero_is_zero(
18 nr_subpage_per_huge::<PagingConsts>().ilog2() as int,
19 );
20 broadcast use vstd::arithmetic::power2::lemma_pow2;
21
22 vstd::arithmetic::power::lemma_pow0(2int);
23}
24
25pub proof fn lemma_va_align_page_size(va: Vaddr, level: PagingLevel)
29 requires
30 1 <= level <= NR_LEVELS + 1,
31 va % PAGE_SIZE == 0,
32 exists|large_level: PagingLevel|
33 1 <= large_level <= NR_LEVELS + 1 && level <= large_level && va % page_size(large_level)
34 == 0,
35 ensures
36 va % page_size(level) == 0,
37{
38 let large_level: PagingLevel = choose|l: PagingLevel|
39 1 <= l <= NR_LEVELS + 1 && level <= l && va % page_size(l) == 0;
40 if level == 1nat {
41 lemma_page_size_spec_level1();
42 } else {
43 let ps_l = page_size(level) as int;
44 let ps_ll = page_size(large_level) as int;
45 lemma_page_size_ge_page_size(level);
46 lemma_page_size_ge_page_size(large_level);
47 lemma_page_size_divides(level, large_level);
48 assert(ps_ll >= ps_l) by {
49 if ps_ll < ps_l {
50 vstd::arithmetic::div_mod::lemma_small_mod(ps_ll as nat, ps_l as nat);
51 }
52 };
53 let k = ps_ll / ps_l;
54 vstd::arithmetic::div_mod::lemma_div_non_zero(ps_ll, ps_l);
55 vstd::arithmetic::div_mod::lemma_fundamental_div_mod(ps_ll, ps_l);
56 vstd::arithmetic::div_mod::lemma_mod_mod(va as int, ps_l, k);
57 assert(va as int % ps_l == 0);
58 }
59}
60
61pub proof fn lemma_va_align_page_size_level_1(va: Vaddr)
64 requires
65 va % PAGE_SIZE == 0,
66 ensures
67 va % page_size(1) == 0,
68{
69 lemma_page_size_spec_level1();
70}
71
72pub proof fn lemma_page_size_multiple_of_page_size(level: PagingLevel)
74 requires
75 1 <= level <= NR_LEVELS,
76 ensures
77 page_size(level) % PAGE_SIZE == 0,
78{
79 lemma_page_size_spec_values();
80}
81
82pub proof fn lemma_page_size_ge_page_size(level: PagingLevel)
84 requires
85 1 <= level <= NR_LEVELS + 1,
86 ensures
87 page_size(level) >= PAGE_SIZE,
88{
89 lemma_page_size_spec_values();
90}
91
92pub proof fn lemma_page_size_monotone(l1: PagingLevel, l2: PagingLevel)
94 requires
95 1 <= l1 <= l2 <= NR_LEVELS + 1,
96 ensures
97 page_size(l1) <= page_size(l2),
98{
99 if l1 != l2 {
100 let ps1 = page_size(l1);
101 let ps2 = page_size(l2);
102
103 lemma_page_size_ge_page_size(l1);
104 lemma_page_size_ge_page_size(l2);
105 lemma_page_size_divides(l1, l2);
106
107 assert(ps1 <= ps2) by {
108 if ps2 < ps1 {
109 vstd::arithmetic::div_mod::lemma_small_mod(ps2 as nat, ps1 as nat);
110 }
111 };
112 }
113}
114
115pub proof fn lemma_page_size_spec_values()
116 ensures
117 page_size(1) == 4096,
118 page_size(2) == 2097152,
119 page_size(3) == 1073741824,
120 page_size(4) == 549755813888,
121 page_size(5) == 281474976710656,
122{
123 lemma_page_size_spec_level1();
124 vstd_extra::external::ilog2::lemma_usize_ilog2_to32();
125 vstd::arithmetic::power2::lemma2_to64();
126 vstd::arithmetic::power2::lemma2_to64_rest();
127 vstd::bits::lemma_usize_pow2_no_overflow(48);
128}
129
130pub proof fn lemma_page_size_div_mul_eq(level: PagingLevel)
133 requires
134 1 <= level <= NR_LEVELS + 1,
135 ensures
136 (page_size(level) / PAGE_SIZE) * PAGE_SIZE == page_size(level),
137{
138 lemma_page_size_spec_values();
139}
140
141pub proof fn lemma_nr_entries_times_sub_page_size(level: PagingLevel)
144 requires
145 2 <= level <= NR_LEVELS + 1,
146 ensures
147 NR_ENTRIES * page_size((level - 1) as PagingLevel) == page_size(level),
148{
149 lemma_page_size_spec_values();
150 crate::arch::mm::lemma_nr_subpage_per_huge_eq_nr_entries();
151}
152
153pub proof fn lemma_split_sub_page_big_j(pa: Paddr, level: PagingLevel, i: usize) -> (big_j: usize)
164 requires
165 2 <= level <= NR_LEVELS,
166 0 < i < NR_ENTRIES,
167 ensures
168 0 < big_j < page_size(level) / PAGE_SIZE,
169 pa + i * page_size((level - 1) as PagingLevel) == pa + big_j * PAGE_SIZE,
170 big_j == i * (page_size((level - 1) as PagingLevel) / PAGE_SIZE),
171{
172 let sub_pages_per_entry: int = (page_size((level - 1) as PagingLevel) / PAGE_SIZE) as int;
173 let big_j_int: int = i * sub_pages_per_entry;
174 lemma_page_size_spec_values();
175 lemma_page_size_div_mul_eq((level - 1) as PagingLevel);
176 lemma_page_size_div_mul_eq(level);
177 lemma_nr_entries_times_sub_page_size(level);
178 vstd::arithmetic::mul::lemma_mul_strictly_positive(i as int, sub_pages_per_entry);
179 vstd::arithmetic::mul::lemma_mul_strict_inequality(
180 i as int,
181 NR_ENTRIES as int,
182 sub_pages_per_entry,
183 );
184 vstd::arithmetic::mul::lemma_mul_is_associative(
185 NR_ENTRIES as int,
186 sub_pages_per_entry,
187 PAGE_SIZE as int,
188 );
189 vstd::arithmetic::div_mod::lemma_div_by_multiple(
190 NR_ENTRIES as int * sub_pages_per_entry,
191 PAGE_SIZE as int,
192 );
193 vstd::arithmetic::mul::lemma_mul_is_associative(
194 i as int,
195 sub_pages_per_entry,
196 PAGE_SIZE as int,
197 );
198 big_j_int as usize
199}
200
201pub proof fn lemma_page_size_divides(l1: PagingLevel, l2: PagingLevel)
205 requires
206 1 <= l1 <= l2 <= NR_LEVELS + 1,
207 ensures
208 page_size(l2) % page_size(l1) == 0,
209{
210 lemma_page_size_spec_values();
211 if l1 == 1 {
213 } else if l1 == 2 {
214 } else if l1 == 3 {
215 } else if l1 == 4 {
216 } else {
217 assert(l1 == 5);
218 }
219}
220
221pub proof fn lemma_pa_plus_page_size_no_overflow(pa: Paddr, level: PagingLevel)
225 requires
226 1 <= level <= NR_LEVELS,
227 pa < MAX_PADDR,
228 ensures
229 pa + page_size(level) < usize::MAX,
230{
231 lemma_page_size_spec_values();
232}
233
234pub proof fn lemma_va_plus_page_size_no_overflow(va: Vaddr, len: usize)
243 requires
244 va + len <= KERNEL_VADDR_RANGE.end,
245 ensures
246 va + len <= usize::MAX,
247{
248 assert(KERNEL_VADDR_RANGE.end == 0xffff_ffff_ffff_0000usize) by (compute_only);
249}
250
251pub proof fn lemma_max_mappings_fit_usize()
254 ensures
255 MAX_PADDR / PAGE_SIZE < usize::MAX,
256{
257 assert(MAX_PADDR / PAGE_SIZE < usize::MAX) by (compute_only);
258}
259
260}