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