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 type PagingLevel = u8;
18
19pub const MAX_NR_LEVELS: usize = 4;
21
22pub mod frame;
24pub mod io;
26pub mod kspace;
27pub(crate) mod page_prop;
28pub mod page_table;
29pub mod pod;
30pub mod tlb;
31pub mod vm_space;
32
33#[cfg(ktest)]
34mod test;
35
36use core::ops::Range;
37
38pub use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, NR_ENTRIES, NR_LEVELS};
40
41#[doc(hidden)]
42pub use crate::specs::arch::paging_consts::PagingConsts;
43
44#[doc(hidden)]
46pub use kspace::paddr_to_vaddr;
47
48#[doc(hidden)]
50pub use page_table::largest_pages;
51
52verus! {
53
54pub const MAX_USERSPACE_VADDR: usize = 0x0000_8000_0000_0000 - PAGE_SIZE;
66
67pub const KERNEL_VADDR_RANGE: Range<Vaddr> = 0xffff_8000_0000_0000..0xffff_ffff_ffff_0000;
72
73pub trait HasPaddr {
75 fn paddr(&self) -> Paddr;
77}
78
79pub const fn is_page_aligned(p: usize) -> bool {
81 (p & (PAGE_SIZE - 1)) == 0
82}
83
84#[allow(non_snake_case)]
85pub trait PagingConstsTrait: Debug + Sync {
86 spec fn BASE_PAGE_SIZE_spec() -> usize;
87
88 proof fn lemma_BASE_PAGE_SIZE_properties()
89 ensures
90 0 < Self::BASE_PAGE_SIZE_spec(),
91 is_pow2(Self::BASE_PAGE_SIZE_spec() as int),
92 ;
93
94 #[verifier::when_used_as_spec(BASE_PAGE_SIZE_spec)]
97 fn BASE_PAGE_SIZE() -> (res: usize)
98 ensures
99 res == Self::BASE_PAGE_SIZE_spec(),
100 0 < res,
101 is_pow2(res as int),
102 ;
103
104 spec fn NR_LEVELS_spec() -> PagingLevel;
105
106 #[verifier::when_used_as_spec(NR_LEVELS_spec)]
112 fn NR_LEVELS() -> (res: PagingLevel)
113 ensures
114 res == Self::NR_LEVELS_spec(),
115 res > 0,
116 ;
117
118 spec fn HIGHEST_TRANSLATION_LEVEL_spec() -> PagingLevel;
119
120 #[verifier::when_used_as_spec(HIGHEST_TRANSLATION_LEVEL_spec)]
123 fn HIGHEST_TRANSLATION_LEVEL() -> (res: PagingLevel)
124 ensures
125 res == Self::HIGHEST_TRANSLATION_LEVEL_spec(),
126 ;
127
128 spec fn PTE_SIZE_spec() -> usize;
129
130 #[verifier::when_used_as_spec(PTE_SIZE_spec)]
132 fn PTE_SIZE() -> (res: usize)
133 ensures
134 res == Self::PTE_SIZE_spec(),
135 is_pow2(res as int),
136 0 < res <= Self::BASE_PAGE_SIZE(),
137 ;
138
139 proof fn lemma_PTE_SIZE_properties()
140 ensures
141 0 < Self::PTE_SIZE_spec() <= Self::BASE_PAGE_SIZE(),
142 is_pow2(Self::PTE_SIZE_spec() as int),
143 ;
144
145 spec fn ADDRESS_WIDTH_spec() -> usize;
146
147 #[verifier::when_used_as_spec(ADDRESS_WIDTH_spec)]
150 fn ADDRESS_WIDTH() -> (res: usize)
151 ensures
152 res == Self::ADDRESS_WIDTH_spec(),
153 ;
154
155 spec fn VA_SIGN_EXT_spec() -> bool;
167
168 #[verifier::when_used_as_spec(VA_SIGN_EXT_spec)]
169 fn VA_SIGN_EXT() -> bool;
170}
171
172#[verifier::inline]
173pub open spec fn nr_subpage_per_huge_spec<C: PagingConstsTrait>() -> usize {
174 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
175}
176
177#[inline(always)]
179#[verifier::when_used_as_spec(nr_subpage_per_huge_spec)]
180pub fn nr_subpage_per_huge<C: PagingConstsTrait>() -> (res: usize)
181 ensures
182 res == nr_subpage_per_huge_spec::<C>(),
183{
184 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
185}
186
187pub proof fn lemma_nr_subpage_per_huge_bounded<C: PagingConstsTrait>()
188 ensures
189 0 < nr_subpage_per_huge::<C>() <= C::BASE_PAGE_SIZE(),
190{
191 C::lemma_PTE_SIZE_properties();
192 broadcast use group_div_basics;
193
194 assert(C::PTE_SIZE() <= C::BASE_PAGE_SIZE());
195 assert(C::BASE_PAGE_SIZE() / C::PTE_SIZE() <= C::BASE_PAGE_SIZE());
196 assert(C::BASE_PAGE_SIZE() / C::PTE_SIZE() > 0) by {
197 lemma_div_non_zero(C::BASE_PAGE_SIZE() as int, C::PTE_SIZE() as int);
198 };
199}
200
201}