1use crate::specs::arch::PAGE_SIZE;
4use core::fmt::Debug;
5use vstd::arithmetic::div_mod::group_div_basics;
6use vstd::arithmetic::div_mod::lemma_div_non_zero;
7use vstd::arithmetic::power2::*;
8use vstd::prelude::*;
9
10pub type Vaddr = usize;
12
13pub type Paddr = usize;
15
16pub const MAX_NR_LEVELS: usize = 4;
18
19pub(crate) mod dma;
20pub mod frame;
21pub mod io;
23pub use io::{
24 Fallible, FallibleVmRead, FallibleVmWrite, Infallible, VmIo, VmIoOnce, VmReader, VmWriter,
25};
26pub mod kspace;
27pub(crate) mod page_prop;
28pub mod page_table;
29pub mod tlb;
30pub mod vm_space;
31
32#[cfg(ktest)]
33mod test;
34
35use core::ops::Range;
36
37pub use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, NR_ENTRIES, NR_LEVELS};
39
40#[doc(hidden)]
41pub use crate::specs::arch::paging_consts::PagingConsts;
42
43#[doc(hidden)]
45pub use kspace::paddr_to_vaddr;
46
47#[doc(hidden)]
49pub use page_table::largest_pages;
50
51pub type PagingLevel = u8;
53
54verus! {
55
56pub const MAX_USERSPACE_VADDR: usize = 0x0000_8000_0000_0000 - PAGE_SIZE;
68
69pub const KERNEL_VADDR_RANGE: Range<Vaddr> = 0xffff_8000_0000_0000..0xffff_ffff_ffff_0000;
74
75pub trait PagingConstsTrait: Clone + Debug + Send + Sync + 'static {
76 spec fn BASE_PAGE_SIZE_spec() -> usize;
77
78 proof fn lemma_BASE_PAGE_SIZE_properties()
79 ensures
80 0 < Self::BASE_PAGE_SIZE_spec(),
81 is_pow2(Self::BASE_PAGE_SIZE_spec() as int),
82 ;
83
84 #[verifier::when_used_as_spec(BASE_PAGE_SIZE_spec)]
87 fn BASE_PAGE_SIZE() -> (res: usize)
88 ensures
89 res == Self::BASE_PAGE_SIZE_spec(),
90 0 < res,
91 is_pow2(res as int),
92 ;
93
94 spec fn NR_LEVELS_spec() -> PagingLevel;
95
96 #[verifier::when_used_as_spec(NR_LEVELS_spec)]
102 fn NR_LEVELS() -> (res: PagingLevel)
103 ensures
104 res == Self::NR_LEVELS_spec(),
105 res > 0,
106 ;
107
108 proof fn lemma_NR_LEVELS_eq()
119 ensures
120 Self::NR_LEVELS_spec() as int == NR_LEVELS as int,
121 ;
122
123 spec fn HIGHEST_TRANSLATION_LEVEL_spec() -> PagingLevel;
124
125 #[verifier::when_used_as_spec(HIGHEST_TRANSLATION_LEVEL_spec)]
128 fn HIGHEST_TRANSLATION_LEVEL() -> (res: PagingLevel)
129 ensures
130 res == Self::HIGHEST_TRANSLATION_LEVEL_spec(),
131 ;
132
133 spec fn PTE_SIZE_spec() -> usize;
134
135 #[verifier::when_used_as_spec(PTE_SIZE_spec)]
137 fn PTE_SIZE() -> (res: usize)
138 ensures
139 res == Self::PTE_SIZE_spec(),
140 is_pow2(res as int),
141 0 < res <= Self::BASE_PAGE_SIZE(),
142 ;
143
144 proof fn lemma_PTE_SIZE_properties()
145 ensures
146 0 < Self::PTE_SIZE_spec() <= Self::BASE_PAGE_SIZE(),
147 is_pow2(Self::PTE_SIZE_spec() as int),
148 ;
149
150 spec fn ADDRESS_WIDTH_spec() -> usize;
151
152 #[verifier::when_used_as_spec(ADDRESS_WIDTH_spec)]
155 fn ADDRESS_WIDTH() -> (res: usize)
156 ensures
157 res == Self::ADDRESS_WIDTH_spec(),
158 ;
159
160 spec fn VA_SIGN_EXT_spec() -> bool;
172
173 #[verifier::when_used_as_spec(VA_SIGN_EXT_spec)]
174 fn VA_SIGN_EXT() -> (res: bool)
175 ensures
176 res == Self::VA_SIGN_EXT_spec(),
177 ;
178}
179
180#[verifier::inline]
181pub open spec fn nr_subpage_per_huge_spec<C: PagingConstsTrait>() -> usize {
182 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
183}
184
185#[inline(always)]
187#[verifier::when_used_as_spec(nr_subpage_per_huge_spec)]
188pub fn nr_subpage_per_huge<C: PagingConstsTrait>() -> (res: usize)
189 ensures
190 res == nr_subpage_per_huge_spec::<C>(),
191{
192 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
193}
194
195pub proof fn lemma_nr_subpage_per_huge_bounded<C: PagingConstsTrait>()
196 ensures
197 0 < nr_subpage_per_huge::<C>() <= C::BASE_PAGE_SIZE(),
198{
199 C::lemma_PTE_SIZE_properties();
200 broadcast use group_div_basics;
201
202 assert(C::PTE_SIZE() <= C::BASE_PAGE_SIZE());
203 assert(C::BASE_PAGE_SIZE() / C::PTE_SIZE() <= C::BASE_PAGE_SIZE());
204 assert(C::BASE_PAGE_SIZE() / C::PTE_SIZE() > 0) by {
205 lemma_div_non_zero(C::BASE_PAGE_SIZE() as int, C::PTE_SIZE() as int);
206 };
207}
208
209pub trait HasPaddr {
211 fn paddr(&self) -> Paddr;
213}
214
215pub const fn is_page_aligned(p: usize) -> bool {
217 (p & (PAGE_SIZE - 1)) == 0
218}
219
220}