1use crate::specs::arch::*;
4use vstd::arithmetic::div_mod::group_div_basics;
5use vstd::arithmetic::power2::*;
6use vstd::prelude::*;
7
8pub type Vaddr = usize;
10
11pub type Paddr = usize;
13
14pub(crate) mod dma;
15pub mod frame;
16pub mod io;
18pub mod kspace;
19pub(crate) mod page_prop;
20pub mod page_table;
21pub mod tlb;
22pub mod vm_space;
23
24#[cfg(ktest)]
25mod test;
26
27use core::{fmt::Debug, ops::Range};
28
29pub use self::io::{
30 Fallible, FallibleVmRead, FallibleVmWrite, Infallible, PodOnce, VmIo, VmIoOnce, VmReader,
31 VmWriter,
32};
33#[doc(hidden)]
34pub use crate::arch::mm::PagingConsts;
35
36#[doc(hidden)]
38pub use self::kspace::paddr_to_vaddr;
39
40#[doc(hidden)]
42pub use page_table::largest_pages;
43
44pub type PagingLevel = u8;
46
47verus! {
48
49pub trait PagingConstsTrait: Clone + Debug + Send + Sync + 'static {
52 spec fn BASE_PAGE_SIZE_spec() -> usize;
53
54 #[verifier::when_used_as_spec(BASE_PAGE_SIZE_spec)]
57 fn BASE_PAGE_SIZE() -> (res: usize)
58 returns
59 Self::BASE_PAGE_SIZE(),
60 ;
61
62 spec fn NR_LEVELS_spec() -> PagingLevel;
63
64 #[verifier::when_used_as_spec(NR_LEVELS_spec)]
70 fn NR_LEVELS() -> (res: PagingLevel)
71 returns
72 Self::NR_LEVELS(),
73 ;
74
75 spec fn HIGHEST_TRANSLATION_LEVEL_spec() -> PagingLevel;
76
77 #[verifier::when_used_as_spec(HIGHEST_TRANSLATION_LEVEL_spec)]
80 fn HIGHEST_TRANSLATION_LEVEL() -> PagingLevel
81 returns
82 Self::HIGHEST_TRANSLATION_LEVEL(),
83 ;
84
85 spec fn PTE_SIZE_spec() -> usize;
86
87 #[verifier::when_used_as_spec(PTE_SIZE_spec)]
89 fn PTE_SIZE() -> (res: usize)
90 returns
91 Self::PTE_SIZE(),
92 ;
93
94 spec fn ADDRESS_WIDTH_spec() -> usize;
95
96 #[verifier::when_used_as_spec(ADDRESS_WIDTH_spec)]
99 fn ADDRESS_WIDTH() -> (res: usize)
100 returns
101 Self::ADDRESS_WIDTH(),
102 ;
103
104 spec fn VA_SIGN_EXT_spec() -> bool;
105
106 #[verifier::when_used_as_spec(VA_SIGN_EXT_spec)]
118 fn VA_SIGN_EXT() -> bool
119 returns
120 Self::VA_SIGN_EXT(),
121 ;
122
123 proof fn lemma_paging_consts_requirements()
140 ensures
141 0 < Self::BASE_PAGE_SIZE(),
142 is_pow2(Self::BASE_PAGE_SIZE() as int),
143 Self::NR_LEVELS() > 0,
144 is_pow2(Self::PTE_SIZE() as int),
145 0 < Self::PTE_SIZE() <= Self::BASE_PAGE_SIZE(),
146 0 < Self::ADDRESS_WIDTH() < usize::BITS,
147 Self::BASE_PAGE_SIZE().ilog2() + (Self::BASE_PAGE_SIZE() / Self::PTE_SIZE()).ilog2()
148 * Self::NR_LEVELS() <= Self::ADDRESS_WIDTH(),
149 Self::PTE_SIZE() == core::mem::size_of::<usize>(),
150 Self::BASE_PAGE_SIZE() == PAGE_SIZE,
154 Self::NR_LEVELS() == NR_LEVELS,
155 Self::BASE_PAGE_SIZE() / Self::PTE_SIZE() == NR_ENTRIES,
156 ;
157
158 proof fn lemma_paging_consts_properties()
162 ensures
163 Self::BASE_PAGE_SIZE().ilog2() + (Self::BASE_PAGE_SIZE() / Self::PTE_SIZE()).ilog2() * (
166 Self::NR_LEVELS() - 1) <= Self::ADDRESS_WIDTH(),
167 0 < Self::BASE_PAGE_SIZE() / Self::PTE_SIZE() <= Self::BASE_PAGE_SIZE(),
168 NR_ENTRIES * Self::PTE_SIZE() == PAGE_SIZE,
169 0 < Self::BASE_PAGE_SIZE(),
172 is_pow2(Self::BASE_PAGE_SIZE() as int),
173 Self::NR_LEVELS() > 0,
174 is_pow2(Self::PTE_SIZE() as int),
175 0 < Self::PTE_SIZE() <= Self::BASE_PAGE_SIZE(),
176 0 < Self::ADDRESS_WIDTH() < usize::BITS,
177 Self::BASE_PAGE_SIZE().ilog2() + (Self::BASE_PAGE_SIZE() / Self::PTE_SIZE()).ilog2()
178 * Self::NR_LEVELS() <= Self::ADDRESS_WIDTH(),
179 Self::PTE_SIZE() == core::mem::size_of::<usize>(),
180 Self::BASE_PAGE_SIZE() == PAGE_SIZE,
184 Self::NR_LEVELS() == NR_LEVELS,
185 Self::BASE_PAGE_SIZE() / Self::PTE_SIZE() == NR_ENTRIES,
186 {
187 Self::lemma_paging_consts_requirements();
188 broadcast use group_div_basics;
189
190 }
191}
192
193pub open spec fn page_size_spec(level: PagingLevel) -> usize {
194 (PAGE_SIZE * pow2(
195 (nr_subpage_per_huge::<PagingConsts>().ilog2() * (level - 1)) as nat,
196 )) as usize
197}
198
199#[verifier::when_used_as_spec(page_size_spec)]
203pub fn page_size(level: PagingLevel) -> (ret: usize)
204 requires
205 1 <= level <= NR_LEVELS + 1,
206 ensures
207 ret == page_size_spec(level),
208 is_pow2(ret as int),
209 ret >= PAGE_SIZE,
210{
211 proof {
212 let index_bits: usize = nr_subpage_per_huge::<PagingConsts>().ilog2() as usize;
213 PagingConsts::lemma_paging_consts_properties();
214 crate::arch::mm::lemma_nr_subpage_per_huge_eq_nr_entries();
215 vstd::layout::unsigned_int_max_values();
216 vstd::arithmetic::power2::lemma2_to64();
217 vstd::arithmetic::power2::lemma2_to64_rest();
218 vstd_extra::external::ilog2::lemma_usize_pow2_ilog2(9);
219 let level_index: usize = (level - 1) as usize;
220 let shift: usize = (index_bits * level_index) as usize;
221 let ghost shift_nat = shift as nat;
222 let ghost page_shift = 12nat + shift_nat;
223
224 vstd::arithmetic::power2::lemma_pow2_adds(12, shift_nat);
225 if page_shift < 48nat {
226 vstd::arithmetic::power2::lemma_pow2_strictly_increases(page_shift, 48nat);
227 }
228 vstd::bits::lemma_usize_shl_is_mul(PAGE_SIZE, shift);
229 vstd_extra::external::ilog2::lemma_usize_pow2_shl_is_pow2(PAGE_SIZE, shift);
230 }
231 PAGE_SIZE << (nr_subpage_per_huge::<PagingConsts>().ilog2() as usize * (level as usize - 1))
232}
233
234#[verifier::inline]
235pub open spec fn nr_subpage_per_huge_spec<C: PagingConstsTrait>() -> usize {
236 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
237}
238
239#[verifier::when_used_as_spec(nr_subpage_per_huge_spec)]
241pub fn nr_subpage_per_huge<C: PagingConstsTrait>() -> (res: usize)
242 ensures
243 res == nr_subpage_per_huge_spec::<C>(),
244{
245 proof {
246 C::lemma_paging_consts_properties();
247 }
248 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
249}
250
251pub const MAX_USERSPACE_VADDR: Vaddr = 0x0000_8000_0000_0000_usize - PAGE_SIZE;
262
263pub const KERNEL_VADDR_RANGE: Range<Vaddr> =
268 0xffff_8000_0000_0000_usize..0xffff_ffff_ffff_0000_usize;
269
270pub trait HasPaddr {
272 fn paddr(&self) -> Paddr;
274}
275
276pub const fn is_page_aligned(p: usize) -> bool {
278 (p & (PAGE_SIZE - 1)) == 0
279}
280
281}