os/mm/
address.rs

1//! Implementation of physical and virtual address and page number.
2use super::PageTableEntry;
3use crate::config::{PAGE_SIZE, PAGE_SIZE_BITS};
4use core::fmt::{self, Debug, Formatter};
5/// physical address
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/// physical address
12#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
13pub struct PhysAddr(pub usize);
14/// virtual address
15#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
16pub struct VirtAddr(pub usize);
17/// physical page number
18#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
19pub struct PhysPageNum(pub usize);
20/// virtual page number
21#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
22pub struct VirtPageNum(pub usize);
23
24/// Debugging
25
26impl 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
47/// T: {PhysAddr, VirtAddr, PhysPageNum, VirtPageNum}
48/// T -> usize: T.0
49/// usize -> T: usize.into()
50
51impl 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}
95///
96impl VirtAddr {
97    ///`VirtAddr`->`VirtPageNum`
98    pub fn floor(&self) -> VirtPageNum {
99        VirtPageNum(self.0 / PAGE_SIZE)
100    }
101    ///`VirtAddr`->`VirtPageNum`
102    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    ///Get page offset
110    pub fn page_offset(&self) -> usize {
111        self.0 & (PAGE_SIZE - 1)
112    }
113    ///Check page aligned
114    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    ///`PhysAddr`->`PhysPageNum`
131    pub fn floor(&self) -> PhysPageNum {
132        PhysPageNum(self.0 / PAGE_SIZE)
133    }
134    ///`PhysAddr`->`PhysPageNum`
135    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    ///Get page offset
143    pub fn page_offset(&self) -> usize {
144        self.0 & (PAGE_SIZE - 1)
145    }
146    ///Check page aligned
147    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    ///Return VPN 3 level index
165    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    ///Get mutable reference to `PhysAddr` value
178    pub fn get_mut<T>(&self) -> &'static mut T {
179        unsafe { (self.0 as *mut T).as_mut().unwrap() }
180    }
181}
182impl PhysPageNum {
183    ///Get `PageTableEntry` on `PhysPageNum`
184    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    ///
189    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    ///
194    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)]
210/// a simple range structure for type T
211pub 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}
243/// iterator for the simple range structure
244pub 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}
274/// a simple range structure for virtual page number
275pub type VPNRange = SimpleRange<VirtPageNum>;