memory_addresses/arch/
fallback.rs

1//! Physical and virtual addresses manipulation
2
3use crate::impl_address;
4use core::fmt;
5
6use align_address::Align;
7
8/// A virtual memory address.
9#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[repr(transparent)]
11pub struct VirtAddr(usize);
12
13impl_address!(VirtAddr, usize);
14
15/// A physical memory address.
16#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
17#[repr(transparent)]
18pub struct PhysAddr(usize);
19
20impl_address!(PhysAddr, usize);
21
22/// An invalid virtual address
23pub struct VirtAddrNotValid(pub usize);
24
25impl core::fmt::Debug for VirtAddrNotValid {
26    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27        f.debug_tuple("VirtAddrNotValid")
28            .field(&format_args!("{:#x}", self.0))
29            .finish()
30    }
31}
32
33impl VirtAddr {
34    /// Creates a new canonical virtual address.
35    #[inline]
36    pub const fn new(addr: usize) -> VirtAddr {
37        Self(addr)
38    }
39
40    /// Tries to create a new canonical virtual address.
41    #[inline]
42    pub const fn try_new(addr: usize) -> Result<VirtAddr, VirtAddrNotValid> {
43        Ok(Self(addr))
44    }
45
46    /// Creates a new virtual address truncating non-address parts.
47    #[inline]
48    pub const fn new_truncate(addr: usize) -> VirtAddr {
49        Self(addr)
50    }
51
52    /// Creates a virtual address from the given pointer
53    #[inline]
54    pub fn from_ptr<T: ?Sized>(ptr: *const T) -> Self {
55        Self::new(ptr as *const () as usize)
56    }
57
58    /// Converts the address to a raw pointer.
59    #[inline]
60    pub const fn as_ptr<T>(self) -> *const T {
61        self.0 as *const T
62    }
63
64    /// Converts the address to a mutable raw pointer.
65    #[inline]
66    pub const fn as_mut_ptr<T>(self) -> *mut T {
67        self.as_ptr::<T>() as *mut T
68    }
69}
70
71impl Align<usize> for VirtAddr {
72    #[inline]
73    fn align_down(self, align: usize) -> Self {
74        Self::new_truncate(self.0.align_down(align))
75    }
76
77    #[inline]
78    fn align_up(self, align: usize) -> Self {
79        Self::new_truncate(self.0.align_up(align))
80    }
81}
82
83/// A passed `usize` was not a valid physical address.
84///
85/// This means that bits 52 to 64 were not all null.
86///
87/// Contains the invalid address.
88pub struct PhysAddrNotValid(pub usize);
89
90impl core::fmt::Debug for PhysAddrNotValid {
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92        f.debug_tuple("PhysAddrNotValid")
93            .field(&format_args!("{:#x}", self.0))
94            .finish()
95    }
96}
97
98impl PhysAddr {
99    /// Creates a new physical address.
100    #[inline]
101    pub const fn new(addr: usize) -> Self {
102        Self(addr)
103    }
104
105    /// Creates a new physical address truncating non-address parts.
106    #[inline]
107    pub const fn new_truncate(addr: usize) -> PhysAddr {
108        PhysAddr(addr)
109    }
110
111    /// Tries to create a new physical address.
112    ///
113    /// Fails if any bits in the range 52 to 64 are set.
114    #[inline]
115    pub const fn try_new(addr: usize) -> Result<Self, PhysAddrNotValid> {
116        Ok(Self(addr))
117    }
118}
119
120impl Align<usize> for PhysAddr {
121    #[inline]
122    fn align_down(self, align: usize) -> Self {
123        Self::new(self.0.align_down(align))
124    }
125
126    #[inline]
127    fn align_up(self, align: usize) -> Self {
128        Self::new(self.0.align_up(align))
129    }
130}
131
132#[cfg(test)]
133mod tests {
134    use super::*;
135    use crate::{AddrRange, MemoryAddress};
136
137    #[test]
138    pub fn virtaddr_new_truncate() {
139        assert_eq!(VirtAddr::new_truncate(0), VirtAddr(0));
140        assert_eq!(VirtAddr::new_truncate(123), VirtAddr(123));
141    }
142
143    #[test]
144    fn test_from_ptr_array() {
145        let slice = &[1, 2, 3, 4, 5];
146        // Make sure that from_ptr(slice) is the address of the first element
147        assert_eq!(VirtAddr::from_ptr(slice), VirtAddr::from_ptr(&slice[0]));
148    }
149
150    #[test]
151    fn test_addr_range() {
152        let r = AddrRange::new(VirtAddr::new(0x0), VirtAddr::new(0x3)).unwrap();
153        assert!(r.contains(&VirtAddr::new(0x0)));
154        assert!(r.contains(&VirtAddr::new(0x1)));
155        assert!(!r.contains(&VirtAddr::new(0x3)));
156        let mut i = r.iter();
157        assert_eq!(i.next().unwrap(), VirtAddr::new(0x0));
158        assert_eq!(i.next().unwrap(), VirtAddr::new(0x1));
159        assert_eq!(i.next().unwrap(), VirtAddr::new(0x2));
160        assert!(i.next().is_none());
161
162        for (i, a) in r.iter().enumerate() {
163            assert_eq!(a.raw(), i);
164        }
165
166        let r = AddrRange::new(PhysAddr::new(0x2), PhysAddr::new(0x4)).unwrap();
167        let mut i = r.iter();
168        assert_eq!(i.next().unwrap(), PhysAddr::new(0x2));
169        assert_eq!(i.next().unwrap(), PhysAddr::new(0x3));
170        assert!(i.next().is_none());
171
172        assert_eq!(r.iter().map(|a| a.raw()).sum::<usize>(), 0x5);
173    }
174}