1*f41941aaSGary Guo // SPDX-License-Identifier: GPL-2.0 2*f41941aaSGary Guo 3*f41941aaSGary Guo //! Infrastructure for handling projections. 4*f41941aaSGary Guo 5*f41941aaSGary Guo use core::{ 6*f41941aaSGary Guo mem::MaybeUninit, 7*f41941aaSGary Guo ops::Deref, // 8*f41941aaSGary Guo }; 9*f41941aaSGary Guo 10*f41941aaSGary Guo use crate::prelude::*; 11*f41941aaSGary Guo 12*f41941aaSGary Guo /// Error raised when a projection is attempted on an array or slice out of bounds. 13*f41941aaSGary Guo pub struct OutOfBound; 14*f41941aaSGary Guo 15*f41941aaSGary Guo impl From<OutOfBound> for Error { 16*f41941aaSGary Guo #[inline(always)] from(_: OutOfBound) -> Self17*f41941aaSGary Guo fn from(_: OutOfBound) -> Self { 18*f41941aaSGary Guo ERANGE 19*f41941aaSGary Guo } 20*f41941aaSGary Guo } 21*f41941aaSGary Guo 22*f41941aaSGary Guo /// A helper trait to perform index projection. 23*f41941aaSGary Guo /// 24*f41941aaSGary Guo /// This is similar to [`core::slice::SliceIndex`], but operates on raw pointers safely and 25*f41941aaSGary Guo /// fallibly. 26*f41941aaSGary Guo /// 27*f41941aaSGary Guo /// # Safety 28*f41941aaSGary Guo /// 29*f41941aaSGary Guo /// The implementation of `index` and `get` (if [`Some`] is returned) must ensure that, if provided 30*f41941aaSGary Guo /// input pointer `slice` and returned pointer `output`, then: 31*f41941aaSGary Guo /// - `output` has the same provenance as `slice`; 32*f41941aaSGary Guo /// - `output.byte_offset_from(slice)` is between 0 to 33*f41941aaSGary Guo /// `KnownSize::size(slice) - KnownSize::size(output)`. 34*f41941aaSGary Guo /// 35*f41941aaSGary Guo /// This means that if the input pointer is valid, then pointer returned by `get` or `index` is 36*f41941aaSGary Guo /// also valid. 37*f41941aaSGary Guo #[diagnostic::on_unimplemented(message = "`{Self}` cannot be used to index `{T}`")] 38*f41941aaSGary Guo #[doc(hidden)] 39*f41941aaSGary Guo pub unsafe trait ProjectIndex<T: ?Sized>: Sized { 40*f41941aaSGary Guo type Output: ?Sized; 41*f41941aaSGary Guo 42*f41941aaSGary Guo /// Returns an index-projected pointer, if in bounds. get(self, slice: *mut T) -> Option<*mut Self::Output>43*f41941aaSGary Guo fn get(self, slice: *mut T) -> Option<*mut Self::Output>; 44*f41941aaSGary Guo 45*f41941aaSGary Guo /// Returns an index-projected pointer; fail the build if it cannot be proved to be in bounds. 46*f41941aaSGary Guo #[inline(always)] index(self, slice: *mut T) -> *mut Self::Output47*f41941aaSGary Guo fn index(self, slice: *mut T) -> *mut Self::Output { 48*f41941aaSGary Guo Self::get(self, slice).unwrap_or_else(|| build_error!()) 49*f41941aaSGary Guo } 50*f41941aaSGary Guo } 51*f41941aaSGary Guo 52*f41941aaSGary Guo // Forward array impl to slice impl. 53*f41941aaSGary Guo // 54*f41941aaSGary Guo // SAFETY: Safety requirement guaranteed by the forwarded impl. 55*f41941aaSGary Guo unsafe impl<T, I, const N: usize> ProjectIndex<[T; N]> for I 56*f41941aaSGary Guo where 57*f41941aaSGary Guo I: ProjectIndex<[T]>, 58*f41941aaSGary Guo { 59*f41941aaSGary Guo type Output = <I as ProjectIndex<[T]>>::Output; 60*f41941aaSGary Guo 61*f41941aaSGary Guo #[inline(always)] get(self, slice: *mut [T; N]) -> Option<*mut Self::Output>62*f41941aaSGary Guo fn get(self, slice: *mut [T; N]) -> Option<*mut Self::Output> { 63*f41941aaSGary Guo <I as ProjectIndex<[T]>>::get(self, slice) 64*f41941aaSGary Guo } 65*f41941aaSGary Guo 66*f41941aaSGary Guo #[inline(always)] index(self, slice: *mut [T; N]) -> *mut Self::Output67*f41941aaSGary Guo fn index(self, slice: *mut [T; N]) -> *mut Self::Output { 68*f41941aaSGary Guo <I as ProjectIndex<[T]>>::index(self, slice) 69*f41941aaSGary Guo } 70*f41941aaSGary Guo } 71*f41941aaSGary Guo 72*f41941aaSGary Guo // SAFETY: `get`-returned pointer has the same provenance as `slice` and the offset is checked to 73*f41941aaSGary Guo // not exceed the required bound. 74*f41941aaSGary Guo unsafe impl<T> ProjectIndex<[T]> for usize { 75*f41941aaSGary Guo type Output = T; 76*f41941aaSGary Guo 77*f41941aaSGary Guo #[inline(always)] get(self, slice: *mut [T]) -> Option<*mut T>78*f41941aaSGary Guo fn get(self, slice: *mut [T]) -> Option<*mut T> { 79*f41941aaSGary Guo if self >= slice.len() { 80*f41941aaSGary Guo None 81*f41941aaSGary Guo } else { 82*f41941aaSGary Guo Some(slice.cast::<T>().wrapping_add(self)) 83*f41941aaSGary Guo } 84*f41941aaSGary Guo } 85*f41941aaSGary Guo } 86*f41941aaSGary Guo 87*f41941aaSGary Guo // SAFETY: `get`-returned pointer has the same provenance as `slice` and the offset is checked to 88*f41941aaSGary Guo // not exceed the required bound. 89*f41941aaSGary Guo unsafe impl<T> ProjectIndex<[T]> for core::ops::Range<usize> { 90*f41941aaSGary Guo type Output = [T]; 91*f41941aaSGary Guo 92*f41941aaSGary Guo #[inline(always)] get(self, slice: *mut [T]) -> Option<*mut [T]>93*f41941aaSGary Guo fn get(self, slice: *mut [T]) -> Option<*mut [T]> { 94*f41941aaSGary Guo let new_len = self.end.checked_sub(self.start)?; 95*f41941aaSGary Guo if self.end > slice.len() { 96*f41941aaSGary Guo return None; 97*f41941aaSGary Guo } 98*f41941aaSGary Guo Some(core::ptr::slice_from_raw_parts_mut( 99*f41941aaSGary Guo slice.cast::<T>().wrapping_add(self.start), 100*f41941aaSGary Guo new_len, 101*f41941aaSGary Guo )) 102*f41941aaSGary Guo } 103*f41941aaSGary Guo } 104*f41941aaSGary Guo 105*f41941aaSGary Guo // SAFETY: Safety requirement guaranteed by the forwarded impl. 106*f41941aaSGary Guo unsafe impl<T> ProjectIndex<[T]> for core::ops::RangeTo<usize> { 107*f41941aaSGary Guo type Output = [T]; 108*f41941aaSGary Guo 109*f41941aaSGary Guo #[inline(always)] get(self, slice: *mut [T]) -> Option<*mut [T]>110*f41941aaSGary Guo fn get(self, slice: *mut [T]) -> Option<*mut [T]> { 111*f41941aaSGary Guo (0..self.end).get(slice) 112*f41941aaSGary Guo } 113*f41941aaSGary Guo } 114*f41941aaSGary Guo 115*f41941aaSGary Guo // SAFETY: Safety requirement guaranteed by the forwarded impl. 116*f41941aaSGary Guo unsafe impl<T> ProjectIndex<[T]> for core::ops::RangeFrom<usize> { 117*f41941aaSGary Guo type Output = [T]; 118*f41941aaSGary Guo 119*f41941aaSGary Guo #[inline(always)] get(self, slice: *mut [T]) -> Option<*mut [T]>120*f41941aaSGary Guo fn get(self, slice: *mut [T]) -> Option<*mut [T]> { 121*f41941aaSGary Guo (self.start..slice.len()).get(slice) 122*f41941aaSGary Guo } 123*f41941aaSGary Guo } 124*f41941aaSGary Guo 125*f41941aaSGary Guo // SAFETY: `get` returned the pointer as is, so it always has the same provenance and offset of 0. 126*f41941aaSGary Guo unsafe impl<T> ProjectIndex<[T]> for core::ops::RangeFull { 127*f41941aaSGary Guo type Output = [T]; 128*f41941aaSGary Guo 129*f41941aaSGary Guo #[inline(always)] get(self, slice: *mut [T]) -> Option<*mut [T]>130*f41941aaSGary Guo fn get(self, slice: *mut [T]) -> Option<*mut [T]> { 131*f41941aaSGary Guo Some(slice) 132*f41941aaSGary Guo } 133*f41941aaSGary Guo } 134*f41941aaSGary Guo 135*f41941aaSGary Guo /// A helper trait to perform field projection. 136*f41941aaSGary Guo /// 137*f41941aaSGary Guo /// This trait has a `DEREF` generic parameter so it can be implemented twice for types that 138*f41941aaSGary Guo /// implement [`Deref`]. This will cause an ambiguity error and thus block [`Deref`] types being 139*f41941aaSGary Guo /// used as base of projection, as they can inject unsoundness. Users therefore must not specify 140*f41941aaSGary Guo /// `DEREF` and should always leave it to be inferred. 141*f41941aaSGary Guo /// 142*f41941aaSGary Guo /// # Safety 143*f41941aaSGary Guo /// 144*f41941aaSGary Guo /// `proj` may only invoke `f` with a valid allocation, as the documentation of [`Self::proj`] 145*f41941aaSGary Guo /// describes. 146*f41941aaSGary Guo #[doc(hidden)] 147*f41941aaSGary Guo pub unsafe trait ProjectField<const DEREF: bool> { 148*f41941aaSGary Guo /// Project a pointer to a type to a pointer of a field. 149*f41941aaSGary Guo /// 150*f41941aaSGary Guo /// `f` may only be invoked with a valid allocation so it can safely obtain raw pointers to 151*f41941aaSGary Guo /// fields using `&raw mut`. 152*f41941aaSGary Guo /// 153*f41941aaSGary Guo /// This is needed because `base` might not point to a valid allocation, while `&raw mut` 154*f41941aaSGary Guo /// requires pointers to be in bounds of a valid allocation. 155*f41941aaSGary Guo /// 156*f41941aaSGary Guo /// # Safety 157*f41941aaSGary Guo /// 158*f41941aaSGary Guo /// `f` must return a pointer in bounds of the provided pointer. proj<F>(base: *mut Self, f: impl FnOnce(*mut Self) -> *mut F) -> *mut F159*f41941aaSGary Guo unsafe fn proj<F>(base: *mut Self, f: impl FnOnce(*mut Self) -> *mut F) -> *mut F; 160*f41941aaSGary Guo } 161*f41941aaSGary Guo 162*f41941aaSGary Guo // NOTE: in theory, this API should work for `T: ?Sized` and `F: ?Sized`, too. However, we cannot 163*f41941aaSGary Guo // currently support that as we need to obtain a valid allocation that `&raw const` can operate on. 164*f41941aaSGary Guo // 165*f41941aaSGary Guo // SAFETY: `proj` invokes `f` with valid allocation. 166*f41941aaSGary Guo unsafe impl<T> ProjectField<false> for T { 167*f41941aaSGary Guo #[inline(always)] proj<F>(base: *mut Self, f: impl FnOnce(*mut Self) -> *mut F) -> *mut F168*f41941aaSGary Guo unsafe fn proj<F>(base: *mut Self, f: impl FnOnce(*mut Self) -> *mut F) -> *mut F { 169*f41941aaSGary Guo // Create a valid allocation to start projection, as `base` is not necessarily so. The 170*f41941aaSGary Guo // memory is never actually used so it will be optimized out, so it should work even for 171*f41941aaSGary Guo // very large `T` (`memoffset` crate also relies on this). To be extra certain, we also 172*f41941aaSGary Guo // annotate `f` closure with `#[inline(always)]` in the macro. 173*f41941aaSGary Guo let mut place = MaybeUninit::uninit(); 174*f41941aaSGary Guo let place_base = place.as_mut_ptr(); 175*f41941aaSGary Guo let field = f(place_base); 176*f41941aaSGary Guo // SAFETY: `field` is in bounds from `base` per safety requirement. 177*f41941aaSGary Guo let offset = unsafe { field.byte_offset_from(place_base) }; 178*f41941aaSGary Guo // Use `wrapping_byte_offset` as `base` does not need to be of valid allocation. 179*f41941aaSGary Guo base.wrapping_byte_offset(offset).cast() 180*f41941aaSGary Guo } 181*f41941aaSGary Guo } 182*f41941aaSGary Guo 183*f41941aaSGary Guo // SAFETY: Vacuously satisfied. 184*f41941aaSGary Guo unsafe impl<T: Deref> ProjectField<true> for T { 185*f41941aaSGary Guo #[inline(always)] proj<F>(_: *mut Self, _: impl FnOnce(*mut Self) -> *mut F) -> *mut F186*f41941aaSGary Guo unsafe fn proj<F>(_: *mut Self, _: impl FnOnce(*mut Self) -> *mut F) -> *mut F { 187*f41941aaSGary Guo build_error!("this function is a guard against `Deref` impl and is never invoked"); 188*f41941aaSGary Guo } 189*f41941aaSGary Guo } 190*f41941aaSGary Guo 191*f41941aaSGary Guo /// Create a projection from a raw pointer. 192*f41941aaSGary Guo /// 193*f41941aaSGary Guo /// The projected pointer is within the memory region marked by the input pointer. There is no 194*f41941aaSGary Guo /// requirement that the input raw pointer needs to be valid, so this macro may be used for 195*f41941aaSGary Guo /// projecting pointers outside normal address space, e.g. I/O pointers. However, if the input 196*f41941aaSGary Guo /// pointer is valid, the projected pointer is also valid. 197*f41941aaSGary Guo /// 198*f41941aaSGary Guo /// Supported projections include field projections and index projections. 199*f41941aaSGary Guo /// It is not allowed to project into types that implement custom [`Deref`] or 200*f41941aaSGary Guo /// [`Index`](core::ops::Index). 201*f41941aaSGary Guo /// 202*f41941aaSGary Guo /// The macro has basic syntax of `kernel::ptr::project!(ptr, projection)`, where `ptr` is an 203*f41941aaSGary Guo /// expression that evaluates to a raw pointer which serves as the base of projection. `projection` 204*f41941aaSGary Guo /// can be a projection expression of form `.field` (normally identifier, or numeral in case of 205*f41941aaSGary Guo /// tuple structs) or of form `[index]`. 206*f41941aaSGary Guo /// 207*f41941aaSGary Guo /// If a mutable pointer is needed, the macro input can be prefixed with the `mut` keyword, i.e. 208*f41941aaSGary Guo /// `kernel::ptr::project!(mut ptr, projection)`. By default, a const pointer is created. 209*f41941aaSGary Guo /// 210*f41941aaSGary Guo /// `ptr::project!` macro can perform both fallible indexing and build-time checked indexing. 211*f41941aaSGary Guo /// `[index]` form performs build-time bounds checking; if compiler fails to prove `[index]` is in 212*f41941aaSGary Guo /// bounds, compilation will fail. `[index]?` can be used to perform runtime bounds checking; 213*f41941aaSGary Guo /// `OutOfBound` error is raised via `?` if the index is out of bounds. 214*f41941aaSGary Guo /// 215*f41941aaSGary Guo /// # Examples 216*f41941aaSGary Guo /// 217*f41941aaSGary Guo /// Field projections are performed with `.field_name`: 218*f41941aaSGary Guo /// 219*f41941aaSGary Guo /// ``` 220*f41941aaSGary Guo /// struct MyStruct { field: u32, } 221*f41941aaSGary Guo /// let ptr: *const MyStruct = core::ptr::dangling(); 222*f41941aaSGary Guo /// let field_ptr: *const u32 = kernel::ptr::project!(ptr, .field); 223*f41941aaSGary Guo /// 224*f41941aaSGary Guo /// struct MyTupleStruct(u32, u32); 225*f41941aaSGary Guo /// 226*f41941aaSGary Guo /// fn proj(ptr: *const MyTupleStruct) { 227*f41941aaSGary Guo /// let field_ptr: *const u32 = kernel::ptr::project!(ptr, .1); 228*f41941aaSGary Guo /// } 229*f41941aaSGary Guo /// ``` 230*f41941aaSGary Guo /// 231*f41941aaSGary Guo /// Index projections are performed with `[index]`: 232*f41941aaSGary Guo /// 233*f41941aaSGary Guo /// ``` 234*f41941aaSGary Guo /// fn proj(ptr: *const [u8; 32]) -> Result { 235*f41941aaSGary Guo /// let field_ptr: *const u8 = kernel::ptr::project!(ptr, [1]); 236*f41941aaSGary Guo /// // The following invocation, if uncommented, would fail the build. 237*f41941aaSGary Guo /// // 238*f41941aaSGary Guo /// // kernel::ptr::project!(ptr, [128]); 239*f41941aaSGary Guo /// 240*f41941aaSGary Guo /// // This will raise an `OutOfBound` error (which is convertible to `ERANGE`). 241*f41941aaSGary Guo /// kernel::ptr::project!(ptr, [128]?); 242*f41941aaSGary Guo /// Ok(()) 243*f41941aaSGary Guo /// } 244*f41941aaSGary Guo /// ``` 245*f41941aaSGary Guo /// 246*f41941aaSGary Guo /// If you need to match on the error instead of propagate, put the invocation inside a closure: 247*f41941aaSGary Guo /// 248*f41941aaSGary Guo /// ``` 249*f41941aaSGary Guo /// let ptr: *const [u8; 32] = core::ptr::dangling(); 250*f41941aaSGary Guo /// let field_ptr: Result<*const u8> = (|| -> Result<_> { 251*f41941aaSGary Guo /// Ok(kernel::ptr::project!(ptr, [128]?)) 252*f41941aaSGary Guo /// })(); 253*f41941aaSGary Guo /// assert!(field_ptr.is_err()); 254*f41941aaSGary Guo /// ``` 255*f41941aaSGary Guo /// 256*f41941aaSGary Guo /// For mutable pointers, put `mut` as the first token in macro invocation. 257*f41941aaSGary Guo /// 258*f41941aaSGary Guo /// ``` 259*f41941aaSGary Guo /// let ptr: *mut [(u8, u16); 32] = core::ptr::dangling_mut(); 260*f41941aaSGary Guo /// let field_ptr: *mut u16 = kernel::ptr::project!(mut ptr, [1].1); 261*f41941aaSGary Guo /// ``` 262*f41941aaSGary Guo #[macro_export] 263*f41941aaSGary Guo macro_rules! project_pointer { 264*f41941aaSGary Guo (@gen $ptr:ident, ) => {}; 265*f41941aaSGary Guo // Field projection. `$field` needs to be `tt` to support tuple index like `.0`. 266*f41941aaSGary Guo (@gen $ptr:ident, .$field:tt $($rest:tt)*) => { 267*f41941aaSGary Guo // SAFETY: The provided closure always returns an in-bounds pointer. 268*f41941aaSGary Guo let $ptr = unsafe { 269*f41941aaSGary Guo $crate::ptr::projection::ProjectField::proj($ptr, #[inline(always)] |ptr| { 270*f41941aaSGary Guo // Check unaligned field. Not all users (e.g. DMA) can handle unaligned 271*f41941aaSGary Guo // projections. 272*f41941aaSGary Guo if false { 273*f41941aaSGary Guo let _ = &(*ptr).$field; 274*f41941aaSGary Guo } 275*f41941aaSGary Guo // SAFETY: `$field` is in bounds, and no implicit `Deref` is possible (if the 276*f41941aaSGary Guo // type implements `Deref`, Rust cannot infer the generic parameter `DEREF`). 277*f41941aaSGary Guo &raw mut (*ptr).$field 278*f41941aaSGary Guo }) 279*f41941aaSGary Guo }; 280*f41941aaSGary Guo $crate::ptr::project!(@gen $ptr, $($rest)*) 281*f41941aaSGary Guo }; 282*f41941aaSGary Guo // Fallible index projection. 283*f41941aaSGary Guo (@gen $ptr:ident, [$index:expr]? $($rest:tt)*) => { 284*f41941aaSGary Guo let $ptr = $crate::ptr::projection::ProjectIndex::get($index, $ptr) 285*f41941aaSGary Guo .ok_or($crate::ptr::projection::OutOfBound)?; 286*f41941aaSGary Guo $crate::ptr::project!(@gen $ptr, $($rest)*) 287*f41941aaSGary Guo }; 288*f41941aaSGary Guo // Build-time checked index projection. 289*f41941aaSGary Guo (@gen $ptr:ident, [$index:expr] $($rest:tt)*) => { 290*f41941aaSGary Guo let $ptr = $crate::ptr::projection::ProjectIndex::index($index, $ptr); 291*f41941aaSGary Guo $crate::ptr::project!(@gen $ptr, $($rest)*) 292*f41941aaSGary Guo }; 293*f41941aaSGary Guo (mut $ptr:expr, $($proj:tt)*) => {{ 294*f41941aaSGary Guo let ptr: *mut _ = $ptr; 295*f41941aaSGary Guo $crate::ptr::project!(@gen ptr, $($proj)*); 296*f41941aaSGary Guo ptr 297*f41941aaSGary Guo }}; 298*f41941aaSGary Guo ($ptr:expr, $($proj:tt)*) => {{ 299*f41941aaSGary Guo let ptr = <*const _>::cast_mut($ptr); 300*f41941aaSGary Guo // We currently always project using mutable pointer, as it is not decided whether `&raw 301*f41941aaSGary Guo // const` allows the resulting pointer to be mutated (see documentation of `addr_of!`). 302*f41941aaSGary Guo $crate::ptr::project!(@gen ptr, $($proj)*); 303*f41941aaSGary Guo ptr.cast_const() 304*f41941aaSGary Guo }}; 305*f41941aaSGary Guo } 306