1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Commonly used sizes. 4 //! 5 //! C headers: [`include/linux/sizes.h`](srctree/include/linux/sizes.h). 6 //! 7 //! The top-level `SZ_*` constants are [`usize`]-typed, for use in kernel page 8 //! arithmetic and similar CPU-side work. 9 //! 10 //! The [`SizeConstants`] trait provides the same constants as associated constants 11 //! on [`u32`], [`u64`], and [`usize`], for use in device address spaces where 12 //! the address width depends on the hardware. Device drivers frequently need 13 //! these constants as [`u64`] (or [`u32`]) rather than [`usize`], because 14 //! device address spaces are sized independently of the CPU pointer width. 15 //! 16 //! The trait is also implemented for [`Alignment`], providing each size as a 17 //! compile-time validated alignment. 18 //! 19 //! [`Alignment`]: crate::ptr::Alignment 20 //! 21 //! # Examples 22 //! 23 //! ``` 24 //! use kernel::{ 25 //! page::PAGE_SIZE, 26 //! sizes::{ 27 //! SizeConstants, 28 //! SZ_1M, // 29 //! }, // 30 //! }; 31 //! 32 //! // Module-level constants continue to work without a type qualifier. 33 //! let num_pages_in_1m = SZ_1M / PAGE_SIZE; 34 //! 35 //! // Trait associated constants require a type qualifier. 36 //! let heap_size = 14 * u64::SZ_1M; 37 //! let small = u32::SZ_4K; 38 //! ``` 39 40 macro_rules! define_sizes { 41 ($($type:ty),* $(,)?) => { 42 define_sizes!(@internal [$($type),*] 43 /// `0x0000_0001`. 44 SZ_1, 45 /// `0x0000_0002`. 46 SZ_2, 47 /// `0x0000_0004`. 48 SZ_4, 49 /// `0x0000_0008`. 50 SZ_8, 51 /// `0x0000_0010`. 52 SZ_16, 53 /// `0x0000_0020`. 54 SZ_32, 55 /// `0x0000_0040`. 56 SZ_64, 57 /// `0x0000_0080`. 58 SZ_128, 59 /// `0x0000_0100`. 60 SZ_256, 61 /// `0x0000_0200`. 62 SZ_512, 63 /// `0x0000_0400`. 64 SZ_1K, 65 /// `0x0000_0800`. 66 SZ_2K, 67 /// `0x0000_1000`. 68 SZ_4K, 69 /// `0x0000_2000`. 70 SZ_8K, 71 /// `0x0000_4000`. 72 SZ_16K, 73 /// `0x0000_8000`. 74 SZ_32K, 75 /// `0x0001_0000`. 76 SZ_64K, 77 /// `0x0002_0000`. 78 SZ_128K, 79 /// `0x0004_0000`. 80 SZ_256K, 81 /// `0x0008_0000`. 82 SZ_512K, 83 /// `0x0010_0000`. 84 SZ_1M, 85 /// `0x0020_0000`. 86 SZ_2M, 87 /// `0x0040_0000`. 88 SZ_4M, 89 /// `0x0080_0000`. 90 SZ_8M, 91 /// `0x0100_0000`. 92 SZ_16M, 93 /// `0x0200_0000`. 94 SZ_32M, 95 /// `0x0400_0000`. 96 SZ_64M, 97 /// `0x0800_0000`. 98 SZ_128M, 99 /// `0x1000_0000`. 100 SZ_256M, 101 /// `0x2000_0000`. 102 SZ_512M, 103 /// `0x4000_0000`. 104 SZ_1G, 105 /// `0x8000_0000`. 106 SZ_2G, 107 ); 108 }; 109 110 (@internal [$($type:ty),*] $($names_and_metas:tt)*) => { 111 define_sizes!(@consts_and_trait $($names_and_metas)*); 112 define_sizes!(@impls [$($type),*] $($names_and_metas)*); 113 define_sizes!(@impl_alignment $($names_and_metas)*); 114 }; 115 116 (@consts_and_trait $($(#[$meta:meta])* $name:ident,)*) => { 117 $( 118 $(#[$meta])* 119 pub const $name: usize = bindings::$name as usize; 120 )* 121 122 /// Size constants for device address spaces. 123 /// 124 /// Implemented for [`u32`], [`u64`], and [`usize`] so drivers can 125 /// choose the width that matches their hardware. All `SZ_*` values fit 126 /// in a [`u32`], so all implementations are lossless. 127 /// 128 /// Also implemented for [`Alignment`], providing each size as a 129 /// compile-time validated alignment. 130 /// 131 /// [`Alignment`]: crate::ptr::Alignment 132 /// 133 /// # Examples 134 /// 135 /// ``` 136 /// use kernel::{ 137 /// ptr::Alignment, 138 /// sizes::SizeConstants, // 139 /// }; 140 /// 141 /// let gpu_heap = 14 * u64::SZ_1M; 142 /// let mmio_window = u32::SZ_16M; 143 /// let page_align = Alignment::SZ_4K; 144 /// ``` 145 pub trait SizeConstants { 146 $( 147 $(#[$meta])* 148 const $name: Self; 149 )* 150 } 151 }; 152 153 (@impls [] $($(#[$meta:meta])* $name:ident,)*) => {}; 154 155 (@impl_alignment $($(#[$meta:meta])* $name:ident,)*) => { 156 impl SizeConstants for crate::ptr::Alignment { 157 $( 158 $(#[$meta])* 159 // A non-power-of-two constant will fail the build here if used. 160 const $name: Self = crate::ptr::Alignment::new::<{ self::$name }>(); 161 )* 162 } 163 }; 164 165 (@impls [$first:ty $(, $rest:ty)*] $($(#[$meta:meta])* $name:ident,)*) => { 166 impl SizeConstants for $first { 167 $( 168 const $name: Self = { 169 assert!((self::$name as u128) <= (<$first>::MAX as u128)); 170 self::$name as $first 171 }; 172 )* 173 } 174 175 define_sizes!(@impls [$($rest),*] $($(#[$meta])* $name,)*); 176 }; 177 } 178 179 define_sizes!(u32, u64, usize); 180