1ea60cea0SAlexandre Courbot // SPDX-License-Identifier: GPL-2.0
2ea60cea0SAlexandre Courbot
3ea60cea0SAlexandre Courbot //! Types and functions to work with pointers and addresses.
4ea60cea0SAlexandre Courbot
5f41941aaSGary Guo pub mod projection;
6f41941aaSGary Guo pub use crate::project_pointer as project;
7f41941aaSGary Guo
808da98f1SGary Guo use core::mem::{
908da98f1SGary Guo align_of,
1008da98f1SGary Guo size_of, //
1108da98f1SGary Guo };
12ea60cea0SAlexandre Courbot use core::num::NonZero;
13ea60cea0SAlexandre Courbot
14560a7a9bSGary Guo use crate::const_assert;
15560a7a9bSGary Guo
16ea60cea0SAlexandre Courbot /// Type representing an alignment, which is always a power of two.
17ea60cea0SAlexandre Courbot ///
18ea60cea0SAlexandre Courbot /// It is used to validate that a given value is a valid alignment, and to perform masking and
19ea60cea0SAlexandre Courbot /// alignment operations.
20ea60cea0SAlexandre Courbot ///
21ea60cea0SAlexandre Courbot /// This is a temporary substitute for the [`Alignment`] nightly type from the standard library,
22ea60cea0SAlexandre Courbot /// and to be eventually replaced by it.
23ea60cea0SAlexandre Courbot ///
24ea60cea0SAlexandre Courbot /// [`Alignment`]: https://github.com/rust-lang/rust/issues/102070
25ea60cea0SAlexandre Courbot ///
26ea60cea0SAlexandre Courbot /// # Invariants
27ea60cea0SAlexandre Courbot ///
28ea60cea0SAlexandre Courbot /// An alignment is always a power of two.
29ea60cea0SAlexandre Courbot #[repr(transparent)]
30ea60cea0SAlexandre Courbot #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
31ea60cea0SAlexandre Courbot pub struct Alignment(NonZero<usize>);
32ea60cea0SAlexandre Courbot
33ea60cea0SAlexandre Courbot impl Alignment {
34ea60cea0SAlexandre Courbot /// Validates that `ALIGN` is a power of two at build-time, and returns an [`Alignment`] of the
35ea60cea0SAlexandre Courbot /// same value.
36ea60cea0SAlexandre Courbot ///
37ea60cea0SAlexandre Courbot /// A build error is triggered if `ALIGN` is not a power of two.
38ea60cea0SAlexandre Courbot ///
39ea60cea0SAlexandre Courbot /// # Examples
40ea60cea0SAlexandre Courbot ///
41ea60cea0SAlexandre Courbot /// ```
42ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment;
43ea60cea0SAlexandre Courbot ///
44ea60cea0SAlexandre Courbot /// let v = Alignment::new::<16>();
45ea60cea0SAlexandre Courbot /// assert_eq!(v.as_usize(), 16);
46ea60cea0SAlexandre Courbot /// ```
47ea60cea0SAlexandre Courbot #[inline(always)]
new<const ALIGN: usize>() -> Self48ea60cea0SAlexandre Courbot pub const fn new<const ALIGN: usize>() -> Self {
49560a7a9bSGary Guo const_assert!(
50ea60cea0SAlexandre Courbot ALIGN.is_power_of_two(),
51ea60cea0SAlexandre Courbot "Provided alignment is not a power of two."
52ea60cea0SAlexandre Courbot );
53ea60cea0SAlexandre Courbot
54ea60cea0SAlexandre Courbot // INVARIANT: `align` is a power of two.
55ea60cea0SAlexandre Courbot // SAFETY: `align` is a power of two, and thus non-zero.
56ea60cea0SAlexandre Courbot Self(unsafe { NonZero::new_unchecked(ALIGN) })
57ea60cea0SAlexandre Courbot }
58ea60cea0SAlexandre Courbot
59ea60cea0SAlexandre Courbot /// Validates that `align` is a power of two at runtime, and returns an
60ea60cea0SAlexandre Courbot /// [`Alignment`] of the same value.
61ea60cea0SAlexandre Courbot ///
62ea60cea0SAlexandre Courbot /// Returns [`None`] if `align` is not a power of two.
63ea60cea0SAlexandre Courbot ///
64ea60cea0SAlexandre Courbot /// # Examples
65ea60cea0SAlexandre Courbot ///
66ea60cea0SAlexandre Courbot /// ```
67ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment;
68ea60cea0SAlexandre Courbot ///
69ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new_checked(16), Some(Alignment::new::<16>()));
70ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new_checked(15), None);
71ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new_checked(1), Some(Alignment::new::<1>()));
72ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new_checked(0), None);
73ea60cea0SAlexandre Courbot /// ```
74ea60cea0SAlexandre Courbot #[inline(always)]
new_checked(align: usize) -> Option<Self>75ea60cea0SAlexandre Courbot pub const fn new_checked(align: usize) -> Option<Self> {
76ea60cea0SAlexandre Courbot if align.is_power_of_two() {
77ea60cea0SAlexandre Courbot // INVARIANT: `align` is a power of two.
78ea60cea0SAlexandre Courbot // SAFETY: `align` is a power of two, and thus non-zero.
79ea60cea0SAlexandre Courbot Some(Self(unsafe { NonZero::new_unchecked(align) }))
80ea60cea0SAlexandre Courbot } else {
81ea60cea0SAlexandre Courbot None
82ea60cea0SAlexandre Courbot }
83ea60cea0SAlexandre Courbot }
84ea60cea0SAlexandre Courbot
85ea60cea0SAlexandre Courbot /// Returns the alignment of `T`.
86ea60cea0SAlexandre Courbot ///
87ea60cea0SAlexandre Courbot /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`].
88ea60cea0SAlexandre Courbot #[inline(always)]
of<T>() -> Self89ea60cea0SAlexandre Courbot pub const fn of<T>() -> Self {
90ea60cea0SAlexandre Courbot // This cannot panic since alignments are always powers of two.
91ea60cea0SAlexandre Courbot //
92ea60cea0SAlexandre Courbot // We unfortunately cannot use `new` as it would require the `generic_const_exprs` feature.
93ea60cea0SAlexandre Courbot const { Alignment::new_checked(align_of::<T>()).unwrap() }
94ea60cea0SAlexandre Courbot }
95ea60cea0SAlexandre Courbot
96ea60cea0SAlexandre Courbot /// Returns this alignment as a [`usize`].
97ea60cea0SAlexandre Courbot ///
98ea60cea0SAlexandre Courbot /// It is guaranteed to be a power of two.
99ea60cea0SAlexandre Courbot ///
100ea60cea0SAlexandre Courbot /// # Examples
101ea60cea0SAlexandre Courbot ///
102ea60cea0SAlexandre Courbot /// ```
103ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment;
104ea60cea0SAlexandre Courbot ///
105ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new::<16>().as_usize(), 16);
106ea60cea0SAlexandre Courbot /// ```
107ea60cea0SAlexandre Courbot #[inline(always)]
as_usize(self) -> usize108ea60cea0SAlexandre Courbot pub const fn as_usize(self) -> usize {
109ea60cea0SAlexandre Courbot self.as_nonzero().get()
110ea60cea0SAlexandre Courbot }
111ea60cea0SAlexandre Courbot
112ea60cea0SAlexandre Courbot /// Returns this alignment as a [`NonZero`].
113ea60cea0SAlexandre Courbot ///
114ea60cea0SAlexandre Courbot /// It is guaranteed to be a power of two.
115ea60cea0SAlexandre Courbot ///
116ea60cea0SAlexandre Courbot /// # Examples
117ea60cea0SAlexandre Courbot ///
118ea60cea0SAlexandre Courbot /// ```
119ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment;
120ea60cea0SAlexandre Courbot ///
121ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new::<16>().as_nonzero().get(), 16);
122ea60cea0SAlexandre Courbot /// ```
123ea60cea0SAlexandre Courbot #[inline(always)]
as_nonzero(self) -> NonZero<usize>124ea60cea0SAlexandre Courbot pub const fn as_nonzero(self) -> NonZero<usize> {
125ea60cea0SAlexandre Courbot // Allow the compiler to know that the value is indeed a power of two. This can help
126ea60cea0SAlexandre Courbot // optimize some operations down the line, like e.g. replacing divisions by bit shifts.
127ea60cea0SAlexandre Courbot if !self.0.is_power_of_two() {
128ea60cea0SAlexandre Courbot // SAFETY: Per the invariants, `self.0` is always a power of two so this block will
129ea60cea0SAlexandre Courbot // never be reached.
130ea60cea0SAlexandre Courbot unsafe { core::hint::unreachable_unchecked() }
131ea60cea0SAlexandre Courbot }
132ea60cea0SAlexandre Courbot self.0
133ea60cea0SAlexandre Courbot }
134ea60cea0SAlexandre Courbot
135ea60cea0SAlexandre Courbot /// Returns the base-2 logarithm of the alignment.
136ea60cea0SAlexandre Courbot ///
137ea60cea0SAlexandre Courbot /// # Examples
138ea60cea0SAlexandre Courbot ///
139ea60cea0SAlexandre Courbot /// ```
140ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment;
141ea60cea0SAlexandre Courbot ///
142ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::of::<u8>().log2(), 0);
143ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new::<16>().log2(), 4);
144ea60cea0SAlexandre Courbot /// ```
145ea60cea0SAlexandre Courbot #[inline(always)]
log2(self) -> u32146ea60cea0SAlexandre Courbot pub const fn log2(self) -> u32 {
147ea60cea0SAlexandre Courbot self.0.ilog2()
148ea60cea0SAlexandre Courbot }
149ea60cea0SAlexandre Courbot
150ea60cea0SAlexandre Courbot /// Returns the mask for this alignment.
151ea60cea0SAlexandre Courbot ///
152ea60cea0SAlexandre Courbot /// This is equivalent to `!(self.as_usize() - 1)`.
153ea60cea0SAlexandre Courbot ///
154ea60cea0SAlexandre Courbot /// # Examples
155ea60cea0SAlexandre Courbot ///
156ea60cea0SAlexandre Courbot /// ```
157ea60cea0SAlexandre Courbot /// use kernel::ptr::Alignment;
158ea60cea0SAlexandre Courbot ///
159ea60cea0SAlexandre Courbot /// assert_eq!(Alignment::new::<0x10>().mask(), !0xf);
160ea60cea0SAlexandre Courbot /// ```
161ea60cea0SAlexandre Courbot #[inline(always)]
mask(self) -> usize162ea60cea0SAlexandre Courbot pub const fn mask(self) -> usize {
163ea60cea0SAlexandre Courbot // No underflow can occur as the alignment is guaranteed to be a power of two, and thus is
164ea60cea0SAlexandre Courbot // non-zero.
165ea60cea0SAlexandre Courbot !(self.as_usize() - 1)
166ea60cea0SAlexandre Courbot }
167ea60cea0SAlexandre Courbot }
168ea60cea0SAlexandre Courbot
169ea60cea0SAlexandre Courbot /// Trait for items that can be aligned against an [`Alignment`].
170ea60cea0SAlexandre Courbot pub trait Alignable: Sized {
171ea60cea0SAlexandre Courbot /// Aligns `self` down to `alignment`.
172ea60cea0SAlexandre Courbot ///
173ea60cea0SAlexandre Courbot /// # Examples
174ea60cea0SAlexandre Courbot ///
175ea60cea0SAlexandre Courbot /// ```
176ea60cea0SAlexandre Courbot /// use kernel::ptr::{Alignable, Alignment};
177ea60cea0SAlexandre Courbot ///
178ea60cea0SAlexandre Courbot /// assert_eq!(0x2f_usize.align_down(Alignment::new::<0x10>()), 0x20);
179ea60cea0SAlexandre Courbot /// assert_eq!(0x30usize.align_down(Alignment::new::<0x10>()), 0x30);
180ea60cea0SAlexandre Courbot /// assert_eq!(0xf0u8.align_down(Alignment::new::<0x1000>()), 0x0);
181ea60cea0SAlexandre Courbot /// ```
align_down(self, alignment: Alignment) -> Self182ea60cea0SAlexandre Courbot fn align_down(self, alignment: Alignment) -> Self;
183ea60cea0SAlexandre Courbot
184ea60cea0SAlexandre Courbot /// Aligns `self` up to `alignment`, returning `None` if aligning would result in an overflow.
185ea60cea0SAlexandre Courbot ///
186ea60cea0SAlexandre Courbot /// # Examples
187ea60cea0SAlexandre Courbot ///
188ea60cea0SAlexandre Courbot /// ```
189ea60cea0SAlexandre Courbot /// use kernel::ptr::{Alignable, Alignment};
190ea60cea0SAlexandre Courbot ///
191ea60cea0SAlexandre Courbot /// assert_eq!(0x4fusize.align_up(Alignment::new::<0x10>()), Some(0x50));
192ea60cea0SAlexandre Courbot /// assert_eq!(0x40usize.align_up(Alignment::new::<0x10>()), Some(0x40));
193ea60cea0SAlexandre Courbot /// assert_eq!(0x0usize.align_up(Alignment::new::<0x10>()), Some(0x0));
194ea60cea0SAlexandre Courbot /// assert_eq!(u8::MAX.align_up(Alignment::new::<0x10>()), None);
195ea60cea0SAlexandre Courbot /// assert_eq!(0x10u8.align_up(Alignment::new::<0x100>()), None);
196ea60cea0SAlexandre Courbot /// assert_eq!(0x0u8.align_up(Alignment::new::<0x100>()), Some(0x0));
197ea60cea0SAlexandre Courbot /// ```
align_up(self, alignment: Alignment) -> Option<Self>198ea60cea0SAlexandre Courbot fn align_up(self, alignment: Alignment) -> Option<Self>;
199ea60cea0SAlexandre Courbot }
200ea60cea0SAlexandre Courbot
201ea60cea0SAlexandre Courbot /// Implement [`Alignable`] for unsigned integer types.
202ea60cea0SAlexandre Courbot macro_rules! impl_alignable_uint {
203ea60cea0SAlexandre Courbot ($($t:ty),*) => {
204ea60cea0SAlexandre Courbot $(
205ea60cea0SAlexandre Courbot impl Alignable for $t {
206ea60cea0SAlexandre Courbot #[inline(always)]
207ea60cea0SAlexandre Courbot fn align_down(self, alignment: Alignment) -> Self {
208ea60cea0SAlexandre Courbot // The operands of `&` need to be of the same type so convert the alignment to
209ea60cea0SAlexandre Courbot // `Self`. This means we need to compute the mask ourselves.
210ea60cea0SAlexandre Courbot ::core::num::NonZero::<Self>::try_from(alignment.as_nonzero())
211ea60cea0SAlexandre Courbot .map(|align| self & !(align.get() - 1))
212ea60cea0SAlexandre Courbot // An alignment larger than `Self` always aligns down to `0`.
213ea60cea0SAlexandre Courbot .unwrap_or(0)
214ea60cea0SAlexandre Courbot }
215ea60cea0SAlexandre Courbot
216ea60cea0SAlexandre Courbot #[inline(always)]
217ea60cea0SAlexandre Courbot fn align_up(self, alignment: Alignment) -> Option<Self> {
218ea60cea0SAlexandre Courbot let aligned_down = self.align_down(alignment);
219ea60cea0SAlexandre Courbot if self == aligned_down {
220ea60cea0SAlexandre Courbot Some(aligned_down)
221ea60cea0SAlexandre Courbot } else {
222ea60cea0SAlexandre Courbot Self::try_from(alignment.as_usize())
223ea60cea0SAlexandre Courbot .ok()
224ea60cea0SAlexandre Courbot .and_then(|align| aligned_down.checked_add(align))
225ea60cea0SAlexandre Courbot }
226ea60cea0SAlexandre Courbot }
227ea60cea0SAlexandre Courbot }
228ea60cea0SAlexandre Courbot )*
229ea60cea0SAlexandre Courbot };
230ea60cea0SAlexandre Courbot }
231ea60cea0SAlexandre Courbot
232ea60cea0SAlexandre Courbot impl_alignable_uint!(u8, u16, u32, u64, usize);
2330a51b384SJohn Hubbard
23408da98f1SGary Guo /// Trait to represent compile-time known size information.
23508da98f1SGary Guo ///
23608da98f1SGary Guo /// This is a generalization of [`size_of`] that works for dynamically sized types.
23708da98f1SGary Guo pub trait KnownSize {
23808da98f1SGary Guo /// Get the size of an object of this type in bytes, with the metadata of the given pointer.
size(p: *const Self) -> usize23908da98f1SGary Guo fn size(p: *const Self) -> usize;
24008da98f1SGary Guo }
24108da98f1SGary Guo
24208da98f1SGary Guo impl<T> KnownSize for T {
24308da98f1SGary Guo #[inline(always)]
size(_: *const Self) -> usize24408da98f1SGary Guo fn size(_: *const Self) -> usize {
24508da98f1SGary Guo size_of::<T>()
24608da98f1SGary Guo }
24708da98f1SGary Guo }
24808da98f1SGary Guo
24908da98f1SGary Guo impl<T> KnownSize for [T] {
25008da98f1SGary Guo #[inline(always)]
size(p: *const Self) -> usize25108da98f1SGary Guo fn size(p: *const Self) -> usize {
25208da98f1SGary Guo p.len() * size_of::<T>()
25308da98f1SGary Guo }
25408da98f1SGary Guo }
255*b06b348eSMiguel Ojeda
2560a51b384SJohn Hubbard /// Aligns `value` up to `align`.
2570a51b384SJohn Hubbard ///
2580a51b384SJohn Hubbard /// This is the const-compatible equivalent of [`Alignable::align_up`].
2590a51b384SJohn Hubbard ///
2600a51b384SJohn Hubbard /// Returns [`None`] on overflow.
2610a51b384SJohn Hubbard ///
2620a51b384SJohn Hubbard /// # Examples
2630a51b384SJohn Hubbard ///
2640a51b384SJohn Hubbard /// ```
2650a51b384SJohn Hubbard /// use kernel::{
2660a51b384SJohn Hubbard /// ptr::{
2670a51b384SJohn Hubbard /// const_align_up,
2680a51b384SJohn Hubbard /// Alignment, //
2690a51b384SJohn Hubbard /// },
2700a51b384SJohn Hubbard /// sizes::SZ_4K, //
2710a51b384SJohn Hubbard /// };
2720a51b384SJohn Hubbard ///
2730a51b384SJohn Hubbard /// assert_eq!(const_align_up(0x4f, Alignment::new::<16>()), Some(0x50));
2740a51b384SJohn Hubbard /// assert_eq!(const_align_up(0x40, Alignment::new::<16>()), Some(0x40));
2750a51b384SJohn Hubbard /// assert_eq!(const_align_up(1, Alignment::new::<SZ_4K>()), Some(SZ_4K));
2760a51b384SJohn Hubbard /// ```
2770a51b384SJohn Hubbard #[inline(always)]
const_align_up(value: usize, align: Alignment) -> Option<usize>2780a51b384SJohn Hubbard pub const fn const_align_up(value: usize, align: Alignment) -> Option<usize> {
2790a51b384SJohn Hubbard match value.checked_add(align.as_usize() - 1) {
2800a51b384SJohn Hubbard Some(v) => Some(v & align.mask()),
2810a51b384SJohn Hubbard None => None,
2820a51b384SJohn Hubbard }
2830a51b384SJohn Hubbard }
284