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};
40pub use crate::specs::arch::paging_consts::PagingConsts;
41
42pub use kspace::paddr_to_vaddr;
44
45pub use page_table::largest_pages;
47
48verus! {
49
50pub const MAX_USERSPACE_VADDR: usize = 0x0000_8000_0000_0000 - PAGE_SIZE;
62
63pub const KERNEL_VADDR_RANGE: Range<Vaddr> = 0xffff_8000_0000_0000..0xffff_ffff_ffff_0000;
68
69pub trait HasPaddr {
71 fn paddr(&self) -> Paddr;
73}
74
75pub const fn is_page_aligned(p: usize) -> bool {
77 (p & (PAGE_SIZE - 1)) == 0
78}
79
80#[allow(non_snake_case)]
81pub trait PagingConstsTrait: Debug + Sync {
82 spec fn BASE_PAGE_SIZE_spec() -> usize;
83
84 proof fn lemma_BASE_PAGE_SIZE_properties()
85 ensures
86 0 < Self::BASE_PAGE_SIZE_spec(),
87 is_pow2(Self::BASE_PAGE_SIZE_spec() as int),
88 ;
89
90 #[verifier::when_used_as_spec(BASE_PAGE_SIZE_spec)]
93 fn BASE_PAGE_SIZE() -> (res: usize)
94 ensures
95 res == Self::BASE_PAGE_SIZE_spec(),
96 0 < res,
97 is_pow2(res as int),
98 ;
99
100 spec fn NR_LEVELS_spec() -> PagingLevel;
101
102 #[verifier::when_used_as_spec(NR_LEVELS_spec)]
108 fn NR_LEVELS() -> (res: PagingLevel)
109 ensures
110 res == Self::NR_LEVELS_spec(),
111 res > 0,
112 ;
113
114 spec fn HIGHEST_TRANSLATION_LEVEL_spec() -> PagingLevel;
115
116 #[verifier::when_used_as_spec(HIGHEST_TRANSLATION_LEVEL_spec)]
119 fn HIGHEST_TRANSLATION_LEVEL() -> (res: PagingLevel)
120 ensures
121 res == Self::HIGHEST_TRANSLATION_LEVEL_spec(),
122 ;
123
124 spec fn PTE_SIZE_spec() -> usize;
125
126 #[verifier::when_used_as_spec(PTE_SIZE_spec)]
128 fn PTE_SIZE() -> (res: usize)
129 ensures
130 res == Self::PTE_SIZE_spec(),
131 is_pow2(res as int),
132 0 < res <= Self::BASE_PAGE_SIZE(),
133 ;
134
135 proof fn lemma_PTE_SIZE_properties()
136 ensures
137 0 < Self::PTE_SIZE_spec() <= Self::BASE_PAGE_SIZE(),
138 is_pow2(Self::PTE_SIZE_spec() as int),
139 ;
140
141 spec fn ADDRESS_WIDTH_spec() -> usize;
142
143 #[verifier::when_used_as_spec(ADDRESS_WIDTH_spec)]
146 fn ADDRESS_WIDTH() -> (res: usize)
147 ensures
148 res == Self::ADDRESS_WIDTH_spec(),
149 ;
150
151 spec fn VA_SIGN_EXT_spec() -> bool;
163
164 #[verifier::when_used_as_spec(VA_SIGN_EXT_spec)]
165 fn VA_SIGN_EXT() -> bool;
166}
167
168#[verifier::inline]
169pub open spec fn nr_subpage_per_huge_spec<C: PagingConstsTrait>() -> usize {
170 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
171}
172
173#[inline(always)]
175#[verifier::when_used_as_spec(nr_subpage_per_huge_spec)]
176pub fn nr_subpage_per_huge<C: PagingConstsTrait>() -> (res: usize)
177 ensures
178 res == nr_subpage_per_huge_spec::<C>(),
179{
180 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
181}
182
183pub proof fn lemma_nr_subpage_per_huge_bounded<C: PagingConstsTrait>()
184 ensures
185 0 < nr_subpage_per_huge::<C>() <= C::BASE_PAGE_SIZE(),
186{
187 C::lemma_PTE_SIZE_properties();
188 broadcast use group_div_basics;
189
190 assert(C::PTE_SIZE() <= C::BASE_PAGE_SIZE());
191 assert(C::BASE_PAGE_SIZE() / C::PTE_SIZE() <= C::BASE_PAGE_SIZE());
192 assert(C::BASE_PAGE_SIZE() / C::PTE_SIZE() > 0) by {
193 lemma_div_non_zero(C::BASE_PAGE_SIZE() as int, C::PTE_SIZE() as int);
194 };
195}
196
197}