os/mm/
address.rs

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/// Definitions
11#[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
27/// Debugging
28
29impl 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
50/// T: {PhysAddr, VirtAddr, PhysPageNum, VirtPageNum}
51/// T -> usize: T.0
52/// usize -> T: usize.into()
53
54impl 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>;