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