Skip to main content

x86_64/
addr.rs

1//! Physical and virtual addresses manipulation
2
3use core::convert::TryFrom;
4use core::fmt;
5#[cfg(feature = "step_trait")]
6use core::iter::Step;
7use core::ops::{Add, AddAssign, Sub, SubAssign};
8#[cfg(feature = "memory_encryption")]
9use core::sync::atomic::Ordering;
10
11#[cfg(feature = "memory_encryption")]
12use crate::structures::mem_encrypt::ENC_BIT_MASK;
13use crate::structures::paging::page_table::PageTableLevel;
14use crate::structures::paging::{PageOffset, PageTableIndex};
15
16use bit_field::BitField;
17use dep_const_fn::const_fn;
18
19const ADDRESS_SPACE_SIZE: u64 = 0x1_0000_0000_0000;
20
21/// A canonical 64-bit virtual memory address.
22///
23/// This is a wrapper type around an `u64`, so it is always 8 bytes, even when compiled
24/// on non 64-bit systems. The
25/// [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) trait can be used for performing conversions
26/// between `u64` and `usize`.
27///
28/// On `x86_64`, only the 48 lower bits of a virtual address can be used. The top 16 bits need
29/// to be copies of bit 47, i.e. the most significant bit. Addresses that fulfil this criterion
30/// are called “canonical”. This type guarantees that it always represents a canonical address.
31#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
32#[repr(transparent)]
33pub struct VirtAddr(u64);
34
35/// A 64-bit physical memory address.
36///
37/// This is a wrapper type around an `u64`, so it is always 8 bytes, even when compiled
38/// on non 64-bit systems. The
39/// [`TryFrom`](https://doc.rust-lang.org/std/convert/trait.TryFrom.html) trait can be used for performing conversions
40/// between `u64` and `usize`.
41///
42/// On `x86_64`, only the 52 lower bits of a physical address can be used. The top 12 bits need
43/// to be zero. This type guarantees that it always represents a valid physical address.
44#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
45#[repr(transparent)]
46pub struct PhysAddr(u64);
47
48/// A passed `u64` was not a valid virtual address.
49///
50/// This means that bits 48 to 64 are not
51/// a valid sign extension and are not null either. So automatic sign extension would have
52/// overwritten possibly meaningful bits. This likely indicates a bug, for example an invalid
53/// address calculation.
54///
55/// Contains the invalid address.
56pub struct VirtAddrNotValid(pub u64);
57
58impl core::fmt::Debug for VirtAddrNotValid {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        f.debug_tuple("VirtAddrNotValid")
61            .field(&format_args!("{:#x}", self.0))
62            .finish()
63    }
64}
65
66impl VirtAddr {
67    /// Creates a new canonical virtual address.
68    ///
69    /// The provided address should already be canonical. If you want to check
70    /// whether an address is canonical, use [`try_new`](Self::try_new).
71    ///
72    /// ## Panics
73    ///
74    /// This function panics if the bits in the range 48 to 64 are invalid
75    /// (i.e. are not a proper sign extension of bit 47).
76    #[inline]
77    pub const fn new(addr: u64) -> VirtAddr {
78        // TODO: Replace with .ok().expect(msg) when that works on stable.
79        match Self::try_new(addr) {
80            Ok(v) => v,
81            Err(_) => panic!("virtual address must be sign extended in bits 48 to 64"),
82        }
83    }
84
85    /// Tries to create a new canonical virtual address.
86    ///
87    /// This function checks whether the given address is canonical
88    /// and returns an error otherwise. An address is canonical
89    /// if bits 48 to 64 are a correct sign
90    /// extension (i.e. copies of bit 47).
91    #[inline]
92    pub const fn try_new(addr: u64) -> Result<VirtAddr, VirtAddrNotValid> {
93        let v = Self::new_truncate(addr);
94        if v.0 == addr {
95            Ok(v)
96        } else {
97            Err(VirtAddrNotValid(addr))
98        }
99    }
100
101    /// Creates a new canonical virtual address, throwing out bits 48..64.
102    ///
103    /// This function performs sign extension of bit 47 to make the address
104    /// canonical, overwriting bits 48 to 64. If you want to check whether an
105    /// address is canonical, use [`new`](Self::new) or [`try_new`](Self::try_new).
106    #[inline]
107    pub const fn new_truncate(addr: u64) -> VirtAddr {
108        // By doing the right shift as a signed operation (on a i64), it will
109        // sign extend the value, repeating the leftmost bit.
110        VirtAddr(((addr << 16) as i64 >> 16) as u64)
111    }
112
113    /// Creates a new virtual address, without any checks.
114    ///
115    /// ## Safety
116    ///
117    /// You must make sure bits 48..64 are equal to bit 47. This is not checked.
118    #[inline]
119    pub const unsafe fn new_unsafe(addr: u64) -> VirtAddr {
120        VirtAddr(addr)
121    }
122
123    /// Creates a virtual address that points to `0`.
124    #[inline]
125    pub const fn zero() -> VirtAddr {
126        VirtAddr(0)
127    }
128
129    /// Converts the address to an `u64`.
130    #[inline]
131    pub const fn as_u64(self) -> u64 {
132        self.0
133    }
134
135    /// Creates a virtual address from the given pointer
136    #[cfg(target_pointer_width = "64")]
137    #[inline]
138    pub fn from_ptr<T: ?Sized>(ptr: *const T) -> Self {
139        Self::new(ptr as *const () as u64)
140    }
141
142    /// Converts the address to a raw pointer.
143    #[cfg(target_pointer_width = "64")]
144    #[inline]
145    pub const fn as_ptr<T>(self) -> *const T {
146        self.as_u64() as *const T
147    }
148
149    /// Converts the address to a mutable raw pointer.
150    #[cfg(target_pointer_width = "64")]
151    #[inline]
152    pub const fn as_mut_ptr<T>(self) -> *mut T {
153        self.as_ptr::<T>() as *mut T
154    }
155
156    /// Convenience method for checking if a virtual address is null.
157    #[inline]
158    pub const fn is_null(self) -> bool {
159        self.0 == 0
160    }
161
162    /// Aligns the virtual address upwards to the given alignment.
163    ///
164    /// See the `align_up` function for more information.
165    ///
166    /// # Panics
167    ///
168    /// This function panics if the resulting address is higher than
169    /// `0xffff_ffff_ffff_ffff`.
170    #[inline]
171    pub fn align_up<U>(self, align: U) -> Self
172    where
173        U: Into<u64>,
174    {
175        VirtAddr::new_truncate(align_up(self.0, align.into()))
176    }
177
178    /// Aligns the virtual address downwards to the given alignment.
179    ///
180    /// See the `align_down` function for more information.
181    #[inline]
182    pub fn align_down<U>(self, align: U) -> Self
183    where
184        U: Into<u64>,
185    {
186        self.align_down_u64(align.into())
187    }
188
189    /// Aligns the virtual address downwards to the given alignment.
190    ///
191    /// See the `align_down` function for more information.
192    #[inline]
193    pub(crate) const fn align_down_u64(self, align: u64) -> Self {
194        VirtAddr::new_truncate(align_down(self.0, align))
195    }
196
197    /// Checks whether the virtual address has the demanded alignment.
198    #[inline]
199    pub fn is_aligned<U>(self, align: U) -> bool
200    where
201        U: Into<u64>,
202    {
203        self.is_aligned_u64(align.into())
204    }
205
206    /// Checks whether the virtual address has the demanded alignment.
207    #[inline]
208    pub(crate) const fn is_aligned_u64(self, align: u64) -> bool {
209        self.align_down_u64(align).as_u64() == self.as_u64()
210    }
211
212    /// Returns the 12-bit page offset of this virtual address.
213    #[inline]
214    pub const fn page_offset(self) -> PageOffset {
215        PageOffset::new_truncate(self.0 as u16)
216    }
217
218    /// Returns the 9-bit level 1 page table index.
219    #[inline]
220    pub const fn p1_index(self) -> PageTableIndex {
221        PageTableIndex::new_truncate((self.0 >> 12) as u16)
222    }
223
224    /// Returns the 9-bit level 2 page table index.
225    #[inline]
226    pub const fn p2_index(self) -> PageTableIndex {
227        PageTableIndex::new_truncate((self.0 >> 12 >> 9) as u16)
228    }
229
230    /// Returns the 9-bit level 3 page table index.
231    #[inline]
232    pub const fn p3_index(self) -> PageTableIndex {
233        PageTableIndex::new_truncate((self.0 >> 12 >> 9 >> 9) as u16)
234    }
235
236    /// Returns the 9-bit level 4 page table index.
237    #[inline]
238    pub const fn p4_index(self) -> PageTableIndex {
239        PageTableIndex::new_truncate((self.0 >> 12 >> 9 >> 9 >> 9) as u16)
240    }
241
242    /// Returns the 9-bit level page table index.
243    #[inline]
244    pub const fn page_table_index(self, level: PageTableLevel) -> PageTableIndex {
245        PageTableIndex::new_truncate((self.0 >> 12 >> ((level as u8 - 1) * 9)) as u16)
246    }
247
248    // FIXME: Move this into the `Step` impl, once `Step` is stabilized.
249    #[cfg(feature = "step_trait")]
250    pub(crate) fn steps_between_impl(start: &Self, end: &Self) -> (usize, Option<usize>) {
251        if let Some(steps) = Self::steps_between_u64(start, end) {
252            let steps = usize::try_from(steps).ok();
253            (steps.unwrap_or(usize::MAX), steps)
254        } else {
255            (0, None)
256        }
257    }
258
259    /// An implementation of steps_between that returns u64. Note that this
260    /// function always returns the exact bound, so it doesn't need to return a
261    /// lower and upper bound like steps_between does.
262    pub(crate) fn steps_between_u64(start: &Self, end: &Self) -> Option<u64> {
263        let mut steps = end.0.checked_sub(start.0)?;
264
265        // Mask away extra bits that appear while jumping the gap.
266        steps &= 0xffff_ffff_ffff;
267
268        Some(steps)
269    }
270
271    // FIXME: Move this into the `Step` impl, once `Step` is stabilized.
272    #[inline]
273    pub(crate) fn forward_checked_impl(start: Self, count: usize) -> Option<Self> {
274        Self::forward_checked_u64(start, u64::try_from(count).ok()?)
275    }
276
277    /// An implementation of forward_checked that takes u64 instead of usize.
278    #[inline]
279    pub(crate) fn forward_checked_u64(start: Self, count: u64) -> Option<Self> {
280        if count > ADDRESS_SPACE_SIZE {
281            return None;
282        }
283
284        let mut addr = start.0.checked_add(count)?;
285
286        match addr.get_bits(47..) {
287            0x1 => {
288                // Jump the gap by sign extending the 47th bit.
289                addr.set_bits(47.., 0x1ffff);
290            }
291            0x2 => {
292                // Address overflow
293                return None;
294            }
295            _ => {}
296        }
297
298        Some(unsafe { Self::new_unsafe(addr) })
299    }
300
301    /// An implementation of backward_checked that takes u64 instead of usize.
302    #[cfg(feature = "step_trait")]
303    #[inline]
304    pub(crate) fn backward_checked_u64(start: Self, count: u64) -> Option<Self> {
305        if count > ADDRESS_SPACE_SIZE {
306            return None;
307        }
308
309        let mut addr = start.0.checked_sub(count)?;
310
311        match addr.get_bits(47..) {
312            0x1fffe => {
313                // Jump the gap by sign extending the 47th bit.
314                addr.set_bits(47.., 0);
315            }
316            0x1fffd => {
317                // Address underflow
318                return None;
319            }
320            _ => {}
321        }
322
323        Some(unsafe { Self::new_unsafe(addr) })
324    }
325}
326
327impl fmt::Debug for VirtAddr {
328    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
329        f.debug_tuple("VirtAddr")
330            .field(&format_args!("{:#x}", self.0))
331            .finish()
332    }
333}
334
335impl fmt::Binary for VirtAddr {
336    #[inline]
337    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338        fmt::Binary::fmt(&self.0, f)
339    }
340}
341
342impl fmt::LowerHex for VirtAddr {
343    #[inline]
344    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
345        fmt::LowerHex::fmt(&self.0, f)
346    }
347}
348
349impl fmt::Octal for VirtAddr {
350    #[inline]
351    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
352        fmt::Octal::fmt(&self.0, f)
353    }
354}
355
356impl fmt::UpperHex for VirtAddr {
357    #[inline]
358    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
359        fmt::UpperHex::fmt(&self.0, f)
360    }
361}
362
363impl fmt::Pointer for VirtAddr {
364    #[inline]
365    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
366        fmt::Pointer::fmt(&(self.0 as *const ()), f)
367    }
368}
369
370impl Add<u64> for VirtAddr {
371    type Output = Self;
372
373    #[cfg_attr(not(feature = "step_trait"), allow(rustdoc::broken_intra_doc_links))]
374    /// Add an offset to a virtual address.
375    ///
376    /// This function performs normal arithmetic addition and doesn't jump the
377    /// address gap. If you're looking for a successor operation that jumps the
378    /// address gap, use [`Step::forward`].
379    ///
380    /// # Panics
381    ///
382    /// This function will panic on overflow or if the result is not a
383    /// canonical address.
384    #[inline]
385    fn add(self, rhs: u64) -> Self::Output {
386        VirtAddr::try_new(
387            self.0
388                .checked_add(rhs)
389                .expect("attempt to add with overflow"),
390        )
391        .expect("attempt to add resulted in non-canonical virtual address")
392    }
393}
394
395impl AddAssign<u64> for VirtAddr {
396    #[cfg_attr(not(feature = "step_trait"), allow(rustdoc::broken_intra_doc_links))]
397    /// Add an offset to a virtual address.
398    ///
399    /// This function performs normal arithmetic addition and doesn't jump the
400    /// address gap. If you're looking for a successor operation that jumps the
401    /// address gap, use [`Step::forward`].
402    ///
403    /// # Panics
404    ///
405    /// This function will panic on overflow or if the result is not a
406    /// canonical address.
407    #[inline]
408    fn add_assign(&mut self, rhs: u64) {
409        *self = *self + rhs;
410    }
411}
412
413impl Sub<u64> for VirtAddr {
414    type Output = Self;
415
416    #[cfg_attr(not(feature = "step_trait"), allow(rustdoc::broken_intra_doc_links))]
417    /// Subtract an offset from a virtual address.
418    ///
419    /// This function performs normal arithmetic subtraction and doesn't jump
420    /// the address gap. If you're looking for a predecessor operation that
421    /// jumps the address gap, use [`Step::backward`].
422    ///
423    /// # Panics
424    ///
425    /// This function will panic on overflow or if the result is not a
426    /// canonical address.
427    #[inline]
428    fn sub(self, rhs: u64) -> Self::Output {
429        VirtAddr::try_new(
430            self.0
431                .checked_sub(rhs)
432                .expect("attempt to subtract with overflow"),
433        )
434        .expect("attempt to subtract resulted in non-canonical virtual address")
435    }
436}
437
438impl SubAssign<u64> for VirtAddr {
439    #[cfg_attr(not(feature = "step_trait"), allow(rustdoc::broken_intra_doc_links))]
440    /// Subtract an offset from a virtual address.
441    ///
442    /// This function performs normal arithmetic subtraction and doesn't jump
443    /// the address gap. If you're looking for a predecessor operation that
444    /// jumps the address gap, use [`Step::backward`].
445    ///
446    /// # Panics
447    ///
448    /// This function will panic on overflow or if the result is not a
449    /// canonical address.
450    #[inline]
451    fn sub_assign(&mut self, rhs: u64) {
452        *self = *self - rhs;
453    }
454}
455
456impl Sub<VirtAddr> for VirtAddr {
457    type Output = u64;
458
459    /// Returns the difference between two addresses.
460    ///
461    /// # Panics
462    ///
463    /// This function will panic on overflow.
464    #[inline]
465    fn sub(self, rhs: VirtAddr) -> Self::Output {
466        self.as_u64()
467            .checked_sub(rhs.as_u64())
468            .expect("attempt to subtract with overflow")
469    }
470}
471
472#[cfg(feature = "step_trait")]
473impl Step for VirtAddr {
474    #[inline]
475    fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
476        Self::steps_between_impl(start, end)
477    }
478
479    #[inline]
480    fn forward_checked(start: Self, count: usize) -> Option<Self> {
481        Self::forward_checked_impl(start, count)
482    }
483
484    #[inline]
485    fn backward_checked(start: Self, count: usize) -> Option<Self> {
486        Self::backward_checked_u64(start, u64::try_from(count).ok()?)
487    }
488
489    // Kani's bundled toolchain predates these methods being added to `Step`.
490    // Exclude them there so the crate still compiles under `cargo kani`.
491    // This can be removed once Kani upgrades its bundled toolchain to nightly-2026-07-10 or later.
492    #[cfg(not(kani))]
493    #[inline]
494    fn forward_overflowing(start: Self, count: usize) -> (Self, bool) {
495        match Self::forward_checked(start, count) {
496            Some(next) => (next, false),
497            None => (start, true),
498        }
499    }
500
501    // Kani's bundled toolchain predates these methods being added to `Step`.
502    // Exclude them there so the crate still compiles under `cargo kani`.
503    // This can be removed once Kani upgrades its bundled toolchain to nightly-2026-07-10 or later.
504    #[cfg(not(kani))]
505    #[inline]
506    fn backward_overflowing(start: Self, count: usize) -> (Self, bool) {
507        match Self::backward_checked(start, count) {
508            Some(next) => (next, false),
509            None => (start, true),
510        }
511    }
512}
513
514#[cfg(kani)]
515impl kani::Arbitrary for VirtAddr {
516    fn any() -> Self {
517        Self::new_truncate(kani::any())
518    }
519}
520
521/// A passed `u64` was not a valid physical address.
522///
523/// This means that bits 52 to 64 were not all null.
524///
525/// Contains the invalid address.
526pub struct PhysAddrNotValid(pub u64);
527
528impl core::fmt::Debug for PhysAddrNotValid {
529    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
530        f.debug_tuple("PhysAddrNotValid")
531            .field(&format_args!("{:#x}", self.0))
532            .finish()
533    }
534}
535
536impl PhysAddr {
537    /// Creates a new physical address.
538    ///
539    /// ## Panics
540    ///
541    /// This function panics if a bit in the range 52 to 64 is set.
542    ///
543    /// If the `memory_encryption` feature has been enabled and an encryption bit has been
544    /// configured, this also panics if the encryption bit is manually set in the address.
545    #[inline]
546    #[const_fn(cfg(not(feature = "memory_encryption")))]
547    pub const fn new(addr: u64) -> Self {
548        // TODO: Replace with .ok().expect(msg) when that works on stable.
549        match Self::try_new(addr) {
550            Ok(p) => p,
551            Err(_) => panic!("physical addresses must not have any bits in the range 52 to 64 set"),
552        }
553    }
554
555    /// Creates a new physical address, throwing bits 52..64 away.
556    #[cfg(not(feature = "memory_encryption"))]
557    #[inline]
558    pub const fn new_truncate(addr: u64) -> PhysAddr {
559        PhysAddr(addr % (1 << 52))
560    }
561
562    /// Creates a new physical address, throwing bits 52..64 and the encryption bit away.
563    #[cfg(feature = "memory_encryption")]
564    #[inline]
565    pub fn new_truncate(addr: u64) -> PhysAddr {
566        PhysAddr((addr % (1 << 52)) & !ENC_BIT_MASK.load(Ordering::Relaxed))
567    }
568
569    /// Creates a new physical address, without any checks.
570    ///
571    /// ## Safety
572    ///
573    /// You must make sure bits 52..64 are zero. This is not checked.
574    #[inline]
575    pub const unsafe fn new_unsafe(addr: u64) -> PhysAddr {
576        PhysAddr(addr)
577    }
578
579    /// Tries to create a new physical address.
580    ///
581    /// Fails if any bits in the range 52 to 64 are set.
582    /// If the `memory_encryption` feature has been enabled and an encryption bit has been
583    /// configured, this also fails if the encryption bit is manually set in the address.
584    #[inline]
585    #[const_fn(cfg(not(feature = "memory_encryption")))]
586    pub const fn try_new(addr: u64) -> Result<Self, PhysAddrNotValid> {
587        let p = Self::new_truncate(addr);
588        if p.0 == addr {
589            Ok(p)
590        } else {
591            Err(PhysAddrNotValid(addr))
592        }
593    }
594
595    /// Creates a physical address that points to `0`.
596    #[inline]
597    pub const fn zero() -> PhysAddr {
598        PhysAddr(0)
599    }
600
601    /// Converts the address to an `u64`.
602    #[inline]
603    pub const fn as_u64(self) -> u64 {
604        self.0
605    }
606
607    /// Convenience method for checking if a physical address is null.
608    #[inline]
609    pub const fn is_null(self) -> bool {
610        self.0 == 0
611    }
612
613    /// Aligns the physical address upwards to the given alignment.
614    ///
615    /// See the `align_up` function for more information.
616    ///
617    /// # Panics
618    ///
619    /// This function panics if the resulting address has a bit in the range 52
620    /// to 64 set.
621    #[inline]
622    pub fn align_up<U>(self, align: U) -> Self
623    where
624        U: Into<u64>,
625    {
626        PhysAddr::new(align_up(self.0, align.into()))
627    }
628
629    /// Aligns the physical address downwards to the given alignment.
630    ///
631    /// See the `align_down` function for more information.
632    #[inline]
633    pub fn align_down<U>(self, align: U) -> Self
634    where
635        U: Into<u64>,
636    {
637        self.align_down_u64(align.into())
638    }
639
640    /// Aligns the physical address downwards to the given alignment.
641    ///
642    /// See the `align_down` function for more information.
643    #[inline]
644    pub(crate) const fn align_down_u64(self, align: u64) -> Self {
645        PhysAddr(align_down(self.0, align))
646    }
647
648    /// Checks whether the physical address has the demanded alignment.
649    #[inline]
650    pub fn is_aligned<U>(self, align: U) -> bool
651    where
652        U: Into<u64>,
653    {
654        self.is_aligned_u64(align.into())
655    }
656
657    /// Checks whether the physical address has the demanded alignment.
658    #[inline]
659    pub(crate) const fn is_aligned_u64(self, align: u64) -> bool {
660        self.align_down_u64(align).as_u64() == self.as_u64()
661    }
662}
663
664impl fmt::Debug for PhysAddr {
665    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
666        f.debug_tuple("PhysAddr")
667            .field(&format_args!("{:#x}", self.0))
668            .finish()
669    }
670}
671
672impl fmt::Binary for PhysAddr {
673    #[inline]
674    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
675        fmt::Binary::fmt(&self.0, f)
676    }
677}
678
679impl fmt::LowerHex for PhysAddr {
680    #[inline]
681    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
682        fmt::LowerHex::fmt(&self.0, f)
683    }
684}
685
686impl fmt::Octal for PhysAddr {
687    #[inline]
688    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
689        fmt::Octal::fmt(&self.0, f)
690    }
691}
692
693impl fmt::UpperHex for PhysAddr {
694    #[inline]
695    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
696        fmt::UpperHex::fmt(&self.0, f)
697    }
698}
699
700impl fmt::Pointer for PhysAddr {
701    #[inline]
702    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
703        fmt::Pointer::fmt(&(self.0 as *const ()), f)
704    }
705}
706
707impl Add<u64> for PhysAddr {
708    type Output = Self;
709    #[inline]
710    fn add(self, rhs: u64) -> Self::Output {
711        PhysAddr::new(self.0.checked_add(rhs).unwrap())
712    }
713}
714
715impl AddAssign<u64> for PhysAddr {
716    #[inline]
717    fn add_assign(&mut self, rhs: u64) {
718        *self = *self + rhs;
719    }
720}
721
722impl Sub<u64> for PhysAddr {
723    type Output = Self;
724    #[inline]
725    fn sub(self, rhs: u64) -> Self::Output {
726        PhysAddr::new(self.0.checked_sub(rhs).unwrap())
727    }
728}
729
730impl SubAssign<u64> for PhysAddr {
731    #[inline]
732    fn sub_assign(&mut self, rhs: u64) {
733        *self = *self - rhs;
734    }
735}
736
737impl Sub<PhysAddr> for PhysAddr {
738    type Output = u64;
739    #[inline]
740    fn sub(self, rhs: PhysAddr) -> Self::Output {
741        self.as_u64().checked_sub(rhs.as_u64()).unwrap()
742    }
743}
744
745#[cfg(kani)]
746impl kani::Arbitrary for PhysAddr {
747    fn any() -> Self {
748        Self::new_truncate(kani::any())
749    }
750}
751
752/// Align address downwards.
753///
754/// Returns the greatest `x` with alignment `align` so that `x <= addr`.
755///
756/// Panics if the alignment is not a power of two.
757#[inline]
758pub const fn align_down(addr: u64, align: u64) -> u64 {
759    assert!(align.is_power_of_two(), "`align` must be a power of two");
760    addr & !(align - 1)
761}
762
763/// Align address upwards.
764///
765/// Returns the smallest `x` with alignment `align` so that `x >= addr`.
766///
767/// Panics if the alignment is not a power of two or if an overflow occurs.
768#[inline]
769pub const fn align_up(addr: u64, align: u64) -> u64 {
770    assert!(align.is_power_of_two(), "`align` must be a power of two");
771    let align_mask = align - 1;
772    if addr & align_mask == 0 {
773        addr // already aligned
774    } else {
775        // FIXME: Replace with .expect, once `Option::expect` is const.
776        if let Some(aligned) = (addr | align_mask).checked_add(1) {
777            aligned
778        } else {
779            panic!("attempt to add with overflow")
780        }
781    }
782}
783
784#[cfg(test)]
785mod tests {
786    use super::*;
787
788    #[test]
789    #[should_panic]
790    pub fn add_overflow_virtaddr() {
791        let _ = VirtAddr::new(0xffff_ffff_ffff_ffff) + 1;
792    }
793
794    #[test]
795    #[should_panic]
796    pub fn add_overflow_physaddr() {
797        let _ = PhysAddr::new(0x000f_ffff_ffff_ffff) + 0xffff_0000_0000_0000;
798    }
799
800    #[test]
801    #[should_panic]
802    pub fn sub_underflow_virtaddr() {
803        let _ = VirtAddr::new(0) - 1;
804    }
805
806    #[test]
807    #[should_panic]
808    pub fn sub_overflow_physaddr() {
809        let _ = PhysAddr::new(0) - 1;
810    }
811
812    #[test]
813    pub fn virtaddr_new_truncate() {
814        assert_eq!(VirtAddr::new_truncate(0), VirtAddr(0));
815        assert_eq!(VirtAddr::new_truncate(1 << 47), VirtAddr(0xfffff << 47));
816        assert_eq!(VirtAddr::new_truncate(123), VirtAddr(123));
817        assert_eq!(VirtAddr::new_truncate(123 << 47), VirtAddr(0xfffff << 47));
818    }
819
820    #[test]
821    #[cfg(feature = "step_trait")]
822    fn virtaddr_step_forward() {
823        assert_eq!(Step::forward(VirtAddr(0), 0), VirtAddr(0));
824        assert_eq!(Step::forward(VirtAddr(0), 1), VirtAddr(1));
825        assert_eq!(
826            Step::forward(VirtAddr(0x7fff_ffff_ffff), 1),
827            VirtAddr(0xffff_8000_0000_0000)
828        );
829        assert_eq!(
830            Step::forward(VirtAddr(0xffff_8000_0000_0000), 1),
831            VirtAddr(0xffff_8000_0000_0001)
832        );
833        assert_eq!(
834            Step::forward_checked(VirtAddr(0xffff_ffff_ffff_ffff), 1),
835            None
836        );
837        #[cfg(target_pointer_width = "64")]
838        assert_eq!(
839            Step::forward(VirtAddr(0x7fff_ffff_ffff), 0x1234_5678_9abd),
840            VirtAddr(0xffff_9234_5678_9abc)
841        );
842        #[cfg(target_pointer_width = "64")]
843        assert_eq!(
844            Step::forward(VirtAddr(0x7fff_ffff_ffff), 0x8000_0000_0000),
845            VirtAddr(0xffff_ffff_ffff_ffff)
846        );
847        #[cfg(target_pointer_width = "64")]
848        assert_eq!(
849            Step::forward(VirtAddr(0x7fff_ffff_ff00), 0x8000_0000_00ff),
850            VirtAddr(0xffff_ffff_ffff_ffff)
851        );
852        #[cfg(target_pointer_width = "64")]
853        assert_eq!(
854            Step::forward_checked(VirtAddr(0x7fff_ffff_ff00), 0x8000_0000_0100),
855            None
856        );
857        #[cfg(target_pointer_width = "64")]
858        assert_eq!(
859            Step::forward_checked(VirtAddr(0x7fff_ffff_ffff), 0x8000_0000_0001),
860            None
861        );
862    }
863
864    #[test]
865    #[cfg(feature = "step_trait")]
866    fn virtaddr_step_backward() {
867        assert_eq!(Step::backward(VirtAddr(0), 0), VirtAddr(0));
868        assert_eq!(Step::backward_checked(VirtAddr(0), 1), None);
869        assert_eq!(Step::backward(VirtAddr(1), 1), VirtAddr(0));
870        assert_eq!(
871            Step::backward(VirtAddr(0xffff_8000_0000_0000), 1),
872            VirtAddr(0x7fff_ffff_ffff)
873        );
874        assert_eq!(
875            Step::backward(VirtAddr(0xffff_8000_0000_0001), 1),
876            VirtAddr(0xffff_8000_0000_0000)
877        );
878        #[cfg(target_pointer_width = "64")]
879        assert_eq!(
880            Step::backward(VirtAddr(0xffff_9234_5678_9abc), 0x1234_5678_9abd),
881            VirtAddr(0x7fff_ffff_ffff)
882        );
883        #[cfg(target_pointer_width = "64")]
884        assert_eq!(
885            Step::backward(VirtAddr(0xffff_8000_0000_0000), 0x8000_0000_0000),
886            VirtAddr(0)
887        );
888        #[cfg(target_pointer_width = "64")]
889        assert_eq!(
890            Step::backward(VirtAddr(0xffff_8000_0000_0000), 0x7fff_ffff_ff01),
891            VirtAddr(0xff)
892        );
893        #[cfg(target_pointer_width = "64")]
894        assert_eq!(
895            Step::backward_checked(VirtAddr(0xffff_8000_0000_0000), 0x8000_0000_0001),
896            None
897        );
898    }
899
900    #[test]
901    #[cfg(feature = "step_trait")]
902    fn virtaddr_steps_between() {
903        assert_eq!(
904            Step::steps_between(&VirtAddr(0), &VirtAddr(0)),
905            (0, Some(0))
906        );
907        assert_eq!(
908            Step::steps_between(&VirtAddr(0), &VirtAddr(1)),
909            (1, Some(1))
910        );
911        assert_eq!(Step::steps_between(&VirtAddr(1), &VirtAddr(0)), (0, None));
912        assert_eq!(
913            Step::steps_between(
914                &VirtAddr(0x7fff_ffff_ffff),
915                &VirtAddr(0xffff_8000_0000_0000)
916            ),
917            (1, Some(1))
918        );
919        assert_eq!(
920            Step::steps_between(
921                &VirtAddr(0xffff_8000_0000_0000),
922                &VirtAddr(0x7fff_ffff_ffff)
923            ),
924            (0, None)
925        );
926        assert_eq!(
927            Step::steps_between(
928                &VirtAddr(0xffff_8000_0000_0000),
929                &VirtAddr(0xffff_8000_0000_0000)
930            ),
931            (0, Some(0))
932        );
933        assert_eq!(
934            Step::steps_between(
935                &VirtAddr(0xffff_8000_0000_0000),
936                &VirtAddr(0xffff_8000_0000_0001)
937            ),
938            (1, Some(1))
939        );
940        assert_eq!(
941            Step::steps_between(
942                &VirtAddr(0xffff_8000_0000_0001),
943                &VirtAddr(0xffff_8000_0000_0000)
944            ),
945            (0, None)
946        );
947        // Make sure that we handle `steps > u32::MAX` correctly on 32-bit
948        // targets. On 64-bit targets, `0x1_0000_0000` fits into `usize`, so we
949        // can return exact lower and upper bounds. On 32-bit targets,
950        // `0x1_0000_0000` doesn't fit into `usize`, so we only return an lower
951        // bound of `usize::MAX` and don't return an upper bound.
952        #[cfg(target_pointer_width = "64")]
953        assert_eq!(
954            Step::steps_between(&VirtAddr(0), &VirtAddr(0x1_0000_0000)),
955            (0x1_0000_0000, Some(0x1_0000_0000))
956        );
957        #[cfg(not(target_pointer_width = "64"))]
958        assert_eq!(
959            Step::steps_between(&VirtAddr(0), &VirtAddr(0x1_0000_0000)),
960            (usize::MAX, None)
961        );
962    }
963
964    #[test]
965    #[cfg(feature = "step_trait")]
966    fn virtaddr_step_overflowing() {
967        assert_eq!(
968            Step::forward_overflowing(VirtAddr(0x7fff_ffff_ffff), 1),
969            (VirtAddr(0xffff_8000_0000_0000), false)
970        );
971        assert_eq!(
972            Step::backward_overflowing(VirtAddr(0xffff_8000_0000_0000), 1),
973            (VirtAddr(0x7fff_ffff_ffff), false)
974        );
975        assert_eq!(
976            Step::forward_overflowing(VirtAddr(0), 0),
977            (VirtAddr(0), false)
978        );
979
980        assert!(Step::forward_overflowing(VirtAddr(0xffff_ffff_ffff_ffff), 1).1);
981        assert!(Step::backward_overflowing(VirtAddr(0), 1).1);
982    }
983
984    #[test]
985    pub fn test_align_up() {
986        // align 1
987        assert_eq!(align_up(0, 1), 0);
988        assert_eq!(align_up(1234, 1), 1234);
989        assert_eq!(align_up(0xffff_ffff_ffff_ffff, 1), 0xffff_ffff_ffff_ffff);
990        // align 2
991        assert_eq!(align_up(0, 2), 0);
992        assert_eq!(align_up(1233, 2), 1234);
993        assert_eq!(align_up(0xffff_ffff_ffff_fffe, 2), 0xffff_ffff_ffff_fffe);
994        // address 0
995        assert_eq!(align_up(0, 128), 0);
996        assert_eq!(align_up(0, 1), 0);
997        assert_eq!(align_up(0, 2), 0);
998        assert_eq!(align_up(0, 0x8000_0000_0000_0000), 0);
999    }
1000
1001    #[test]
1002    fn test_virt_addr_align_up() {
1003        // Make sure the 47th bit is extended.
1004        assert_eq!(
1005            VirtAddr::new(0x7fff_ffff_ffff).align_up(2u64),
1006            VirtAddr::new(0xffff_8000_0000_0000)
1007        );
1008    }
1009
1010    #[test]
1011    fn test_virt_addr_align_down() {
1012        // Make sure the 47th bit is extended.
1013        assert_eq!(
1014            VirtAddr::new(0xffff_8000_0000_0000).align_down(1u64 << 48),
1015            VirtAddr::new(0)
1016        );
1017    }
1018
1019    #[test]
1020    #[should_panic]
1021    fn test_virt_addr_align_up_overflow() {
1022        VirtAddr::new(0xffff_ffff_ffff_ffff).align_up(2u64);
1023    }
1024
1025    #[test]
1026    #[should_panic]
1027    fn test_phys_addr_align_up_overflow() {
1028        PhysAddr::new(0x000f_ffff_ffff_ffff).align_up(2u64);
1029    }
1030
1031    #[test]
1032    #[cfg(target_pointer_width = "64")]
1033    fn test_from_ptr_array() {
1034        let slice = &[1, 2, 3, 4, 5];
1035        // Make sure that from_ptr(slice) is the address of the first element
1036        assert_eq!(
1037            VirtAddr::from_ptr(slice.as_slice()),
1038            VirtAddr::from_ptr(&slice[0])
1039        );
1040    }
1041}
1042
1043#[cfg(kani)]
1044mod proofs {
1045    use super::*;
1046
1047    // The next two proof harnesses prove the correctness of the `forward`
1048    // implementation of VirtAddr.
1049
1050    // This harness proves that our implementation can correctly take 0 or 1
1051    // step starting from any address.
1052    #[kani::proof]
1053    fn forward_base_case() {
1054        let start = kani::any::<VirtAddr>();
1055        let start_raw = start.as_u64();
1056
1057        // Adding 0 to any address should always yield the same address.
1058        let same = Step::forward(start, 0);
1059        assert!(start == same);
1060
1061        // Manually calculate the expected address after stepping once.
1062        let expected = match start_raw {
1063            // Adding 1 to addresses in this range don't require gap jumps, so
1064            // we can just add 1.
1065            0x0000_0000_0000_0000..=0x0000_7fff_ffff_fffe => Some(start_raw + 1),
1066            // Adding 1 to this address jumps the gap.
1067            0x0000_7fff_ffff_ffff => Some(0xffff_8000_0000_0000),
1068            // The range of non-canonical addresses.
1069            0x0000_8000_0000_0000..=0xffff_7fff_ffff_ffff => unreachable!(),
1070            // Adding 1 to addresses in this range don't require gap jumps, so
1071            // we can just add 1.
1072            0xffff_8000_0000_0000..=0xffff_ffff_ffff_fffe => Some(start_raw + 1),
1073            // Adding 1 to this address causes an overflow.
1074            0xffff_ffff_ffff_ffff => None,
1075        };
1076        if let Some(expected) = expected {
1077            // Verify that `expected` is a valid address.
1078            assert!(VirtAddr::try_new(expected).is_ok());
1079        }
1080        // Verify `forward_checked`.
1081        let next = Step::forward_checked(start, 1);
1082        assert!(next.map(VirtAddr::as_u64) == expected);
1083    }
1084
1085    // This harness proves that the result of taking two small steps is the
1086    // same as taking one combined large step.
1087    #[kani::proof]
1088    fn forward_induction_step() {
1089        let start = kani::any::<VirtAddr>();
1090
1091        let count1: usize = kani::any();
1092        let count2: usize = kani::any();
1093        // If we can take two small steps...
1094        let Some(next1) = Step::forward_checked(start, count1) else {
1095            return;
1096        };
1097        let Some(next2) = Step::forward_checked(next1, count2) else {
1098            return;
1099        };
1100
1101        // ...then we can also take one combined large step.
1102        let count_both = count1 + count2;
1103        let next_both = Step::forward(start, count_both);
1104        assert!(next2 == next_both);
1105    }
1106
1107    // The next two proof harnesses prove the correctness of the `backward`
1108    // implementation of VirtAddr using the `forward` implementation which
1109    // we've already proven to be correct.
1110    // They do this by proving the symmetry between those two functions.
1111
1112    // This harness proves the correctness of the implementation of `backward`
1113    // for all inputs for which `forward_checked` succeeds.
1114    #[kani::proof]
1115    fn forward_implies_backward() {
1116        let start = kani::any::<VirtAddr>();
1117        let count: usize = kani::any();
1118
1119        // If `forward_checked` succeeds...
1120        let Some(end) = Step::forward_checked(start, count) else {
1121            return;
1122        };
1123
1124        // ...then `backward` succeeds as well.
1125        let start2 = Step::backward(end, count);
1126        assert!(start == start2);
1127    }
1128
1129    // This harness proves that for all inputs for which `backward_checked`
1130    // succeeds, `forward` succeeds as well.
1131    #[kani::proof]
1132    fn backward_implies_forward() {
1133        let end = kani::any::<VirtAddr>();
1134        let count: usize = kani::any();
1135
1136        // If `backward_checked` succeeds...
1137        let Some(start) = Step::backward_checked(end, count) else {
1138            return;
1139        };
1140
1141        // ...then `forward` succeeds as well.
1142        let end2 = Step::forward(start, count);
1143        assert!(end == end2);
1144    }
1145
1146    // The next two proof harnesses prove the correctness of the
1147    // `steps_between` implementation of VirtAddr using the `forward`
1148    // implementation which we've already proven to be correct.
1149    // They do this by proving the symmetry between those two functions.
1150
1151    // This harness proves the correctness of the implementation of
1152    // `steps_between` for all inputs for which `forward_checked` succeeds.
1153    #[kani::proof]
1154    fn forward_implies_steps_between() {
1155        let start = kani::any::<VirtAddr>();
1156        let count: usize = kani::any();
1157
1158        // If `forward_checked` succeeds...
1159        let Some(end) = Step::forward_checked(start, count) else {
1160            return;
1161        };
1162
1163        // ...then `steps_between` succeeds as well.
1164        assert!(Step::steps_between(&start, &end) == (count, Some(count)));
1165    }
1166
1167    // This harness proves that for all inputs for which `steps_between`
1168    // succeeds, `forward` succeeds as well.
1169    #[kani::proof]
1170    fn steps_between_implies_forward() {
1171        let start = kani::any::<VirtAddr>();
1172        let end = kani::any::<VirtAddr>();
1173
1174        // If `steps_between` succeeds...
1175        let Some(count) = Step::steps_between(&start, &end).1 else {
1176            return;
1177        };
1178
1179        // ...then `forward` succeeds as well.
1180        assert!(Step::forward(start, count) == end);
1181    }
1182}