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