1use vstd::{
4 arithmetic::{div_mod::group_div_basics, power2::*},
5 prelude::*,
6};
7use vstd_extra::external::ilog2::{
8 lemma_pow2_is_pow2, lemma_usize_ilog2_ordered, lemma_usize_is_pow2_is_ilog2_pow2,
9};
10
11use crate::specs::arch::*;
12
13pub type Vaddr = usize;
15
16pub type Paddr = usize;
18
19pub(crate) mod dma;
20pub mod frame;
21pub mod io;
23pub mod kspace;
24pub(crate) mod page_prop;
25pub mod page_table;
26pub mod tlb;
27pub mod vm_space;
28
29#[cfg(ktest)]
30mod test;
31
32use core::{fmt::Debug, ops::Range};
33
34pub use self::{
35 dma::{Daddr, DmaCoherent, HasDaddr},
36 frame::{
37 Frame,
38 allocator::FrameAllocOptions,
39 segment::{Segment, USegment},
40 unique::UniqueFrame,
41 untyped::{AnyUFrameMeta, UFrame, UntypedMem},
42 },
43 io::{
44 Fallible, FallibleVmRead, FallibleVmWrite, Infallible, PodOnce, VmIo, VmIoOnce, VmReader,
45 VmWriter,
46 },
47 page_prop::{CachePolicy, PageFlags, PageProperty},
48 vm_space::VmSpace,
49};
50pub(crate) use self::{
51 kspace::paddr_to_vaddr, page_prop::PrivilegedPageFlags, page_table::PageTable,
52};
53pub(crate) use crate::arch::mm::PagingConsts;
54
55pub(crate) use page_table::largest_pages;
57
58pub type PagingLevel = u8;
60
61verus! {
62
63pub trait PagingConstsTrait: Clone + Debug + Send + Sync + 'static {
66 spec fn BASE_PAGE_SIZE_spec() -> usize;
67
68 #[verifier::when_used_as_spec(BASE_PAGE_SIZE_spec)]
71 fn BASE_PAGE_SIZE() -> (res: usize)
72 returns
73 Self::BASE_PAGE_SIZE(),
74 ;
75
76 spec fn NR_LEVELS_spec() -> PagingLevel;
77
78 #[verifier::when_used_as_spec(NR_LEVELS_spec)]
84 fn NR_LEVELS() -> (res: PagingLevel)
85 returns
86 Self::NR_LEVELS(),
87 ;
88
89 spec fn HIGHEST_TRANSLATION_LEVEL_spec() -> PagingLevel;
90
91 #[verifier::when_used_as_spec(HIGHEST_TRANSLATION_LEVEL_spec)]
94 fn HIGHEST_TRANSLATION_LEVEL() -> PagingLevel
95 returns
96 Self::HIGHEST_TRANSLATION_LEVEL(),
97 ;
98
99 spec fn PTE_SIZE_spec() -> usize;
100
101 #[verifier::when_used_as_spec(PTE_SIZE_spec)]
103 fn PTE_SIZE() -> (res: usize)
104 returns
105 Self::PTE_SIZE(),
106 ;
107
108 spec fn ADDRESS_WIDTH_spec() -> usize;
109
110 #[verifier::when_used_as_spec(ADDRESS_WIDTH_spec)]
113 fn ADDRESS_WIDTH() -> (res: usize)
114 returns
115 Self::ADDRESS_WIDTH(),
116 ;
117
118 spec fn VA_SIGN_EXT_spec() -> bool;
119
120 #[verifier::when_used_as_spec(VA_SIGN_EXT_spec)]
132 fn VA_SIGN_EXT() -> bool
133 returns
134 Self::VA_SIGN_EXT(),
135 ;
136
137 proof fn lemma_paging_consts_requirements()
154 ensures
155 0 < Self::BASE_PAGE_SIZE(),
156 is_pow2(Self::BASE_PAGE_SIZE() as int),
157 Self::NR_LEVELS() > 0,
158 is_pow2(Self::PTE_SIZE() as int),
159 0 < Self::PTE_SIZE() <= Self::BASE_PAGE_SIZE(),
160 0 < Self::ADDRESS_WIDTH() < usize::BITS,
161 Self::BASE_PAGE_SIZE().ilog2() + (Self::BASE_PAGE_SIZE() / Self::PTE_SIZE()).ilog2()
162 * Self::NR_LEVELS() <= Self::ADDRESS_WIDTH(),
163 Self::PTE_SIZE() == core::mem::size_of::<usize>(),
164 Self::BASE_PAGE_SIZE() == PAGE_SIZE,
168 Self::NR_LEVELS() == NR_LEVELS,
169 Self::BASE_PAGE_SIZE() / Self::PTE_SIZE() == NR_ENTRIES,
170 ;
171
172 proof fn lemma_paging_consts_properties()
176 ensures
177 Self::BASE_PAGE_SIZE().ilog2() + (Self::BASE_PAGE_SIZE() / Self::PTE_SIZE()).ilog2() * (
180 Self::NR_LEVELS() - 1) <= Self::ADDRESS_WIDTH(),
181 0 < Self::BASE_PAGE_SIZE() / Self::PTE_SIZE() <= Self::BASE_PAGE_SIZE(),
182 is_pow2((Self::BASE_PAGE_SIZE() / Self::PTE_SIZE()) as int),
183 NR_ENTRIES * Self::PTE_SIZE() == PAGE_SIZE,
184 0 < Self::BASE_PAGE_SIZE(),
187 is_pow2(Self::BASE_PAGE_SIZE() as int),
188 Self::NR_LEVELS() > 0,
189 is_pow2(Self::PTE_SIZE() as int),
190 0 < Self::PTE_SIZE() <= Self::BASE_PAGE_SIZE(),
191 0 < Self::ADDRESS_WIDTH() < usize::BITS,
192 Self::BASE_PAGE_SIZE().ilog2() + (Self::BASE_PAGE_SIZE() / Self::PTE_SIZE()).ilog2()
193 * Self::NR_LEVELS() <= Self::ADDRESS_WIDTH(),
194 Self::PTE_SIZE() == core::mem::size_of::<usize>(),
195 Self::BASE_PAGE_SIZE() == PAGE_SIZE,
199 Self::NR_LEVELS() == NR_LEVELS,
200 Self::BASE_PAGE_SIZE() / Self::PTE_SIZE() == NR_ENTRIES,
201 {
202 Self::lemma_paging_consts_requirements();
203 broadcast use group_div_basics;
204
205 let page = Self::BASE_PAGE_SIZE();
206 let pte = Self::PTE_SIZE();
207 lemma_usize_is_pow2_is_ilog2_pow2(page);
208 lemma_usize_is_pow2_is_ilog2_pow2(pte);
209 lemma_usize_ilog2_ordered(pte, page);
210 lemma_pow2_subtracts(pte.ilog2() as nat, page.ilog2() as nat);
211 lemma_pow2_is_pow2((page.ilog2() - pte.ilog2()) as nat);
212 }
213}
214
215pub open spec fn page_size_spec<C: PagingConstsTrait>(level: PagingLevel) -> usize {
216 (C::BASE_PAGE_SIZE() * pow2((nr_subpage_per_huge::<C>().ilog2() * (level - 1)) as nat)) as usize
217}
218
219#[verifier::when_used_as_spec(page_size_spec)]
223pub fn page_size<C: PagingConstsTrait>(level: PagingLevel) -> (ret: usize)
224 requires
225 1 <= level <= C::NR_LEVELS() + 1,
226 ensures
227 ret == page_size_spec::<C>(level),
228 is_pow2(ret as int),
229 ret >= C::BASE_PAGE_SIZE(),
230{
231 proof {
232 let index_bits: usize = nr_subpage_per_huge::<C>().ilog2() as usize;
233 C::lemma_paging_consts_properties();
234 crate::arch::mm::lemma_nr_subpage_per_huge_eq_nr_entries();
235 vstd::layout::unsigned_int_max_values();
236 vstd::arithmetic::power2::lemma2_to64();
237 vstd::arithmetic::power2::lemma2_to64_rest();
238 vstd_extra::external::ilog2::lemma_usize_pow2_ilog2(9);
239 let level_index: usize = (level - 1) as usize;
240 let shift: usize = (index_bits * level_index) as usize;
241 let ghost shift_nat = shift as nat;
242 let ghost page_shift = 12nat + shift_nat;
243
244 vstd::arithmetic::power2::lemma_pow2_adds(12, shift_nat);
245 if page_shift < 48nat {
246 vstd::arithmetic::power2::lemma_pow2_strictly_increases(page_shift, 48nat);
247 }
248 vstd::bits::lemma_usize_shl_is_mul(PAGE_SIZE, shift);
249 vstd_extra::external::ilog2::lemma_usize_pow2_shl_is_pow2(PAGE_SIZE, shift);
250 }
251 C::BASE_PAGE_SIZE() << (nr_subpage_per_huge::<C>().ilog2() as usize * (level as usize - 1))
252}
253
254#[verifier::inline]
255pub open spec fn nr_subpage_per_huge_spec<C: PagingConstsTrait>() -> usize {
256 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
257}
258
259#[verifier::when_used_as_spec(nr_subpage_per_huge_spec)]
261pub fn nr_subpage_per_huge<C: PagingConstsTrait>() -> (res: usize)
262 ensures
263 res == nr_subpage_per_huge_spec::<C>(),
264{
265 proof {
266 C::lemma_paging_consts_properties();
267 }
268 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
269}
270
271pub const MAX_USERSPACE_VADDR: Vaddr = 0x0000_8000_0000_0000_usize - PAGE_SIZE;
282
283pub const KERNEL_VADDR_RANGE: Range<Vaddr> =
288 0xffff_8000_0000_0000_usize..0xffff_ffff_ffff_0000_usize;
289
290pub trait HasPaddr {
292 fn paddr(&self) -> Paddr;
294}
295
296pub const fn is_page_aligned(p: usize) -> bool {
298 (p & (PAGE_SIZE - 1)) == 0
299}
300
301}