1use super::PageTableEntry;
3use crate::config::{PAGE_SIZE, PAGE_SIZE_BITS};
4use core::fmt::{self, Debug, Formatter};
5
6const PA_WIDTH_SV39: usize = 56;
7const VA_WIDTH_SV39: usize = 39;
8const PPN_WIDTH_SV39: usize = PA_WIDTH_SV39 - PAGE_SIZE_BITS;
9const VPN_WIDTH_SV39: usize = VA_WIDTH_SV39 - PAGE_SIZE_BITS;
10
11#[repr(C)]
13#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
14pub struct PhysAddr(pub usize);
15
16#[repr(C)]
17#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
18pub struct VirtAddr(pub usize);
20
21#[repr(C)]
22#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
23pub struct PhysPageNum(pub usize);
25
26#[repr(C)]
27#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
28pub struct VirtPageNum(pub usize);
30
31impl Debug for VirtAddr {
34 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
35 f.write_fmt(format_args!("VA:{:#x}", self.0))
36 }
37}
38impl Debug for VirtPageNum {
39 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
40 f.write_fmt(format_args!("VPN:{:#x}", self.0))
41 }
42}
43impl Debug for PhysAddr {
44 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
45 f.write_fmt(format_args!("PA:{:#x}", self.0))
46 }
47}
48impl Debug for PhysPageNum {
49 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
50 f.write_fmt(format_args!("PPN:{:#x}", self.0))
51 }
52}
53
54impl From<usize> for PhysAddr {
59 fn from(v: usize) -> Self {
60 Self(v & ((1 << PA_WIDTH_SV39) - 1))
61 }
62}
63impl From<usize> for PhysPageNum {
64 fn from(v: usize) -> Self {
65 Self(v & ((1 << PPN_WIDTH_SV39) - 1))
66 }
67}
68impl From<usize> for VirtAddr {
69 fn from(v: usize) -> Self {
70 Self(v & ((1 << VA_WIDTH_SV39) - 1))
71 }
72}
73impl From<usize> for VirtPageNum {
74 fn from(v: usize) -> Self {
75 Self(v & ((1 << VPN_WIDTH_SV39) - 1))
76 }
77}
78impl From<PhysAddr> for usize {
79 fn from(v: PhysAddr) -> Self {
80 v.0
81 }
82}
83impl From<PhysPageNum> for usize {
84 fn from(v: PhysPageNum) -> Self {
85 v.0
86 }
87}
88impl From<VirtAddr> for usize {
89 fn from(v: VirtAddr) -> Self {
90 if v.0 >= (1 << (VA_WIDTH_SV39 - 1)) {
91 v.0 | (!((1 << VA_WIDTH_SV39) - 1))
92 } else {
93 v.0
94 }
95 }
96}
97impl From<VirtPageNum> for usize {
98 fn from(v: VirtPageNum) -> Self {
99 v.0
100 }
101}
102impl VirtAddr {
104 pub fn floor(&self) -> VirtPageNum {
106 VirtPageNum(self.0 / PAGE_SIZE)
107 }
108 pub fn ceil(&self) -> VirtPageNum {
110 if self.0 == 0 {
111 VirtPageNum(0)
112 } else {
113 VirtPageNum((self.0 - 1 + PAGE_SIZE) / PAGE_SIZE)
114 }
115 }
116 pub fn page_offset(&self) -> usize {
118 self.0 & (PAGE_SIZE - 1)
119 }
120 pub fn aligned(&self) -> bool {
122 self.page_offset() == 0
123 }
124}
125impl From<VirtAddr> for VirtPageNum {
126 fn from(v: VirtAddr) -> Self {
127 assert_eq!(v.page_offset(), 0);
128 v.floor()
129 }
130}
131impl From<VirtPageNum> for VirtAddr {
132 fn from(v: VirtPageNum) -> Self {
133 Self(v.0 << PAGE_SIZE_BITS)
134 }
135}
136impl PhysAddr {
137 pub fn floor(&self) -> PhysPageNum {
139 PhysPageNum(self.0 / PAGE_SIZE)
140 }
141 pub fn ceil(&self) -> PhysPageNum {
143 if self.0 == 0 {
144 PhysPageNum(0)
145 } else {
146 PhysPageNum((self.0 - 1 + PAGE_SIZE) / PAGE_SIZE)
147 }
148 }
149 pub fn page_offset(&self) -> usize {
151 self.0 & (PAGE_SIZE - 1)
152 }
153 pub fn aligned(&self) -> bool {
155 self.page_offset() == 0
156 }
157}
158impl From<PhysAddr> for PhysPageNum {
159 fn from(v: PhysAddr) -> Self {
160 assert_eq!(v.page_offset(), 0);
161 v.floor()
162 }
163}
164impl From<PhysPageNum> for PhysAddr {
165 fn from(v: PhysPageNum) -> Self {
166 Self(v.0 << PAGE_SIZE_BITS)
167 }
168}
169
170impl VirtPageNum {
171 pub fn indexes(&self) -> [usize; 3] {
173 let mut vpn = self.0;
174 let mut idx = [0usize; 3];
175 for i in (0..3).rev() {
176 idx[i] = vpn & 511;
177 vpn >>= 9;
178 }
179 idx
180 }
181}
182
183impl PhysAddr {
184 pub fn get_ref<T>(&self) -> &'static T {
186 unsafe { (self.0 as *const T).as_ref().unwrap() }
187 }
188 pub fn get_mut<T>(&self) -> &'static mut T {
190 unsafe { (self.0 as *mut T).as_mut().unwrap() }
191 }
192}
193impl PhysPageNum {
194 pub fn get_pte_array(&self) -> &'static mut [PageTableEntry] {
196 let pa: PhysAddr = (*self).into();
197 unsafe { core::slice::from_raw_parts_mut(pa.0 as *mut PageTableEntry, 512) }
198 }
199 pub fn get_bytes_array(&self) -> &'static mut [u8] {
201 let pa: PhysAddr = (*self).into();
202 unsafe { core::slice::from_raw_parts_mut(pa.0 as *mut u8, 4096) }
203 }
204 pub fn get_mut<T>(&self) -> &'static mut T {
206 let pa: PhysAddr = (*self).into();
207 pa.get_mut()
208 }
209}
210pub trait StepByOne {
212 fn step(&mut self);
214}
215impl StepByOne for VirtPageNum {
216 fn step(&mut self) {
217 self.0 += 1;
218 }
219}
220impl StepByOne for PhysPageNum {
221 fn step(&mut self) {
222 self.0 += 1;
223 }
224}
225
226#[derive(Copy, Clone)]
227pub struct SimpleRange<T>
229where
230 T: StepByOne + Copy + PartialEq + PartialOrd + Debug,
231{
232 l: T,
233 r: T,
234}
235impl<T> SimpleRange<T>
236where
237 T: StepByOne + Copy + PartialEq + PartialOrd + Debug,
238{
239 pub fn new(start: T, end: T) -> Self {
240 assert!(start <= end, "start {:?} > end {:?}!", start, end);
241 Self { l: start, r: end }
242 }
243 pub fn get_start(&self) -> T {
244 self.l
245 }
246 pub fn get_end(&self) -> T {
247 self.r
248 }
249}
250impl<T> IntoIterator for SimpleRange<T>
251where
252 T: StepByOne + Copy + PartialEq + PartialOrd + Debug,
253{
254 type Item = T;
255 type IntoIter = SimpleRangeIterator<T>;
256 fn into_iter(self) -> Self::IntoIter {
257 SimpleRangeIterator::new(self.l, self.r)
258 }
259}
260pub struct SimpleRangeIterator<T>
262where
263 T: StepByOne + Copy + PartialEq + PartialOrd + Debug,
264{
265 current: T,
266 end: T,
267}
268impl<T> SimpleRangeIterator<T>
269where
270 T: StepByOne + Copy + PartialEq + PartialOrd + Debug,
271{
272 pub fn new(l: T, r: T) -> Self {
273 Self { current: l, end: r }
274 }
275}
276impl<T> Iterator for SimpleRangeIterator<T>
277where
278 T: StepByOne + Copy + PartialEq + PartialOrd + Debug,
279{
280 type Item = T;
281 fn next(&mut self) -> Option<Self::Item> {
282 if self.current == self.end {
283 None
284 } else {
285 let t = self.current;
286 self.current.step();
287 Some(t)
288 }
289 }
290}
291pub type VPNRange = SimpleRange<VirtPageNum>;