1*ea60cea0SAlexandre Courbot // SPDX-License-Identifier: GPL-2.0 2*ea60cea0SAlexandre Courbot 3*ea60cea0SAlexandre Courbot //! Types and functions to work with pointers and addresses. 4*ea60cea0SAlexandre Courbot 5*ea60cea0SAlexandre Courbot use core::fmt::Debug; 6*ea60cea0SAlexandre Courbot use core::mem::align_of; 7*ea60cea0SAlexandre Courbot use core::num::NonZero; 8*ea60cea0SAlexandre Courbot 9*ea60cea0SAlexandre Courbot use crate::build_assert; 10*ea60cea0SAlexandre Courbot 11*ea60cea0SAlexandre Courbot /// Type representing an alignment, which is always a power of two. 12*ea60cea0SAlexandre Courbot /// 13*ea60cea0SAlexandre Courbot /// It is used to validate that a given value is a valid alignment, and to perform masking and 14*ea60cea0SAlexandre Courbot /// alignment operations. 15*ea60cea0SAlexandre Courbot /// 16*ea60cea0SAlexandre Courbot /// This is a temporary substitute for the [`Alignment`] nightly type from the standard library, 17*ea60cea0SAlexandre Courbot /// and to be eventually replaced by it. 18*ea60cea0SAlexandre Courbot /// 19*ea60cea0SAlexandre Courbot /// [`Alignment`]: https://github.com/rust-lang/rust/issues/102070 20*ea60cea0SAlexandre Courbot /// 21*ea60cea0SAlexandre Courbot /// # Invariants 22*ea60cea0SAlexandre Courbot /// 23*ea60cea0SAlexandre Courbot /// An alignment is always a power of two. 24*ea60cea0SAlexandre Courbot #[repr(transparent)] 25*ea60cea0SAlexandre Courbot #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] 26*ea60cea0SAlexandre Courbot pub struct Alignment(NonZero<usize>); 27*ea60cea0SAlexandre Courbot 28*ea60cea0SAlexandre Courbot impl Alignment { 29*ea60cea0SAlexandre Courbot /// Validates that `ALIGN` is a power of two at build-time, and returns an [`Alignment`] of the 30*ea60cea0SAlexandre Courbot /// same value. 31*ea60cea0SAlexandre Courbot /// 32*ea60cea0SAlexandre Courbot /// A build error is triggered if `ALIGN` is not a power of two. 33*ea60cea0SAlexandre Courbot /// 34*ea60cea0SAlexandre Courbot /// # Examples 35*ea60cea0SAlexandre Courbot /// 36*ea60cea0SAlexandre Courbot /// ``` 37*ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment; 38*ea60cea0SAlexandre Courbot /// 39*ea60cea0SAlexandre Courbot /// let v = Alignment::new::<16>(); 40*ea60cea0SAlexandre Courbot /// assert_eq!(v.as_usize(), 16); 41*ea60cea0SAlexandre Courbot /// ``` 42*ea60cea0SAlexandre Courbot #[inline(always)] 43*ea60cea0SAlexandre Courbot pub const fn new<const ALIGN: usize>() -> Self { 44*ea60cea0SAlexandre Courbot build_assert!( 45*ea60cea0SAlexandre Courbot ALIGN.is_power_of_two(), 46*ea60cea0SAlexandre Courbot "Provided alignment is not a power of two." 47*ea60cea0SAlexandre Courbot ); 48*ea60cea0SAlexandre Courbot 49*ea60cea0SAlexandre Courbot // INVARIANT: `align` is a power of two. 50*ea60cea0SAlexandre Courbot // SAFETY: `align` is a power of two, and thus non-zero. 51*ea60cea0SAlexandre Courbot Self(unsafe { NonZero::new_unchecked(ALIGN) }) 52*ea60cea0SAlexandre Courbot } 53*ea60cea0SAlexandre Courbot 54*ea60cea0SAlexandre Courbot /// Validates that `align` is a power of two at runtime, and returns an 55*ea60cea0SAlexandre Courbot /// [`Alignment`] of the same value. 56*ea60cea0SAlexandre Courbot /// 57*ea60cea0SAlexandre Courbot /// Returns [`None`] if `align` is not a power of two. 58*ea60cea0SAlexandre Courbot /// 59*ea60cea0SAlexandre Courbot /// # Examples 60*ea60cea0SAlexandre Courbot /// 61*ea60cea0SAlexandre Courbot /// ``` 62*ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment; 63*ea60cea0SAlexandre Courbot /// 64*ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new_checked(16), Some(Alignment::new::<16>())); 65*ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new_checked(15), None); 66*ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new_checked(1), Some(Alignment::new::<1>())); 67*ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new_checked(0), None); 68*ea60cea0SAlexandre Courbot /// ``` 69*ea60cea0SAlexandre Courbot #[inline(always)] 70*ea60cea0SAlexandre Courbot pub const fn new_checked(align: usize) -> Option<Self> { 71*ea60cea0SAlexandre Courbot if align.is_power_of_two() { 72*ea60cea0SAlexandre Courbot // INVARIANT: `align` is a power of two. 73*ea60cea0SAlexandre Courbot // SAFETY: `align` is a power of two, and thus non-zero. 74*ea60cea0SAlexandre Courbot Some(Self(unsafe { NonZero::new_unchecked(align) })) 75*ea60cea0SAlexandre Courbot } else { 76*ea60cea0SAlexandre Courbot None 77*ea60cea0SAlexandre Courbot } 78*ea60cea0SAlexandre Courbot } 79*ea60cea0SAlexandre Courbot 80*ea60cea0SAlexandre Courbot /// Returns the alignment of `T`. 81*ea60cea0SAlexandre Courbot /// 82*ea60cea0SAlexandre Courbot /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`]. 83*ea60cea0SAlexandre Courbot #[inline(always)] 84*ea60cea0SAlexandre Courbot pub const fn of<T>() -> Self { 85*ea60cea0SAlexandre Courbot #![allow(clippy::incompatible_msrv)] 86*ea60cea0SAlexandre Courbot // This cannot panic since alignments are always powers of two. 87*ea60cea0SAlexandre Courbot // 88*ea60cea0SAlexandre Courbot // We unfortunately cannot use `new` as it would require the `generic_const_exprs` feature. 89*ea60cea0SAlexandre Courbot const { Alignment::new_checked(align_of::<T>()).unwrap() } 90*ea60cea0SAlexandre Courbot } 91*ea60cea0SAlexandre Courbot 92*ea60cea0SAlexandre Courbot /// Returns this alignment as a [`usize`]. 93*ea60cea0SAlexandre Courbot /// 94*ea60cea0SAlexandre Courbot /// It is guaranteed to be a power of two. 95*ea60cea0SAlexandre Courbot /// 96*ea60cea0SAlexandre Courbot /// # Examples 97*ea60cea0SAlexandre Courbot /// 98*ea60cea0SAlexandre Courbot /// ``` 99*ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment; 100*ea60cea0SAlexandre Courbot /// 101*ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new::<16>().as_usize(), 16); 102*ea60cea0SAlexandre Courbot /// ``` 103*ea60cea0SAlexandre Courbot #[inline(always)] 104*ea60cea0SAlexandre Courbot pub const fn as_usize(self) -> usize { 105*ea60cea0SAlexandre Courbot self.as_nonzero().get() 106*ea60cea0SAlexandre Courbot } 107*ea60cea0SAlexandre Courbot 108*ea60cea0SAlexandre Courbot /// Returns this alignment as a [`NonZero`]. 109*ea60cea0SAlexandre Courbot /// 110*ea60cea0SAlexandre Courbot /// It is guaranteed to be a power of two. 111*ea60cea0SAlexandre Courbot /// 112*ea60cea0SAlexandre Courbot /// # Examples 113*ea60cea0SAlexandre Courbot /// 114*ea60cea0SAlexandre Courbot /// ``` 115*ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment; 116*ea60cea0SAlexandre Courbot /// 117*ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new::<16>().as_nonzero().get(), 16); 118*ea60cea0SAlexandre Courbot /// ``` 119*ea60cea0SAlexandre Courbot #[inline(always)] 120*ea60cea0SAlexandre Courbot pub const fn as_nonzero(self) -> NonZero<usize> { 121*ea60cea0SAlexandre Courbot // Allow the compiler to know that the value is indeed a power of two. This can help 122*ea60cea0SAlexandre Courbot // optimize some operations down the line, like e.g. replacing divisions by bit shifts. 123*ea60cea0SAlexandre Courbot if !self.0.is_power_of_two() { 124*ea60cea0SAlexandre Courbot // SAFETY: Per the invariants, `self.0` is always a power of two so this block will 125*ea60cea0SAlexandre Courbot // never be reached. 126*ea60cea0SAlexandre Courbot unsafe { core::hint::unreachable_unchecked() } 127*ea60cea0SAlexandre Courbot } 128*ea60cea0SAlexandre Courbot self.0 129*ea60cea0SAlexandre Courbot } 130*ea60cea0SAlexandre Courbot 131*ea60cea0SAlexandre Courbot /// Returns the base-2 logarithm of the alignment. 132*ea60cea0SAlexandre Courbot /// 133*ea60cea0SAlexandre Courbot /// # Examples 134*ea60cea0SAlexandre Courbot /// 135*ea60cea0SAlexandre Courbot /// ``` 136*ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment; 137*ea60cea0SAlexandre Courbot /// 138*ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::of::<u8>().log2(), 0); 139*ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new::<16>().log2(), 4); 140*ea60cea0SAlexandre Courbot /// ``` 141*ea60cea0SAlexandre Courbot #[inline(always)] 142*ea60cea0SAlexandre Courbot pub const fn log2(self) -> u32 { 143*ea60cea0SAlexandre Courbot self.0.ilog2() 144*ea60cea0SAlexandre Courbot } 145*ea60cea0SAlexandre Courbot 146*ea60cea0SAlexandre Courbot /// Returns the mask for this alignment. 147*ea60cea0SAlexandre Courbot /// 148*ea60cea0SAlexandre Courbot /// This is equivalent to `!(self.as_usize() - 1)`. 149*ea60cea0SAlexandre Courbot /// 150*ea60cea0SAlexandre Courbot /// # Examples 151*ea60cea0SAlexandre Courbot /// 152*ea60cea0SAlexandre Courbot /// ``` 153*ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment; 154*ea60cea0SAlexandre Courbot /// 155*ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new::<0x10>().mask(), !0xf); 156*ea60cea0SAlexandre Courbot /// ``` 157*ea60cea0SAlexandre Courbot #[inline(always)] 158*ea60cea0SAlexandre Courbot pub const fn mask(self) -> usize { 159*ea60cea0SAlexandre Courbot // No underflow can occur as the alignment is guaranteed to be a power of two, and thus is 160*ea60cea0SAlexandre Courbot // non-zero. 161*ea60cea0SAlexandre Courbot !(self.as_usize() - 1) 162*ea60cea0SAlexandre Courbot } 163*ea60cea0SAlexandre Courbot } 164*ea60cea0SAlexandre Courbot 165*ea60cea0SAlexandre Courbot /// Trait for items that can be aligned against an [`Alignment`]. 166*ea60cea0SAlexandre Courbot pub trait Alignable: Sized { 167*ea60cea0SAlexandre Courbot /// Aligns `self` down to `alignment`. 168*ea60cea0SAlexandre Courbot /// 169*ea60cea0SAlexandre Courbot /// # Examples 170*ea60cea0SAlexandre Courbot /// 171*ea60cea0SAlexandre Courbot /// ``` 172*ea60cea0SAlexandre Courbot /// use kernel::ptr::{Alignable, Alignment}; 173*ea60cea0SAlexandre Courbot /// 174*ea60cea0SAlexandre Courbot /// assert_eq!(0x2f_usize.align_down(Alignment::new::<0x10>()), 0x20); 175*ea60cea0SAlexandre Courbot /// assert_eq!(0x30usize.align_down(Alignment::new::<0x10>()), 0x30); 176*ea60cea0SAlexandre Courbot /// assert_eq!(0xf0u8.align_down(Alignment::new::<0x1000>()), 0x0); 177*ea60cea0SAlexandre Courbot /// ``` 178*ea60cea0SAlexandre Courbot fn align_down(self, alignment: Alignment) -> Self; 179*ea60cea0SAlexandre Courbot 180*ea60cea0SAlexandre Courbot /// Aligns `self` up to `alignment`, returning `None` if aligning would result in an overflow. 181*ea60cea0SAlexandre Courbot /// 182*ea60cea0SAlexandre Courbot /// # Examples 183*ea60cea0SAlexandre Courbot /// 184*ea60cea0SAlexandre Courbot /// ``` 185*ea60cea0SAlexandre Courbot /// use kernel::ptr::{Alignable, Alignment}; 186*ea60cea0SAlexandre Courbot /// 187*ea60cea0SAlexandre Courbot /// assert_eq!(0x4fusize.align_up(Alignment::new::<0x10>()), Some(0x50)); 188*ea60cea0SAlexandre Courbot /// assert_eq!(0x40usize.align_up(Alignment::new::<0x10>()), Some(0x40)); 189*ea60cea0SAlexandre Courbot /// assert_eq!(0x0usize.align_up(Alignment::new::<0x10>()), Some(0x0)); 190*ea60cea0SAlexandre Courbot /// assert_eq!(u8::MAX.align_up(Alignment::new::<0x10>()), None); 191*ea60cea0SAlexandre Courbot /// assert_eq!(0x10u8.align_up(Alignment::new::<0x100>()), None); 192*ea60cea0SAlexandre Courbot /// assert_eq!(0x0u8.align_up(Alignment::new::<0x100>()), Some(0x0)); 193*ea60cea0SAlexandre Courbot /// ``` 194*ea60cea0SAlexandre Courbot fn align_up(self, alignment: Alignment) -> Option<Self>; 195*ea60cea0SAlexandre Courbot } 196*ea60cea0SAlexandre Courbot 197*ea60cea0SAlexandre Courbot /// Implement [`Alignable`] for unsigned integer types. 198*ea60cea0SAlexandre Courbot macro_rules! impl_alignable_uint { 199*ea60cea0SAlexandre Courbot ($($t:ty),*) => { 200*ea60cea0SAlexandre Courbot $( 201*ea60cea0SAlexandre Courbot impl Alignable for $t { 202*ea60cea0SAlexandre Courbot #[inline(always)] 203*ea60cea0SAlexandre Courbot fn align_down(self, alignment: Alignment) -> Self { 204*ea60cea0SAlexandre Courbot // The operands of `&` need to be of the same type so convert the alignment to 205*ea60cea0SAlexandre Courbot // `Self`. This means we need to compute the mask ourselves. 206*ea60cea0SAlexandre Courbot ::core::num::NonZero::<Self>::try_from(alignment.as_nonzero()) 207*ea60cea0SAlexandre Courbot .map(|align| self & !(align.get() - 1)) 208*ea60cea0SAlexandre Courbot // An alignment larger than `Self` always aligns down to `0`. 209*ea60cea0SAlexandre Courbot .unwrap_or(0) 210*ea60cea0SAlexandre Courbot } 211*ea60cea0SAlexandre Courbot 212*ea60cea0SAlexandre Courbot #[inline(always)] 213*ea60cea0SAlexandre Courbot fn align_up(self, alignment: Alignment) -> Option<Self> { 214*ea60cea0SAlexandre Courbot let aligned_down = self.align_down(alignment); 215*ea60cea0SAlexandre Courbot if self == aligned_down { 216*ea60cea0SAlexandre Courbot Some(aligned_down) 217*ea60cea0SAlexandre Courbot } else { 218*ea60cea0SAlexandre Courbot Self::try_from(alignment.as_usize()) 219*ea60cea0SAlexandre Courbot .ok() 220*ea60cea0SAlexandre Courbot .and_then(|align| aligned_down.checked_add(align)) 221*ea60cea0SAlexandre Courbot } 222*ea60cea0SAlexandre Courbot } 223*ea60cea0SAlexandre Courbot } 224*ea60cea0SAlexandre Courbot )* 225*ea60cea0SAlexandre Courbot }; 226*ea60cea0SAlexandre Courbot } 227*ea60cea0SAlexandre Courbot 228*ea60cea0SAlexandre Courbot impl_alignable_uint!(u8, u16, u32, u64, usize); 229