Skip to main content

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, as_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, as_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 checked_align_up(self, align: usize) -> Option<Self> {
79        let addr = self.0.checked_align_up(align)?;
80        Some(Self::new_truncate(addr))
81    }
82}
83
84/// A passed `usize` was not a valid physical address.
85///
86/// This means that bits 52 to 64 were not all null.
87///
88/// Contains the invalid address.
89pub struct PhysAddrNotValid(pub usize);
90
91impl core::fmt::Debug for PhysAddrNotValid {
92    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
93        f.debug_tuple("PhysAddrNotValid")
94            .field(&format_args!("{:#x}", self.0))
95            .finish()
96    }
97}
98
99impl PhysAddr {
100    /// Creates a new physical address.
101    #[inline]
102    pub const fn new(addr: usize) -> Self {
103        Self(addr)
104    }
105
106    /// Creates a new physical address truncating non-address parts.
107    #[inline]
108    pub const fn new_truncate(addr: usize) -> PhysAddr {
109        PhysAddr(addr)
110    }
111
112    /// Tries to create a new physical address.
113    ///
114    /// Fails if any bits in the range 52 to 64 are set.
115    #[inline]
116    pub const fn try_new(addr: usize) -> Result<Self, PhysAddrNotValid> {
117        Ok(Self(addr))
118    }
119}
120
121impl Align<usize> for PhysAddr {
122    #[inline]
123    fn align_down(self, align: usize) -> Self {
124        Self::new(self.0.align_down(align))
125    }
126
127    #[inline]
128    fn checked_align_up(self, align: usize) -> Option<Self> {
129        let addr = self.0.checked_align_up(align)?;
130        let this = Self::try_new(addr).ok()?;
131        Some(this)
132    }
133}
134
135#[cfg(test)]
136mod tests {
137    use super::*;
138    use crate::{AddrRange, MemoryAddress};
139
140    #[test]
141    pub fn virtaddr_new_truncate() {
142        assert_eq!(VirtAddr::new_truncate(0), VirtAddr(0));
143        assert_eq!(VirtAddr::new_truncate(123), VirtAddr(123));
144    }
145
146    #[test]
147    fn test_from_ptr_array() {
148        let slice = &[1, 2, 3, 4, 5];
149        // Make sure that from_ptr(slice) is the address of the first element
150        assert_eq!(VirtAddr::from_ptr(slice), VirtAddr::from_ptr(&slice[0]));
151    }
152
153    #[test]
154    fn test_addr_range() {
155        let r = AddrRange::new(VirtAddr::new(0x0), VirtAddr::new(0x3)).unwrap();
156        assert!(r.contains(&VirtAddr::new(0x0)));
157        assert!(r.contains(&VirtAddr::new(0x1)));
158        assert!(!r.contains(&VirtAddr::new(0x3)));
159        let mut i = r.iter();
160        assert_eq!(i.next().unwrap(), VirtAddr::new(0x0));
161        assert_eq!(i.next().unwrap(), VirtAddr::new(0x1));
162        assert_eq!(i.next().unwrap(), VirtAddr::new(0x2));
163        assert!(i.next().is_none());
164
165        for (i, a) in r.iter().enumerate() {
166            assert_eq!(a.raw(), i);
167        }
168
169        let r = AddrRange::new(PhysAddr::new(0x2), PhysAddr::new(0x4)).unwrap();
170        let mut i = r.iter();
171        assert_eq!(i.next().unwrap(), PhysAddr::new(0x2));
172        assert_eq!(i.next().unwrap(), PhysAddr::new(0x3));
173        assert!(i.next().is_none());
174
175        assert_eq!(r.iter().map(|a| a.raw()).sum::<usize>(), 0x5);
176    }
177}