xref: /linux/rust/kernel/ptr.rs (revision 4f38da1f027ea2c9f01bb71daa7a299c191b6940)
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