os/mm/address/
page_num.rs1use crate::config::PAGE_SIZE;
9use crate::mm::address::address::{Address, Paddr, Vaddr};
10use crate::mm::address::operations::{AlignOps, CalcOps, UsizeConvert};
11use core::ops::Range;
12
13pub trait PageNum:
19 CalcOps + UsizeConvert + Copy + Clone + PartialEq + PartialOrd + Eq + Ord
20{
21 type TAddress: Address + AlignOps; fn step(&mut self) {
26 self.step_by(1);
27 }
28
29 fn step_by(&mut self, offset: usize) {
34 *self = Self::from_usize(self.as_usize() + offset);
35 }
36
37 fn step_back(&mut self) {
39 self.step_back_by(1);
40 }
41
42 fn step_back_by(&mut self, offset: usize) {
47 *self = Self::from_usize(self.as_usize() - offset);
48 }
49
50 fn from_addr_floor(addr: Self::TAddress) -> Self {
58 Self::from_usize(addr.align_down_to_page().as_usize() / PAGE_SIZE)
60 }
61
62 fn from_addr_ceil(addr: Self::TAddress) -> Self {
71 Self::from_usize(addr.align_up_to_page().as_usize() / PAGE_SIZE)
73 }
74
75 fn start_addr(self) -> Self::TAddress {
80 Self::TAddress::from_usize(self.as_usize() * PAGE_SIZE)
81 }
82
83 fn end_addr(self) -> Self::TAddress {
88 Self::TAddress::from_usize((self.as_usize() + 1) * PAGE_SIZE)
89 }
90
91 fn diff(self, other: Self) -> isize {
99 self.as_usize() as isize - other.as_usize() as isize
100 }
101}
102
103#[macro_export]
117macro_rules! impl_page_num {
118 ($type:ty, $addr_type:ty) => {
119 impl $crate::mm::address::operations::UsizeConvert for $type {
121 fn as_usize(&self) -> usize {
122 self.0
123 }
124
125 fn from_usize(value: usize) -> Self {
126 Self(value)
127 }
128 }
129
130 $crate::impl_calc_ops!($type);
132
133 impl $crate::mm::address::page_num::PageNum for $type {
135 type TAddress = $addr_type;
136 }
137 };
138}
139
140#[repr(transparent)]
144#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
145pub struct Ppn(pub usize);
146impl_page_num!(Ppn, Paddr);
147
148#[repr(transparent)]
152#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
153pub struct Vpn(pub usize);
154impl_page_num!(Vpn, Vaddr);
155
156#[repr(C)]
160#[derive(Clone, Copy, Debug, PartialEq, Eq)]
161pub struct PageNumRange<T>
162where
163 T: PageNum,
164{
165 pub start: T,
167 pub end: T,
169}
170
171impl<T> PageNumRange<T>
172where
173 T: PageNum,
174{
175 pub fn new(start: T, end: T) -> Self {
177 Self { start, end }
178 }
179
180 pub fn from_range(range: Range<T>) -> Self {
182 Self {
183 start: range.start,
184 end: range.end,
185 }
186 }
187
188 pub fn from_start_len(start: T, len: usize) -> Self {
190 Self {
191 start,
192 end: T::from_usize(start.as_usize() + len),
193 }
194 }
195
196 pub fn start(&self) -> T {
198 self.start
199 }
200
201 pub fn end(&self) -> T {
203 self.end
204 }
205
206 pub fn len(&self) -> usize {
208 debug_assert!(self.end.as_usize() >= self.start.as_usize());
209 self.end.as_usize() - self.start.as_usize()
210 }
211
212 pub fn empty(&self) -> bool {
214 self.start == self.end
215 }
216
217 pub fn contains(&self, addr: T) -> bool {
219 addr >= self.start && addr < self.end
220 }
221
222 pub fn contains_range(&self, other: &Self) -> bool {
224 other.start >= self.start && other.end <= self.end
225 }
226
227 pub fn contains_in(&self, other: &Self) -> bool {
229 self.start >= other.start && self.end <= other.end
230 }
231
232 pub fn overlaps(&self, other: &Self) -> bool {
236 !(self.end <= other.start || self.start >= other.end)
237 }
238
239 pub fn iter(&self) -> PageNumRangeIterator<T> {
241 PageNumRangeIterator {
242 range: *self,
243 current: self.start,
244 }
245 }
246}
247
248impl<T> IntoIterator for PageNumRange<T>
249where
250 T: PageNum,
251{
252 type Item = T;
253 type IntoIter = PageNumRangeIterator<T>;
254
255 fn into_iter(self) -> Self::IntoIter {
256 self.iter()
257 }
258}
259
260pub struct PageNumRangeIterator<T>
264where
265 T: PageNum,
266{
267 range: PageNumRange<T>,
268 current: T,
269}
270
271impl<T> Iterator for PageNumRangeIterator<T>
272where
273 T: PageNum,
274{
275 type Item = T;
276
277 fn next(&mut self) -> Option<Self::Item> {
278 if self.current >= self.range.end {
279 return None;
280 }
281 let result = self.current;
282 self.current.step(); Some(result)
284 }
285}
286
287pub type PpnRange = PageNumRange<Ppn>;
289pub type VpnRange = PageNumRange<Vpn>;
291
292#[cfg(test)]
293mod page_num_tests {
294 use super::*;
295 use crate::mm::address::{Paddr, PageNum, Ppn, Vpn};
296 use crate::{kassert, test_case};
297
298 test_case!(test_pagenum_from_usize, {
300 let ppn = Ppn::from_usize(0x80000); kassert!(ppn.as_usize() == 0x80000);
303
304 let vpn = Vpn::from_usize(0x000F_FFFF_FC08_0000);
305 kassert!(vpn.as_usize() == 0x000F_FFFF_FC08_0000);
306 });
307
308 test_case!(test_pagenum_from_addr, {
310 let paddr = Paddr::from_usize(0x8000_1234);
311
312 let ppn_floor = Ppn::from_addr_floor(paddr);
314 kassert!(ppn_floor.as_usize() == 0x80001); let ppn_ceil = Ppn::from_addr_ceil(paddr);
318 kassert!(ppn_ceil.as_usize() == 0x80002);
319 });
320
321 test_case!(test_pagenum_to_addr, {
323 let ppn = Ppn::from_usize(0x80000);
324
325 let start = ppn.start_addr();
327 kassert!(start.as_usize() == 0x8000_0000);
328
329 let end = ppn.end_addr();
331 kassert!(end.as_usize() == 0x8000_1000);
332 });
333
334 test_case!(test_pagenum_step, {
336 let mut ppn = Ppn::from_usize(0x80000);
337
338 ppn.step();
339 kassert!(ppn.as_usize() == 0x80001);
340
341 ppn.step_back();
342 kassert!(ppn.as_usize() == 0x80000);
343 });
344
345 test_case!(test_pagenum_range, {
347 let start = Ppn::from_usize(0x80000);
348 let end = Ppn::from_usize(0x80003); let range = PpnRange::new(start, end);
350
351 kassert!(range.start().as_usize() == 0x80000);
352 kassert!(range.end().as_usize() == 0x80003);
353 kassert!(range.len() == 3); });
355
356 test_case!(test_pagenum_range_iter, {
358 let range = PpnRange::new(Ppn::from_usize(0x80000), Ppn::from_usize(0x80003));
359
360 let mut count = 0;
361 for ppn in range {
363 kassert!(ppn.as_usize() >= 0x80000);
364 kassert!(ppn.as_usize() < 0x80003);
365 count += 1;
366 }
367 kassert!(count == 3);
368 });
369
370 test_case!(test_floor_ceil_difference, {
372 let aligned = Paddr::from_usize(0x8000_0000);
374 let floor1 = Ppn::from_addr_floor(aligned);
375 let ceil1 = Ppn::from_addr_ceil(aligned);
376 kassert!(floor1.as_usize() == ceil1.as_usize());
377
378 let unaligned = Paddr::from_usize(0x8000_0001);
380 let floor2 = Ppn::from_addr_floor(unaligned); let ceil2 = Ppn::from_addr_ceil(unaligned); kassert!(ceil2.as_usize() == floor2.as_usize() + 1);
383 });
384
385 test_case!(test_pagenum_comparison, {
387 let ppn1 = Ppn::from_usize(0x80000);
388 let ppn2 = Ppn::from_usize(0x80000);
389 let ppn3 = Ppn::from_usize(0x80001);
390
391 kassert!(ppn1 == ppn2);
392 kassert!(ppn1 < ppn3);
393 kassert!(ppn3 > ppn1);
394 });
395}