1use crate::specs::arch::CONST_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::*;
9use vstd_extra::extern_const;
10
11pub type Vaddr = usize;
13
14pub type Paddr = usize;
16
17pub type PagingLevel = u8;
19
20pub const MAX_NR_LEVELS: usize = 4;
22
23pub mod frame;
25pub mod io;
27pub mod kspace;
28pub(crate) mod page_prop;
29pub mod page_table;
30pub mod pod;
31pub mod tlb;
32pub mod vm_space;
33
34#[cfg(ktest)]
35mod test;
36
37use core::ops::Range;
38
39pub use crate::specs::arch::mm::{MAX_NR_PAGES, MAX_PADDR, NR_ENTRIES, NR_LEVELS, PAGE_SIZE};
41pub use crate::specs::arch::paging_consts::PagingConsts;
42
43pub use kspace::paddr_to_vaddr;
45
46pub use page_table::largest_pages;
48extern_const!(
49 pub MAX_USERSPACE_VADDR [MAX_USERSPACE_VADDR_SPEC, CONST_MAX_USERSPACE_VADDR]: usize =
61 0x0000_8000_0000_0000 - CONST_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
80verus! {
81
82#[allow(non_snake_case)]
83pub trait PagingConstsTrait: Debug + Sync {
84 spec fn BASE_PAGE_SIZE_spec() -> usize;
85
86 proof fn lemma_BASE_PAGE_SIZE_properties()
87 ensures
88 0 < Self::BASE_PAGE_SIZE_spec(),
89 is_pow2(Self::BASE_PAGE_SIZE_spec() as int),
90 ;
91
92 #[verifier::when_used_as_spec(BASE_PAGE_SIZE_spec)]
95 fn BASE_PAGE_SIZE() -> (res: usize)
96 ensures
97 res == Self::BASE_PAGE_SIZE_spec(),
98 0 < res,
99 is_pow2(res as int),
100 ;
101
102 spec fn NR_LEVELS_spec() -> PagingLevel;
103
104 #[verifier::when_used_as_spec(NR_LEVELS_spec)]
110 fn NR_LEVELS() -> (res: PagingLevel)
111 ensures
112 res == Self::NR_LEVELS_spec(),
113 res > 0,
114 ;
115
116 spec fn HIGHEST_TRANSLATION_LEVEL_spec() -> PagingLevel;
117
118 #[verifier::when_used_as_spec(HIGHEST_TRANSLATION_LEVEL_spec)]
121 fn HIGHEST_TRANSLATION_LEVEL() -> (res: PagingLevel)
122 ensures
123 res == Self::HIGHEST_TRANSLATION_LEVEL_spec(),
124 ;
125
126 spec fn PTE_SIZE_spec() -> usize;
127
128 #[verifier::when_used_as_spec(PTE_SIZE_spec)]
130 fn PTE_SIZE() -> (res: usize)
131 ensures
132 res == Self::PTE_SIZE_spec(),
133 is_pow2(res as int),
134 0 < res <= Self::BASE_PAGE_SIZE(),
135 ;
136
137 proof fn lemma_PTE_SIZE_properties()
138 ensures
139 0 < Self::PTE_SIZE_spec() <= Self::BASE_PAGE_SIZE(),
140 is_pow2(Self::PTE_SIZE_spec() as int),
141 ;
142
143 spec fn ADDRESS_WIDTH_spec() -> usize;
144
145 #[verifier::when_used_as_spec(ADDRESS_WIDTH_spec)]
148 fn ADDRESS_WIDTH() -> (res: usize)
149 ensures
150 res == Self::ADDRESS_WIDTH_spec(),
151 ;
152
153 spec fn VA_SIGN_EXT_spec() -> bool;
165
166 #[verifier::when_used_as_spec(VA_SIGN_EXT_spec)]
167 fn VA_SIGN_EXT() -> bool;
168}
169
170#[verifier::inline]
171pub open spec fn nr_subpage_per_huge_spec<C: PagingConstsTrait>() -> usize {
172 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
173}
174
175#[inline(always)]
177#[verifier::when_used_as_spec(nr_subpage_per_huge_spec)]
178pub fn nr_subpage_per_huge<C: PagingConstsTrait>() -> (res: usize)
179 ensures
180 res == nr_subpage_per_huge_spec::<C>(),
181{
182 C::BASE_PAGE_SIZE() / C::PTE_SIZE()
183}
184
185pub proof fn lemma_nr_subpage_per_huge_bounded<C: PagingConstsTrait>()
186 ensures
187 0 < nr_subpage_per_huge::<C>() <= C::BASE_PAGE_SIZE(),
188{
189 C::lemma_PTE_SIZE_properties();
190 broadcast use group_div_basics;
191
192 assert(C::PTE_SIZE() <= C::BASE_PAGE_SIZE());
193 assert(C::BASE_PAGE_SIZE() / C::PTE_SIZE() <= C::BASE_PAGE_SIZE());
194 assert(C::BASE_PAGE_SIZE() / C::PTE_SIZE() > 0) by {
195 lemma_div_non_zero(C::BASE_PAGE_SIZE() as int, C::PTE_SIZE() as int);
196 };
197}
198
199}