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(crate) mod dma;
23pub mod frame;
24pub mod io;
26pub use io::{
27 FallibleVmRead, FallibleVmWrite, Fallible, Infallible, VmIo, VmIoOnce, VmReader, VmWriter,
28};
29pub mod kspace;
30pub(crate) mod page_prop;
31pub mod page_table;
32pub mod pod;
33pub mod tlb;
34pub mod vm_space;
35
36#[cfg(ktest)]
37mod test;
38
39use core::ops::Range;
40
41pub use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, NR_ENTRIES, NR_LEVELS};
43
44#[doc(hidden)]
45pub use crate::specs::arch::paging_consts::PagingConsts;
46
47#[doc(hidden)]
49pub use kspace::paddr_to_vaddr;
50
51#[doc(hidden)]
53pub use page_table::largest_pages;
54
55verus! {
56
57pub const MAX_USERSPACE_VADDR: usize = 0x0000_8000_0000_0000 - PAGE_SIZE;
69
70pub const KERNEL_VADDR_RANGE: Range<Vaddr> = 0xffff_8000_0000_0000..0xffff_ffff_ffff_0000;
75
76pub trait HasPaddr {
78 fn paddr(&self) -> Paddr;
80}
81
82pub const fn is_page_aligned(p: usize) -> bool {
84 (p & (PAGE_SIZE - 1)) == 0
85}
86
87#[allow(non_snake_case)]
88pub trait PagingConstsTrait: Debug + Sync {
89 spec fn BASE_PAGE_SIZE_spec() -> usize;
90
91 proof fn lemma_BASE_PAGE_SIZE_properties()
92 ensures
93 0 < Self::BASE_PAGE_SIZE_spec(),
94 is_pow2(Self::BASE_PAGE_SIZE_spec() as int),
95 ;
96
97 #[verifier::when_used_as_spec(BASE_PAGE_SIZE_spec)]
100 fn BASE_PAGE_SIZE() -> (res: usize)
101 ensures
102 res == Self::BASE_PAGE_SIZE_spec(),
103 0 < res,
104 is_pow2(res as int),
105 ;
106
107 spec fn NR_LEVELS_spec() -> PagingLevel;
108
109 #[verifier::when_used_as_spec(NR_LEVELS_spec)]
115 fn NR_LEVELS() -> (res: PagingLevel)
116 ensures
117 res == Self::NR_LEVELS_spec(),
118 res > 0,
119 ;
120
121 spec fn HIGHEST_TRANSLATION_LEVEL_spec() -> PagingLevel;
122
123 #[verifier::when_used_as_spec(HIGHEST_TRANSLATION_LEVEL_spec)]
126 fn HIGHEST_TRANSLATION_LEVEL() -> (res: PagingLevel)
127 ensures
128 res == Self::HIGHEST_TRANSLATION_LEVEL_spec(),
129 ;
130
131 spec fn PTE_SIZE_spec() -> usize;
132
133 #[verifier::when_used_as_spec(PTE_SIZE_spec)]
135 fn PTE_SIZE() -> (res: usize)
136 ensures
137 res == Self::PTE_SIZE_spec(),
138 is_pow2(res as int),
139 0 < res <= Self::BASE_PAGE_SIZE(),
140 ;
141
142 proof fn lemma_PTE_SIZE_properties()
143 ensures
144 0 < Self::PTE_SIZE_spec() <= Self::BASE_PAGE_SIZE(),
145 is_pow2(Self::PTE_SIZE_spec() as int),
146 ;
147
148 spec fn ADDRESS_WIDTH_spec() -> usize;
149
150 #[verifier::when_used_as_spec(ADDRESS_WIDTH_spec)]
153 fn ADDRESS_WIDTH() -> (res: usize)
154 ensures
155 res == Self::ADDRESS_WIDTH_spec(),
156 ;
157
158 spec fn VA_SIGN_EXT_spec() -> bool;
170
171 #[verifier::when_used_as_spec(VA_SIGN_EXT_spec)]
172 fn VA_SIGN_EXT() -> bool;
173}
174
175#[verifier::inline]
176pub open spec fn nr_subpage_per_huge_spec<C: PagingConstsTrait>() -> usize {
177 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
178}
179
180#[inline(always)]
182#[verifier::when_used_as_spec(nr_subpage_per_huge_spec)]
183pub fn nr_subpage_per_huge<C: PagingConstsTrait>() -> (res: usize)
184 ensures
185 res == nr_subpage_per_huge_spec::<C>(),
186{
187 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
188}
189
190pub proof fn lemma_nr_subpage_per_huge_bounded<C: PagingConstsTrait>()
191 ensures
192 0 < nr_subpage_per_huge::<C>() <= C::BASE_PAGE_SIZE(),
193{
194 C::lemma_PTE_SIZE_properties();
195 broadcast use group_div_basics;
196
197 assert(C::PTE_SIZE() <= C::BASE_PAGE_SIZE());
198 assert(C::BASE_PAGE_SIZE() / C::PTE_SIZE() <= C::BASE_PAGE_SIZE());
199 assert(C::BASE_PAGE_SIZE() / C::PTE_SIZE() > 0) by {
200 lemma_div_non_zero(C::BASE_PAGE_SIZE() as int, C::PTE_SIZE() as int);
201 };
202}
203
204}