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