1use core::cmp::Ord;
2
3pub trait MemoryAddr:
13 Copy
15 + From<usize>
17 + Into<usize>
18 + Ord
20{
21 #[inline]
29 #[must_use = "this returns a new address, without modifying the original"]
30 fn align_down<U>(self, align: U) -> Self
31 where
32 U: Into<usize>,
33 {
34 Self::from(crate::align_down(self.into(), align.into()))
35 }
36
37 #[inline]
39 #[must_use = "this returns a new address, without modifying the original"]
40 fn align_up<U>(self, align: U) -> Self
41 where
42 U: Into<usize>,
43 {
44 Self::from(crate::align_up(self.into(), align.into()))
45 }
46
47 #[inline]
49 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
50 fn align_offset<U>(self, align: U) -> usize
51 where
52 U: Into<usize>,
53 {
54 crate::align_offset(self.into(), align.into())
55 }
56
57 #[inline]
59 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
60 fn is_aligned<U>(self, align: U) -> bool
61 where
62 U: Into<usize>,
63 {
64 crate::is_aligned(self.into(), align.into())
65 }
66
67 #[inline]
69 #[must_use = "this returns a new address, without modifying the original"]
70 fn align_down_4k(self) -> Self {
71 Self::from(crate::align_down(self.into(), crate::PAGE_SIZE_4K))
72 }
73
74 #[inline]
76 #[must_use = "this returns a new address, without modifying the original"]
77 fn align_up_4k(self) -> Self {
78 Self::from(crate::align_up(self.into(), crate::PAGE_SIZE_4K))
79 }
80
81 #[inline]
83 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
84 fn align_offset_4k(self) -> usize {
85 crate::align_offset(self.into(), crate::PAGE_SIZE_4K)
86 }
87
88 #[inline]
90 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
91 fn is_aligned_4k(self) -> bool {
92 crate::is_aligned(self.into(), crate::PAGE_SIZE_4K)
93 }
94
95 #[inline]
105 #[must_use = "this returns a new address, without modifying the original"]
106 fn offset(self, offset: isize) -> Self {
107 Self::from(usize::checked_add_signed(self.into(), offset).expect("overflow in `MemoryAddr::offset`"))
109 }
110
111 #[inline]
115 #[must_use = "this returns a new address, without modifying the original"]
116 fn wrapping_offset(self, offset: isize) -> Self {
117 Self::from(usize::wrapping_add_signed(self.into(), offset))
118 }
119
120 #[inline]
126 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
127 fn offset_from(self, base: Self) -> isize {
128 let result = usize::wrapping_sub(self.into(), base.into()) as isize;
129 if (result > 0) ^ (base < self) {
130 panic!("overflow in `MemoryAddr::offset_from`");
132 } else {
133 result
134 }
135 }
136
137 #[inline]
145 #[must_use = "this returns a new address, without modifying the original"]
146 fn add(self, rhs: usize) -> Self {
147 Self::from(usize::checked_add(self.into(), rhs).expect("overflow in `MemoryAddr::add`"))
148 }
149
150 #[inline]
154 #[must_use = "this returns a new address, without modifying the original"]
155 fn wrapping_add(self, rhs: usize) -> Self {
156 Self::from(usize::wrapping_add(self.into(), rhs))
157 }
158
159 #[inline]
164 #[must_use = "this returns a new address, without modifying the original"]
165 fn overflowing_add(self, rhs: usize) -> (Self, bool) {
166 let (result, overflow) = self.into().overflowing_add(rhs);
167 (Self::from(result), overflow)
168 }
169
170 #[inline]
174 #[must_use = "this returns a new address, without modifying the original"]
175 fn checked_add(self, rhs: usize) -> Option<Self> {
176 usize::checked_add(self.into(), rhs).map(Self::from)
177 }
178
179 #[inline]
187 #[must_use = "this returns a new address, without modifying the original"]
188 fn sub(self, rhs: usize) -> Self {
189 Self::from(usize::checked_sub(self.into(), rhs).expect("overflow in `MemoryAddr::sub`"))
190 }
191
192 #[inline]
196 #[must_use = "this returns a new address, without modifying the original"]
197 fn wrapping_sub(self, rhs: usize) -> Self {
198 Self::from(usize::wrapping_sub(self.into(), rhs))
199 }
200
201 #[inline]
206 #[must_use = "this returns a new address, without modifying the original"]
207 fn overflowing_sub(self, rhs: usize) -> (Self, bool) {
208 let (result, overflow) = self.into().overflowing_sub(rhs);
209 (Self::from(result), overflow)
210 }
211
212 #[inline]
216 #[must_use = "this returns a new address, without modifying the original"]
217 fn checked_sub(self, rhs: usize) -> Option<Self> {
218 usize::checked_sub(self.into(), rhs).map(Self::from)
219 }
220
221 #[inline]
227 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
228 fn sub_addr(self, rhs: Self) -> usize {
229 usize::checked_sub(self.into(), rhs.into()).expect("overflow in `MemoryAddr::sub_addr`")
230 }
231
232 #[inline]
236 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
237 fn wrapping_sub_addr(self, rhs: Self) -> usize {
238 usize::wrapping_sub(self.into(), rhs.into())
239 }
240
241 #[inline]
246 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
247 fn overflowing_sub_addr(self, rhs: Self) -> (usize, bool) {
248 usize::overflowing_sub(self.into(), rhs.into())
249 }
250
251 #[inline]
255 #[must_use = "this function has no side effects, so it can be removed if the return value is not used"]
256 fn checked_sub_addr(self, rhs: Self) -> Option<usize> {
257 usize::checked_sub(self.into(), rhs.into())
258 }
259}
260
261impl<T> MemoryAddr for T where T: Copy + From<usize> + Into<usize> + Ord {}
264
265#[macro_export]
303macro_rules! def_usize_addr {
304 (
305 $(#[$meta:meta])*
306 $vis:vis type $name:ident;
307
308 $($tt:tt)*
309 ) => {
310 #[repr(transparent)]
311 #[derive(Copy, Clone, Default, Ord, PartialOrd, Eq, PartialEq)]
312 $(#[$meta])*
313 pub struct $name(usize);
314
315 impl $name {
316 #[doc = concat!("Converts an `usize` to an [`", stringify!($name), "`].")]
317 #[inline]
318 pub const fn from_usize(addr: usize) -> Self {
319 Self(addr)
320 }
321
322 #[doc = concat!("Converts an [`", stringify!($name), "`] to an `usize`.")]
323 #[inline]
324 pub const fn as_usize(self) -> usize {
325 self.0
326 }
327 }
328
329 impl From<usize> for $name {
330 #[inline]
331 fn from(addr: usize) -> Self {
332 Self(addr)
333 }
334 }
335
336 impl From<$name> for usize {
337 #[inline]
338 fn from(addr: $name) -> usize {
339 addr.0
340 }
341 }
342
343 impl core::ops::Add<usize> for $name {
344 type Output = Self;
345 #[inline]
346 fn add(self, rhs: usize) -> Self {
347 Self(self.0 + rhs)
348 }
349 }
350
351 impl core::ops::AddAssign<usize> for $name {
352 #[inline]
353 fn add_assign(&mut self, rhs: usize) {
354 self.0 += rhs;
355 }
356 }
357
358 impl core::ops::Sub<usize> for $name {
359 type Output = Self;
360 #[inline]
361 fn sub(self, rhs: usize) -> Self {
362 Self(self.0 - rhs)
363 }
364 }
365
366 impl core::ops::SubAssign<usize> for $name {
367 #[inline]
368 fn sub_assign(&mut self, rhs: usize) {
369 self.0 -= rhs;
370 }
371 }
372
373 impl core::ops::Sub<$name> for $name {
374 type Output = usize;
375 #[inline]
376 fn sub(self, rhs: $name) -> usize {
377 self.0 - rhs.0
378 }
379 }
380
381 $crate::def_usize_addr!($($tt)*);
382 };
383 () => {};
384}
385
386#[macro_export]
421macro_rules! def_usize_addr_formatter {
422 (
423 $name:ident = $format:literal;
424
425 $($tt:tt)*
426 ) => {
427 impl core::fmt::Debug for $name {
428 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
429 f.write_fmt(format_args!($format, format_args!("{:#x}", self.0)))
430 }
431 }
432
433 impl core::fmt::LowerHex for $name {
434 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
435 f.write_fmt(format_args!($format, format_args!("{:#x}", self.0)))
436 }
437 }
438
439 impl core::fmt::UpperHex for $name {
440 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
441 f.write_fmt(format_args!($format, format_args!("{:#X}", self.0)))
442 }
443 }
444
445 $crate::def_usize_addr_formatter!($($tt)*);
446 };
447 () => {};
448}
449
450def_usize_addr! {
451 pub type PhysAddr;
453
454 pub type VirtAddr;
456}
457
458def_usize_addr_formatter! {
459 PhysAddr = "PA:{}";
460 VirtAddr = "VA:{}";
461}
462
463impl VirtAddr {
464 #[inline]
466 pub fn from_ptr_of<T>(ptr: *const T) -> Self {
467 Self(ptr as usize)
468 }
469
470 #[inline]
472 pub fn from_mut_ptr_of<T>(ptr: *mut T) -> Self {
473 Self(ptr as usize)
474 }
475
476 #[inline]
478 pub const fn as_ptr(self) -> *const u8 {
479 self.0 as *const u8
480 }
481
482 #[inline]
484 pub const fn as_ptr_of<T>(self) -> *const T {
485 self.0 as *const T
486 }
487
488 #[inline]
490 pub const fn as_mut_ptr(self) -> *mut u8 {
491 self.0 as *mut u8
492 }
493
494 #[inline]
497 pub const fn as_mut_ptr_of<T>(self) -> *mut T {
498 self.0 as *mut T
499 }
500}
501
502#[macro_export]
504macro_rules! pa {
505 ($addr:expr) => {
506 $crate::PhysAddr::from_usize($addr)
507 };
508}
509
510#[macro_export]
512macro_rules! va {
513 ($addr:expr) => {
514 $crate::VirtAddr::from_usize($addr)
515 };
516}
517
518#[cfg(test)]
519mod test {
520 use core::mem::size_of;
521
522 use super::*;
523
524 def_usize_addr! {
525 pub type ExampleAddr;
527 pub type AnotherAddr;
529 }
530
531 def_usize_addr_formatter! {
532 ExampleAddr = "EA:{}";
533 AnotherAddr = "AA:{}";
534 }
535
536 #[test]
537 fn test_addr() {
538 let addr = va!(0x2000);
539 assert!(addr.is_aligned_4k());
540 assert!(!addr.is_aligned(0x10000usize));
541 assert_eq!(addr.align_offset_4k(), 0);
542 assert_eq!(addr.align_down_4k(), va!(0x2000));
543 assert_eq!(addr.align_up_4k(), va!(0x2000));
544
545 let addr = va!(0x2fff);
546 assert!(!addr.is_aligned_4k());
547 assert_eq!(addr.align_offset_4k(), 0xfff);
548 assert_eq!(addr.align_down_4k(), va!(0x2000));
549 assert_eq!(addr.align_up_4k(), va!(0x3000));
550
551 let align = 0x100000;
552 let addr = va!(align * 5) + 0x2000;
553 assert!(addr.is_aligned_4k());
554 assert!(!addr.is_aligned(align));
555 assert_eq!(addr.align_offset(align), 0x2000);
556 assert_eq!(addr.align_down(align), va!(align * 5));
557 assert_eq!(addr.align_up(align), va!(align * 6));
558 }
559
560 #[test]
561 pub fn test_addr_convert_and_comparison() {
562 let example1 = ExampleAddr::from_usize(0x1234);
563 let example2 = ExampleAddr::from(0x5678);
564 let another1 = AnotherAddr::from_usize(0x9abc);
565 let another2 = AnotherAddr::from(0xdef0);
566
567 assert_eq!(example1.as_usize(), 0x1234);
568 assert_eq!(Into::<usize>::into(example2), 0x5678);
569 assert_eq!(Into::<usize>::into(another1), 0x9abc);
570 assert_eq!(another2.as_usize(), 0xdef0);
571
572 assert_eq!(example1, ExampleAddr::from(0x1234));
573 assert_eq!(example2, ExampleAddr::from_usize(0x5678));
574 assert_eq!(another1, AnotherAddr::from_usize(0x9abc));
575 assert_eq!(another2, AnotherAddr::from(0xdef0));
576
577 assert!(example1 < example2);
578 assert!(example1 <= example2);
579 assert!(example2 > example1);
580 assert!(example2 >= example1);
581 assert!(example1 != example2);
582 }
583
584 #[test]
585 pub fn test_addr_fmt() {
586 assert_eq!(format!("{:?}", ExampleAddr::from(0x1abc)), "EA:0x1abc");
587 assert_eq!(format!("{:x}", AnotherAddr::from(0x1abc)), "AA:0x1abc");
588 assert_eq!(format!("{:X}", ExampleAddr::from(0x1abc)), "EA:0x1ABC");
589 }
590
591 #[test]
592 pub fn test_alignment() {
593 let alignment = 0x1000usize;
594 let base = alignment * 2;
595 let offset = 0x123usize;
596 let addr = ExampleAddr::from_usize(base + offset);
597
598 assert_eq!(addr.align_down(alignment), ExampleAddr::from_usize(base));
599 assert_eq!(
600 addr.align_up(alignment),
601 ExampleAddr::from_usize(base + alignment)
602 );
603 assert_eq!(addr.align_offset(alignment), offset);
604 assert!(!addr.is_aligned(alignment));
605 assert!(ExampleAddr::from_usize(base).is_aligned(alignment));
606 assert_eq!(
607 ExampleAddr::from_usize(base).align_up(alignment),
608 ExampleAddr::from_usize(base)
609 );
610 }
611
612 #[test]
613 pub fn test_addr_arithmetic() {
614 let base = 0x1234usize;
615 let offset = 0x100usize;
616 let with_offset = base + offset;
617
618 let addr = ExampleAddr::from_usize(base);
619 let offset_addr = ExampleAddr::from_usize(with_offset);
620
621 assert_eq!(addr.offset(offset as isize), offset_addr);
622 assert_eq!(addr.wrapping_offset(offset as isize), offset_addr);
623 assert_eq!(offset_addr.offset_from(addr), offset as isize);
624 assert_eq!(addr.add(offset), offset_addr);
625 assert_eq!(addr.wrapping_add(offset), offset_addr);
626 assert_eq!(offset_addr.sub(offset), addr);
627 assert_eq!(offset_addr.wrapping_sub(offset), addr);
628 assert_eq!(offset_addr.sub_addr(addr), offset);
629 assert_eq!(offset_addr.wrapping_sub_addr(addr), offset);
630
631 assert_eq!(addr + offset, offset_addr);
632 assert_eq!(offset_addr - offset, addr);
633 assert_eq!(offset_addr - addr, offset);
634 }
635
636 #[test]
637 pub fn test_addr_wrapping_arithmetic() {
638 let base = usize::MAX - 0x100usize;
639 let offset = 0x200usize;
640 let with_offset = base.wrapping_add(offset);
641
642 let addr = ExampleAddr::from_usize(base);
643 let offset_addr = ExampleAddr::from_usize(with_offset);
644
645 assert_eq!(addr.wrapping_offset(offset as isize), offset_addr);
646 assert_eq!(offset_addr.wrapping_offset(-(offset as isize)), addr);
647 assert_eq!(addr.wrapping_add(offset), offset_addr);
648 assert_eq!(offset_addr.wrapping_sub(offset), addr);
649 assert_eq!(offset_addr.wrapping_sub_addr(addr), offset);
650 }
651
652 #[test]
653 pub fn test_addr_checked_arithmetic() {
654 let low_addr = ExampleAddr::from_usize(0x100usize);
655 let high_addr = ExampleAddr::from_usize(usize::MAX - 0x100usize);
656 let small_offset = 0x50usize;
657 let large_offset = 0x200usize;
658
659 assert_eq!(
660 low_addr.checked_sub(small_offset),
661 Some(low_addr.wrapping_sub(small_offset))
662 );
663 assert_eq!(low_addr.checked_sub(large_offset), None);
664 assert_eq!(
665 high_addr.checked_add(small_offset),
666 Some(high_addr.wrapping_add(small_offset))
667 );
668 assert_eq!(high_addr.checked_add(large_offset), None);
669
670 assert_eq!(
671 high_addr.checked_sub_addr(low_addr),
672 Some(usize::MAX - 0x200usize)
673 );
674 assert_eq!(low_addr.checked_sub_addr(high_addr), None);
675 }
676
677 #[test]
678 pub fn test_addr_overflowing_arithmetic() {
679 let low_addr = ExampleAddr::from_usize(0x100usize);
680 let high_addr = ExampleAddr::from_usize(usize::MAX - 0x100usize);
681 let small_offset = 0x50usize;
682 let large_offset = 0x200usize;
683
684 assert_eq!(
685 low_addr.overflowing_sub(small_offset),
686 (low_addr.wrapping_sub(small_offset), false)
687 );
688 assert_eq!(
689 low_addr.overflowing_sub(large_offset),
690 (low_addr.wrapping_sub(large_offset), true)
691 );
692 assert_eq!(
693 high_addr.overflowing_add(small_offset),
694 (high_addr.wrapping_add(small_offset), false)
695 );
696 assert_eq!(
697 high_addr.overflowing_add(large_offset),
698 (high_addr.wrapping_add(large_offset), true)
699 );
700 assert_eq!(
701 high_addr.overflowing_sub_addr(low_addr),
702 (high_addr.wrapping_sub_addr(low_addr), false)
703 );
704 assert_eq!(
705 low_addr.overflowing_sub_addr(high_addr),
706 (low_addr.wrapping_sub_addr(high_addr), true)
707 );
708 }
709
710 #[test]
711 #[should_panic]
712 pub fn test_addr_offset_overflow() {
713 let addr = ExampleAddr::from_usize(usize::MAX);
714 let _ = addr.offset(1);
715 }
716
717 #[test]
718 #[should_panic]
719 pub fn test_addr_offset_from_overflow() {
720 let addr = ExampleAddr::from_usize(usize::MAX);
721 let _ = addr.offset_from(ExampleAddr::from_usize(0));
722 }
723
724 #[test]
725 #[should_panic]
726 pub fn test_addr_offset_from_underflow() {
727 let addr = ExampleAddr::from_usize(0);
728 let _ = addr.offset_from(ExampleAddr::from_usize(usize::MAX));
729 }
730
731 #[test]
732 #[should_panic]
733 pub fn test_addr_add_overflow() {
734 let addr = ExampleAddr::from_usize(usize::MAX);
735 let _ = addr.add(1);
736 }
737
738 #[test]
739 #[should_panic]
740 pub fn test_addr_sub_underflow() {
741 let addr = ExampleAddr::from_usize(0);
742 let _ = addr.sub(1);
743 }
744
745 #[test]
746 #[should_panic]
747 pub fn test_addr_sub_addr_overflow() {
748 let addr = ExampleAddr::from_usize(0);
749 let _ = addr.sub_addr(ExampleAddr::from_usize(1));
750 }
751
752 #[test]
753 pub fn test_virt_addr_ptr() {
754 let a: [usize; 4] = [0x1234, 0x5678, 0x9abc, 0xdef0];
755
756 let va0 = VirtAddr::from_ptr_of(&a as *const usize);
757 let va1 = va0.add(size_of::<usize>());
758 let va2 = va1.add(size_of::<usize>());
759 let va3 = va2.add(size_of::<usize>());
760
761 let p0 = va0.as_ptr() as *const usize;
762 let p1 = va1.as_ptr_of::<usize>();
763 let p2 = va2.as_mut_ptr() as *mut usize;
764 let p3 = va3.as_mut_ptr_of::<usize>();
765
766 assert_eq!(va0, VirtAddr::from_ptr_of(p0));
768 assert_eq!(va1, VirtAddr::from_ptr_of(p1));
769 assert_eq!(va2, VirtAddr::from_mut_ptr_of(p2));
770 assert_eq!(va3, VirtAddr::from_mut_ptr_of(p3));
771
772 assert!(unsafe { *p0 } == a[0]);
774 assert!(unsafe { *p1 } == a[1]);
775 assert!(unsafe { *p2 } == a[2]);
776 assert!(unsafe { *p3 } == a[3]);
777
778 unsafe {
779 *p2 = 0xdeadbeef;
780 }
781 unsafe {
782 *p3 = 0xcafebabe;
783 }
784 assert_eq!(a[2], 0xdeadbeef);
785 assert_eq!(a[3], 0xcafebabe);
786 }
787}