1b7b8b4ccSAlexandre Courbot // SPDX-License-Identifier: GPL-2.0 2b7b8b4ccSAlexandre Courbot 3b7b8b4ccSAlexandre Courbot //! Support for defining bitfields as Rust structures. 4b7b8b4ccSAlexandre Courbot //! 5b7b8b4ccSAlexandre Courbot //! The [`bitfield!`](kernel::bitfield!) macro declares integer types that are split into distinct 6b7b8b4ccSAlexandre Courbot //! bit fields of arbitrary length. Each field is typed using [`Bounded`](kernel::num::Bounded) to 7b7b8b4ccSAlexandre Courbot //! ensure values are properly validated and to avoid implicit data loss. 8b7b8b4ccSAlexandre Courbot //! 9b7b8b4ccSAlexandre Courbot //! # Example 10b7b8b4ccSAlexandre Courbot //! 11b7b8b4ccSAlexandre Courbot //! ```rust 12b7b8b4ccSAlexandre Courbot //! use kernel::bitfield; 13b7b8b4ccSAlexandre Courbot //! use kernel::num::Bounded; 14b7b8b4ccSAlexandre Courbot //! 15b7b8b4ccSAlexandre Courbot //! bitfield! { 16b7b8b4ccSAlexandre Courbot //! pub struct Rgb(u16) { 17b7b8b4ccSAlexandre Courbot //! 15:11 blue; 18b7b8b4ccSAlexandre Courbot //! 10:5 green; 19b7b8b4ccSAlexandre Courbot //! 4:0 red; 20b7b8b4ccSAlexandre Courbot //! } 21b7b8b4ccSAlexandre Courbot //! } 22b7b8b4ccSAlexandre Courbot //! 23b7b8b4ccSAlexandre Courbot //! // Valid value for the `blue` field. 24b7b8b4ccSAlexandre Courbot //! let blue = Bounded::<u16, 5>::new::<0x18>(); 25b7b8b4ccSAlexandre Courbot //! 26b7b8b4ccSAlexandre Courbot //! // Setters can be chained. Values ranges are checked at compile-time. 27b7b8b4ccSAlexandre Courbot //! let color = Rgb::zeroed() 28b7b8b4ccSAlexandre Courbot //! // Compile-time bounds check of constant value. 29b7b8b4ccSAlexandre Courbot //! .with_const_red::<0x10>() 30b7b8b4ccSAlexandre Courbot //! .with_const_green::<0x1f>() 31b7b8b4ccSAlexandre Courbot //! // A `Bounded` can also be passed. 32b7b8b4ccSAlexandre Courbot //! .with_blue(blue); 33b7b8b4ccSAlexandre Courbot //! 34b7b8b4ccSAlexandre Courbot //! assert_eq!(color.red(), 0x10); 35b7b8b4ccSAlexandre Courbot //! assert_eq!(color.green(), 0x1f); 36b7b8b4ccSAlexandre Courbot //! assert_eq!(color.blue(), 0x18); 37b7b8b4ccSAlexandre Courbot //! assert_eq!( 38b7b8b4ccSAlexandre Courbot //! color.into_raw(), 39b7b8b4ccSAlexandre Courbot //! (0x18 << Rgb::BLUE_SHIFT) + (0x1f << Rgb::GREEN_SHIFT) + 0x10, 40b7b8b4ccSAlexandre Courbot //! ); 41b7b8b4ccSAlexandre Courbot //! 42b7b8b4ccSAlexandre Courbot //! // Convert to/from the backing storage type. 43b7b8b4ccSAlexandre Courbot //! let raw: u16 = color.into(); 44b7b8b4ccSAlexandre Courbot //! assert_eq!(Rgb::from(raw), color); 45b7b8b4ccSAlexandre Courbot //! ``` 46b7b8b4ccSAlexandre Courbot //! 47b7b8b4ccSAlexandre Courbot //! # Syntax 48b7b8b4ccSAlexandre Courbot //! 49b7b8b4ccSAlexandre Courbot //! ```text 50b7b8b4ccSAlexandre Courbot //! bitfield! { 51b7b8b4ccSAlexandre Courbot //! #[attributes] 52b7b8b4ccSAlexandre Courbot //! // Documentation for `Name`. 53b7b8b4ccSAlexandre Courbot //! pub struct Name(storage_type) { 54b7b8b4ccSAlexandre Courbot //! // `field_1` documentation. 55b7b8b4ccSAlexandre Courbot //! hi:lo field_1; 56b7b8b4ccSAlexandre Courbot //! // `field_2` documentation. 57b7b8b4ccSAlexandre Courbot //! hi:lo field_2 => ConvertedType; 58b7b8b4ccSAlexandre Courbot //! // `field_3` documentation. 59b7b8b4ccSAlexandre Courbot //! hi:lo field_3 ?=> ConvertedType; 60b7b8b4ccSAlexandre Courbot //! ... 61b7b8b4ccSAlexandre Courbot //! } 62b7b8b4ccSAlexandre Courbot //! } 63b7b8b4ccSAlexandre Courbot //! ``` 64b7b8b4ccSAlexandre Courbot //! 65b7b8b4ccSAlexandre Courbot //! - `storage_type`: The underlying unsigned integer type ([`u8`], [`u16`], [`u32`], [`u64`]). 66b7b8b4ccSAlexandre Courbot //! Signed integer storage types are not supported. 67b7b8b4ccSAlexandre Courbot //! - `hi:lo`: Bit range (inclusive), where `hi >= lo`. 68b7b8b4ccSAlexandre Courbot //! - `=> Type`: Optional infallible conversion (see [below](#infallible-conversion-)). 69b7b8b4ccSAlexandre Courbot //! - `?=> Type`: Optional fallible conversion (see [below](#fallible-conversion-)). 70b7b8b4ccSAlexandre Courbot //! - Documentation strings and attributes are optional. 71b7b8b4ccSAlexandre Courbot //! 72b7b8b4ccSAlexandre Courbot //! # Generated code 73b7b8b4ccSAlexandre Courbot //! 74b7b8b4ccSAlexandre Courbot //! Each field is internally represented as a [`Bounded`] parameterized by its bit width. Field 75b7b8b4ccSAlexandre Courbot //! values can either be set/retrieved directly, or converted from/to another type. 76b7b8b4ccSAlexandre Courbot //! 77b7b8b4ccSAlexandre Courbot //! The use of [`Bounded`] for each field enforces bounds-checking (at build time or runtime) of 78b7b8b4ccSAlexandre Courbot //! every value assigned to a field. This ensures that data is never accidentally truncated. 79b7b8b4ccSAlexandre Courbot //! 80b7b8b4ccSAlexandre Courbot //! The macro generates the bitfield type, [`From`] and [`Into`] implementations for its storage 81b7b8b4ccSAlexandre Courbot //! type, as well as [`Debug`] and [`Zeroable`](pin_init::Zeroable) implementations. 82b7b8b4ccSAlexandre Courbot //! 83b7b8b4ccSAlexandre Courbot //! For each field, it also generates: 84b7b8b4ccSAlexandre Courbot //! 85b7b8b4ccSAlexandre Courbot //! - `field()`: Getter method for the field value. 86b7b8b4ccSAlexandre Courbot //! - `with_field(value)`: Infallible setter; the argument type must fit within the field's width. 87b7b8b4ccSAlexandre Courbot //! - `with_const_field::<VALUE>()`: `const` setter; the value is validated at compile time. 88b7b8b4ccSAlexandre Courbot //! Usually shorter to use than `with_field` for constant values as it doesn't require 89b7b8b4ccSAlexandre Courbot //! constructing a [`Bounded`]. 90b7b8b4ccSAlexandre Courbot //! - `try_with_field(value)`: Fallible setter. Returns an error if the value is out of range. 91b7b8b4ccSAlexandre Courbot //! - `FIELD_MASK`, `FIELD_SHIFT`, `FIELD_RANGE`: Constants for manual bit manipulation. 92b7b8b4ccSAlexandre Courbot //! 93b7b8b4ccSAlexandre Courbot //! # Reserved names for field identifiers 94b7b8b4ccSAlexandre Courbot //! 95b7b8b4ccSAlexandre Courbot //! Field identifiers are used to generate methods and associated constants on the bitfield type. 96b7b8b4ccSAlexandre Courbot //! For a field named `field`, the macro may generate methods named `field`, `with_field`, 97b7b8b4ccSAlexandre Courbot //! `with_const_field`, `try_with_field`, `__field` and `__with_field`, as well as constants named 98b7b8b4ccSAlexandre Courbot //! `FIELD_MASK`, `FIELD_SHIFT` and `FIELD_RANGE`. 99b7b8b4ccSAlexandre Courbot //! 100b7b8b4ccSAlexandre Courbot //! Therefore, field identifiers must not use names that would collide with generated items for 101b7b8b4ccSAlexandre Courbot //! any field in the same bitfield. The following prefixes are thus reserved for field identifiers: 102b7b8b4ccSAlexandre Courbot //! 103b7b8b4ccSAlexandre Courbot //! - `with_` 104b7b8b4ccSAlexandre Courbot //! - `const_` 105b7b8b4ccSAlexandre Courbot //! - `try_with_` 106b7b8b4ccSAlexandre Courbot //! - `__` 107b7b8b4ccSAlexandre Courbot //! 108b7b8b4ccSAlexandre Courbot //! The field identifiers `from_raw`, `into_raw`, and `into` are also reserved. 109b7b8b4ccSAlexandre Courbot //! 110b7b8b4ccSAlexandre Courbot //! In addition, field identifiers should follow Rust `snake_case` conventions, since the associated 111b7b8b4ccSAlexandre Courbot //! constants are generated by uppercasing the field name. 112b7b8b4ccSAlexandre Courbot //! 113b7b8b4ccSAlexandre Courbot //! # Implicit conversions 114b7b8b4ccSAlexandre Courbot //! 115b7b8b4ccSAlexandre Courbot //! Types that fit entirely within a field's bit width can be used directly with setters. For 116b7b8b4ccSAlexandre Courbot //! example, [`bool`] works with single-bit fields, and [`u8`] works with 8-bit fields: 117b7b8b4ccSAlexandre Courbot //! 118b7b8b4ccSAlexandre Courbot //! ```rust 119b7b8b4ccSAlexandre Courbot //! use kernel::bitfield; 120b7b8b4ccSAlexandre Courbot //! 121b7b8b4ccSAlexandre Courbot //! bitfield! { 122b7b8b4ccSAlexandre Courbot //! pub struct Flags(u32) { 123b7b8b4ccSAlexandre Courbot //! 15:8 byte_field; 124b7b8b4ccSAlexandre Courbot //! 0:0 flag; 125b7b8b4ccSAlexandre Courbot //! } 126b7b8b4ccSAlexandre Courbot //! } 127b7b8b4ccSAlexandre Courbot //! 128b7b8b4ccSAlexandre Courbot //! let flags = Flags::zeroed() 129b7b8b4ccSAlexandre Courbot //! .with_byte_field(0x42_u8) 130b7b8b4ccSAlexandre Courbot //! .with_flag(true); 131b7b8b4ccSAlexandre Courbot //! 132b7b8b4ccSAlexandre Courbot //! assert_eq!(flags.into_raw(), (0x42 << Flags::BYTE_FIELD_SHIFT) | 1); 133b7b8b4ccSAlexandre Courbot //! ``` 134b7b8b4ccSAlexandre Courbot //! 135b7b8b4ccSAlexandre Courbot //! # Runtime bounds checking 136b7b8b4ccSAlexandre Courbot //! 137b7b8b4ccSAlexandre Courbot //! When a value is not known at compile time, use `try_with_field()` to check bounds at runtime: 138b7b8b4ccSAlexandre Courbot //! 139b7b8b4ccSAlexandre Courbot //! ```rust 140b7b8b4ccSAlexandre Courbot //! use kernel::bitfield; 141b7b8b4ccSAlexandre Courbot //! 142b7b8b4ccSAlexandre Courbot //! bitfield! { 143b7b8b4ccSAlexandre Courbot //! pub struct Config(u8) { 144b7b8b4ccSAlexandre Courbot //! 3:0 nibble; 145b7b8b4ccSAlexandre Courbot //! } 146b7b8b4ccSAlexandre Courbot //! } 147b7b8b4ccSAlexandre Courbot //! 148b7b8b4ccSAlexandre Courbot //! fn set_nibble(config: Config, value: u8) -> Result<Config, Error> { 149b7b8b4ccSAlexandre Courbot //! // Returns `EOVERFLOW` if `value > 0xf`. 150b7b8b4ccSAlexandre Courbot //! config.try_with_nibble(value) 151b7b8b4ccSAlexandre Courbot //! } 152b7b8b4ccSAlexandre Courbot //! # Ok::<(), Error>(()) 153b7b8b4ccSAlexandre Courbot //! ``` 154b7b8b4ccSAlexandre Courbot //! 155b7b8b4ccSAlexandre Courbot //! # Type conversion 156b7b8b4ccSAlexandre Courbot //! 157b7b8b4ccSAlexandre Courbot //! Fields can be automatically converted to/from a custom type using `=>` (infallible) or `?=>` 158b7b8b4ccSAlexandre Courbot //! (fallible). The custom type must implement the appropriate [`From`] or [`TryFrom`] traits with 159b7b8b4ccSAlexandre Courbot //! [`Bounded`]. 160b7b8b4ccSAlexandre Courbot //! 161b7b8b4ccSAlexandre Courbot //! ## Infallible conversion (`=>`) 162b7b8b4ccSAlexandre Courbot //! 163b7b8b4ccSAlexandre Courbot //! Use this when all possible bit patterns of a field map to valid values: 164b7b8b4ccSAlexandre Courbot //! 165b7b8b4ccSAlexandre Courbot //! ```rust 166b7b8b4ccSAlexandre Courbot //! use kernel::bitfield; 167b7b8b4ccSAlexandre Courbot //! use kernel::num::Bounded; 168b7b8b4ccSAlexandre Courbot //! 169b7b8b4ccSAlexandre Courbot //! #[derive(Debug, Clone, Copy, PartialEq)] 170b7b8b4ccSAlexandre Courbot //! enum Power { 171b7b8b4ccSAlexandre Courbot //! Off, 172b7b8b4ccSAlexandre Courbot //! On, 173b7b8b4ccSAlexandre Courbot //! } 174b7b8b4ccSAlexandre Courbot //! 175b7b8b4ccSAlexandre Courbot //! impl From<Bounded<u32, 1>> for Power { 176b7b8b4ccSAlexandre Courbot //! fn from(v: Bounded<u32, 1>) -> Self { 177b7b8b4ccSAlexandre Courbot //! match *v { 178b7b8b4ccSAlexandre Courbot //! 0 => Power::Off, 179b7b8b4ccSAlexandre Courbot //! _ => Power::On, 180b7b8b4ccSAlexandre Courbot //! } 181b7b8b4ccSAlexandre Courbot //! } 182b7b8b4ccSAlexandre Courbot //! } 183b7b8b4ccSAlexandre Courbot //! 184b7b8b4ccSAlexandre Courbot //! impl From<Power> for Bounded<u32, 1> { 185b7b8b4ccSAlexandre Courbot //! fn from(p: Power) -> Self { 186b7b8b4ccSAlexandre Courbot //! (p as u32 != 0).into() 187b7b8b4ccSAlexandre Courbot //! } 188b7b8b4ccSAlexandre Courbot //! } 189b7b8b4ccSAlexandre Courbot //! 190b7b8b4ccSAlexandre Courbot //! bitfield! { 191b7b8b4ccSAlexandre Courbot //! pub struct Control(u32) { 192b7b8b4ccSAlexandre Courbot //! 0:0 power => Power; 193b7b8b4ccSAlexandre Courbot //! } 194b7b8b4ccSAlexandre Courbot //! } 195b7b8b4ccSAlexandre Courbot //! 196b7b8b4ccSAlexandre Courbot //! let ctrl = Control::zeroed().with_power(Power::On); 197b7b8b4ccSAlexandre Courbot //! assert_eq!(ctrl.power(), Power::On); 198b7b8b4ccSAlexandre Courbot //! ``` 199b7b8b4ccSAlexandre Courbot //! 200b7b8b4ccSAlexandre Courbot //! ## Fallible conversion (`?=>`) 201b7b8b4ccSAlexandre Courbot //! 202b7b8b4ccSAlexandre Courbot //! Use this when some bit patterns of a field are invalid. The getter returns a [`Result`]: 203b7b8b4ccSAlexandre Courbot //! 204b7b8b4ccSAlexandre Courbot //! ```rust 205b7b8b4ccSAlexandre Courbot //! use kernel::bitfield; 206b7b8b4ccSAlexandre Courbot //! use kernel::num::Bounded; 207b7b8b4ccSAlexandre Courbot //! 208b7b8b4ccSAlexandre Courbot //! #[derive(Debug, Clone, Copy, PartialEq)] 209b7b8b4ccSAlexandre Courbot //! enum Mode { 210b7b8b4ccSAlexandre Courbot //! Low = 0, 211b7b8b4ccSAlexandre Courbot //! High = 1, 212b7b8b4ccSAlexandre Courbot //! Auto = 2, 213b7b8b4ccSAlexandre Courbot //! // 3 is invalid 214b7b8b4ccSAlexandre Courbot //! } 215b7b8b4ccSAlexandre Courbot //! 216b7b8b4ccSAlexandre Courbot //! impl TryFrom<Bounded<u32, 2>> for Mode { 217b7b8b4ccSAlexandre Courbot //! type Error = u32; 218b7b8b4ccSAlexandre Courbot //! 219b7b8b4ccSAlexandre Courbot //! fn try_from(v: Bounded<u32, 2>) -> Result<Self, u32> { 220b7b8b4ccSAlexandre Courbot //! match *v { 221b7b8b4ccSAlexandre Courbot //! 0 => Ok(Mode::Low), 222b7b8b4ccSAlexandre Courbot //! 1 => Ok(Mode::High), 223b7b8b4ccSAlexandre Courbot //! 2 => Ok(Mode::Auto), 224b7b8b4ccSAlexandre Courbot //! n => Err(n), 225b7b8b4ccSAlexandre Courbot //! } 226b7b8b4ccSAlexandre Courbot //! } 227b7b8b4ccSAlexandre Courbot //! } 228b7b8b4ccSAlexandre Courbot //! 229b7b8b4ccSAlexandre Courbot //! impl From<Mode> for Bounded<u32, 2> { 230b7b8b4ccSAlexandre Courbot //! fn from(m: Mode) -> Self { 231b7b8b4ccSAlexandre Courbot //! match m { 232b7b8b4ccSAlexandre Courbot //! Mode::Low => Bounded::<u32, _>::new::<0>(), 233b7b8b4ccSAlexandre Courbot //! Mode::High => Bounded::<u32, _>::new::<1>(), 234b7b8b4ccSAlexandre Courbot //! Mode::Auto => Bounded::<u32, _>::new::<2>(), 235b7b8b4ccSAlexandre Courbot //! } 236b7b8b4ccSAlexandre Courbot //! } 237b7b8b4ccSAlexandre Courbot //! } 238b7b8b4ccSAlexandre Courbot //! 239b7b8b4ccSAlexandre Courbot //! bitfield! { 240b7b8b4ccSAlexandre Courbot //! pub struct Config(u32) { 241b7b8b4ccSAlexandre Courbot //! 1:0 mode ?=> Mode; 242b7b8b4ccSAlexandre Courbot //! } 243b7b8b4ccSAlexandre Courbot //! } 244b7b8b4ccSAlexandre Courbot //! 245b7b8b4ccSAlexandre Courbot //! let cfg = Config::zeroed().with_mode(Mode::Auto); 246b7b8b4ccSAlexandre Courbot //! assert_eq!(cfg.mode(), Ok(Mode::Auto)); 247b7b8b4ccSAlexandre Courbot //! 248b7b8b4ccSAlexandre Courbot //! // Invalid bit pattern returns an error. 249b7b8b4ccSAlexandre Courbot //! assert_eq!(Config::from(0b11).mode(), Err(3)); 250b7b8b4ccSAlexandre Courbot //! ``` 251b7b8b4ccSAlexandre Courbot //! 252b7b8b4ccSAlexandre Courbot //! # Bits outside of declared fields 253b7b8b4ccSAlexandre Courbot //! 254b7b8b4ccSAlexandre Courbot //! Bits of the storage type that are not part of any declared field are preserved by the setter 255b7b8b4ccSAlexandre Courbot //! methods, and can only be modified through `from_raw` or the [`From`] implementation from the 256b7b8b4ccSAlexandre Courbot //! storage type. 257b7b8b4ccSAlexandre Courbot //! 258b7b8b4ccSAlexandre Courbot //! ```rust 259b7b8b4ccSAlexandre Courbot //! use kernel::bitfield; 260b7b8b4ccSAlexandre Courbot //! 261b7b8b4ccSAlexandre Courbot //! bitfield! { 262b7b8b4ccSAlexandre Courbot //! pub struct Sparse(u8) { 263b7b8b4ccSAlexandre Courbot //! 7:6 high; 264b7b8b4ccSAlexandre Courbot //! // Bits 5:1 are not covered by any field. 265b7b8b4ccSAlexandre Courbot //! 0:0 low; 266b7b8b4ccSAlexandre Courbot //! } 267b7b8b4ccSAlexandre Courbot //! } 268b7b8b4ccSAlexandre Courbot //! 269b7b8b4ccSAlexandre Courbot //! // Set the gap bits via `from_raw`, then mutate the declared fields. 270b7b8b4ccSAlexandre Courbot //! let val = Sparse::from_raw(0b0010_1010) 271b7b8b4ccSAlexandre Courbot //! .with_const_high::<0b11>() 272b7b8b4ccSAlexandre Courbot //! .with_low(true); 273b7b8b4ccSAlexandre Courbot //! 274b7b8b4ccSAlexandre Courbot //! // Bits 5:1 are unchanged. 275b7b8b4ccSAlexandre Courbot //! assert_eq!(val.into_raw(), 0b1110_1011); 276b7b8b4ccSAlexandre Courbot //! ``` 277b7b8b4ccSAlexandre Courbot //! 278b7b8b4ccSAlexandre Courbot //! # Signed field values 279b7b8b4ccSAlexandre Courbot //! 280b7b8b4ccSAlexandre Courbot //! Bitfield storage types are unsigned. Since field getter methods return a [`Bounded`] of the 281b7b8b4ccSAlexandre Courbot //! storage type, fields are also unsigned by default. 282b7b8b4ccSAlexandre Courbot //! 283b7b8b4ccSAlexandre Courbot //! If a field needs to encode a signed value, use a custom conversion type with `=>` or `?=>` to 284b7b8b4ccSAlexandre Courbot //! perform the sign interpretation explicitly. 285b7b8b4ccSAlexandre Courbot //! 286b7b8b4ccSAlexandre Courbot //! [`Bounded`]: kernel::num::Bounded 287b7b8b4ccSAlexandre Courbot 288b7b8b4ccSAlexandre Courbot /// Defines a bitfield struct with bounds-checked accessors for individual bit ranges. 289b7b8b4ccSAlexandre Courbot /// 290b7b8b4ccSAlexandre Courbot /// See the [`mod@kernel::bitfield`] module for full documentation and examples. 291b7b8b4ccSAlexandre Courbot #[macro_export] 292b7b8b4ccSAlexandre Courbot macro_rules! bitfield { 293b7b8b4ccSAlexandre Courbot // Entry point defining the bitfield struct, its implementations and its field accessors. 294b7b8b4ccSAlexandre Courbot ( 295b7b8b4ccSAlexandre Courbot $(#[$attr:meta])* $vis:vis struct $name:ident($storage:ty) { $($fields:tt)* } 296b7b8b4ccSAlexandre Courbot ) => { 297b7b8b4ccSAlexandre Courbot $crate::bitfield!(@core 298b7b8b4ccSAlexandre Courbot #[allow(non_camel_case_types)] 299b7b8b4ccSAlexandre Courbot $(#[$attr])* $vis $name $storage 300b7b8b4ccSAlexandre Courbot ); 301b7b8b4ccSAlexandre Courbot $crate::bitfield!(@fields $vis $name $storage { $($fields)* }); 302b7b8b4ccSAlexandre Courbot }; 303b7b8b4ccSAlexandre Courbot 304b7b8b4ccSAlexandre Courbot // All rules below are helpers. 305b7b8b4ccSAlexandre Courbot 306b7b8b4ccSAlexandre Courbot // Defines the wrapper `$name` type and its conversions from/to the storage type. 307b7b8b4ccSAlexandre Courbot (@core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) => { 308b7b8b4ccSAlexandre Courbot $(#[$attr])* 309b7b8b4ccSAlexandre Courbot #[repr(transparent)] 310b7b8b4ccSAlexandre Courbot #[derive(Clone, Copy, PartialEq, Eq)] 311b7b8b4ccSAlexandre Courbot $vis struct $name { 312b7b8b4ccSAlexandre Courbot inner: $storage, 313b7b8b4ccSAlexandre Courbot } 314b7b8b4ccSAlexandre Courbot 315b7b8b4ccSAlexandre Courbot #[allow(dead_code)] 316b7b8b4ccSAlexandre Courbot impl $name { 317b7b8b4ccSAlexandre Courbot /// Creates a bitfield from a raw value. 318b7b8b4ccSAlexandre Courbot #[inline(always)] 319b7b8b4ccSAlexandre Courbot $vis const fn from_raw(value: $storage) -> Self { 320b7b8b4ccSAlexandre Courbot Self{ inner: value } 321b7b8b4ccSAlexandre Courbot } 322b7b8b4ccSAlexandre Courbot 323b7b8b4ccSAlexandre Courbot /// Turns this bitfield into its raw value. 324b7b8b4ccSAlexandre Courbot /// 325b7b8b4ccSAlexandre Courbot /// This is similar to the [`From`] implementation, but is shorter to invoke in 326b7b8b4ccSAlexandre Courbot /// most cases. 327b7b8b4ccSAlexandre Courbot #[inline(always)] 328b7b8b4ccSAlexandre Courbot $vis const fn into_raw(self) -> $storage { 329b7b8b4ccSAlexandre Courbot self.inner 330b7b8b4ccSAlexandre Courbot } 331b7b8b4ccSAlexandre Courbot } 332b7b8b4ccSAlexandre Courbot 333b7b8b4ccSAlexandre Courbot // SAFETY: `$storage` is `Zeroable` and `$name` is transparent. 334b7b8b4ccSAlexandre Courbot unsafe impl ::pin_init::Zeroable for $name {} 335b7b8b4ccSAlexandre Courbot 336b7b8b4ccSAlexandre Courbot impl ::core::convert::From<$name> for $storage { 337b7b8b4ccSAlexandre Courbot #[inline(always)] 338b7b8b4ccSAlexandre Courbot fn from(val: $name) -> $storage { 339b7b8b4ccSAlexandre Courbot val.into_raw() 340b7b8b4ccSAlexandre Courbot } 341b7b8b4ccSAlexandre Courbot } 342b7b8b4ccSAlexandre Courbot 343b7b8b4ccSAlexandre Courbot impl ::core::convert::From<$storage> for $name { 344b7b8b4ccSAlexandre Courbot #[inline(always)] 345b7b8b4ccSAlexandre Courbot fn from(val: $storage) -> $name { 346b7b8b4ccSAlexandre Courbot Self::from_raw(val) 347b7b8b4ccSAlexandre Courbot } 348b7b8b4ccSAlexandre Courbot } 349b7b8b4ccSAlexandre Courbot }; 350b7b8b4ccSAlexandre Courbot 351b7b8b4ccSAlexandre Courbot // Definitions requiring knowledge of individual fields: private and public field accessors, 352b7b8b4ccSAlexandre Courbot // and `Debug` implementation. 353b7b8b4ccSAlexandre Courbot (@fields $vis:vis $name:ident $storage:ty { 354b7b8b4ccSAlexandre Courbot $($(#[doc = $doc:expr])* $hi:literal:$lo:literal $field:ident 355b7b8b4ccSAlexandre Courbot $(?=> $try_into_type:ty)? 356b7b8b4ccSAlexandre Courbot $(=> $into_type:ty)? 357b7b8b4ccSAlexandre Courbot ; 358b7b8b4ccSAlexandre Courbot )* 359b7b8b4ccSAlexandre Courbot } 360b7b8b4ccSAlexandre Courbot ) => { 361b7b8b4ccSAlexandre Courbot #[allow(dead_code)] 362b7b8b4ccSAlexandre Courbot impl $name { 363b7b8b4ccSAlexandre Courbot $( 364b7b8b4ccSAlexandre Courbot $crate::bitfield!(@private_field_accessors $vis $name $storage : $hi:$lo $field); 365b7b8b4ccSAlexandre Courbot $crate::bitfield!( 366b7b8b4ccSAlexandre Courbot @public_field_accessors $(#[doc = $doc])* $vis $name $storage : $hi:$lo $field 367b7b8b4ccSAlexandre Courbot $(?=> $try_into_type)? 368b7b8b4ccSAlexandre Courbot $(=> $into_type)? 369b7b8b4ccSAlexandre Courbot ); 370b7b8b4ccSAlexandre Courbot )* 371b7b8b4ccSAlexandre Courbot } 372b7b8b4ccSAlexandre Courbot 373b7b8b4ccSAlexandre Courbot $crate::bitfield!(@debug $name { $($field;)* }); 374b7b8b4ccSAlexandre Courbot }; 375b7b8b4ccSAlexandre Courbot 376b7b8b4ccSAlexandre Courbot // Private field accessors working with the exact `Bounded` type for the field. 377b7b8b4ccSAlexandre Courbot ( 378b7b8b4ccSAlexandre Courbot @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident 379b7b8b4ccSAlexandre Courbot ) => { 380b7b8b4ccSAlexandre Courbot ::kernel::macros::paste!( 381b7b8b4ccSAlexandre Courbot $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi; 382b7b8b4ccSAlexandre Courbot $vis const [<$field:upper _MASK>]: $storage = 383b7b8b4ccSAlexandre Courbot ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1); 384b7b8b4ccSAlexandre Courbot $vis const [<$field:upper _SHIFT>]: u32 = $lo; 385b7b8b4ccSAlexandre Courbot ); 386b7b8b4ccSAlexandre Courbot 387b7b8b4ccSAlexandre Courbot ::kernel::macros::paste!( 388b7b8b4ccSAlexandre Courbot #[inline(always)] 389b7b8b4ccSAlexandre Courbot fn [<__ $field>](self) -> 390b7b8b4ccSAlexandre Courbot ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> { 391b7b8b4ccSAlexandre Courbot // Left shift to align the field's MSB with the storage MSB. 392b7b8b4ccSAlexandre Courbot const ALIGN_TOP: u32 = $storage::BITS - ($hi + 1); 393b7b8b4ccSAlexandre Courbot // Right shift to move the top-aligned field to bit 0 of the storage. 394b7b8b4ccSAlexandre Courbot const ALIGN_BOTTOM: u32 = ALIGN_TOP + $lo; 395b7b8b4ccSAlexandre Courbot 396b7b8b4ccSAlexandre Courbot // Extract the field using two shifts. `Bounded::shr` produces the correctly-sized 397b7b8b4ccSAlexandre Courbot // output type. 398b7b8b4ccSAlexandre Courbot let val = ::kernel::num::Bounded::<$storage, { $storage::BITS }>::from( 399b7b8b4ccSAlexandre Courbot self.inner << ALIGN_TOP 400b7b8b4ccSAlexandre Courbot ); 401b7b8b4ccSAlexandre Courbot val.shr::<ALIGN_BOTTOM, { $hi + 1 - $lo } >() 402b7b8b4ccSAlexandre Courbot } 403b7b8b4ccSAlexandre Courbot 404b7b8b4ccSAlexandre Courbot #[inline(always)] 405b7b8b4ccSAlexandre Courbot const fn [<__with_ $field>]( 406b7b8b4ccSAlexandre Courbot mut self, 407b7b8b4ccSAlexandre Courbot value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>, 408b7b8b4ccSAlexandre Courbot ) -> Self 409b7b8b4ccSAlexandre Courbot { 410b7b8b4ccSAlexandre Courbot const MASK: $storage = <$name>::[<$field:upper _MASK>]; 411b7b8b4ccSAlexandre Courbot const SHIFT: u32 = <$name>::[<$field:upper _SHIFT>]; 412b7b8b4ccSAlexandre Courbot 413b7b8b4ccSAlexandre Courbot let value = value.get() << SHIFT; 414b7b8b4ccSAlexandre Courbot self.inner = (self.inner & !MASK) | value; 415b7b8b4ccSAlexandre Courbot 416b7b8b4ccSAlexandre Courbot self 417b7b8b4ccSAlexandre Courbot } 418b7b8b4ccSAlexandre Courbot ); 419b7b8b4ccSAlexandre Courbot }; 420b7b8b4ccSAlexandre Courbot 421b7b8b4ccSAlexandre Courbot // Public accessors for fields infallibly (`=>`) converted to a type. 422b7b8b4ccSAlexandre Courbot ( 423b7b8b4ccSAlexandre Courbot @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : 424b7b8b4ccSAlexandre Courbot $hi:literal:$lo:literal $field:ident => $into_type:ty 425b7b8b4ccSAlexandre Courbot ) => { 426b7b8b4ccSAlexandre Courbot ::kernel::macros::paste!( 427b7b8b4ccSAlexandre Courbot 428b7b8b4ccSAlexandre Courbot $(#[doc = $doc])* 429b7b8b4ccSAlexandre Courbot #[doc = "Returns the value of this field."] 430b7b8b4ccSAlexandre Courbot #[inline(always)] 431b7b8b4ccSAlexandre Courbot $vis fn $field(self) -> $into_type 432b7b8b4ccSAlexandre Courbot { 433b7b8b4ccSAlexandre Courbot self.[<__ $field>]().into() 434b7b8b4ccSAlexandre Courbot } 435b7b8b4ccSAlexandre Courbot 436b7b8b4ccSAlexandre Courbot $(#[doc = $doc])* 437b7b8b4ccSAlexandre Courbot #[doc = "Sets this field to the given `value`."] 438b7b8b4ccSAlexandre Courbot #[inline(always)] 439b7b8b4ccSAlexandre Courbot $vis fn [<with_ $field>](self, value: $into_type) -> Self 440b7b8b4ccSAlexandre Courbot { 441b7b8b4ccSAlexandre Courbot self.[<__with_ $field>](value.into()) 442b7b8b4ccSAlexandre Courbot } 443b7b8b4ccSAlexandre Courbot 444b7b8b4ccSAlexandre Courbot ); 445b7b8b4ccSAlexandre Courbot }; 446b7b8b4ccSAlexandre Courbot 447b7b8b4ccSAlexandre Courbot // Public accessors for fields fallibly (`?=>`) converted to a type. 448b7b8b4ccSAlexandre Courbot ( 449b7b8b4ccSAlexandre Courbot @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : 450b7b8b4ccSAlexandre Courbot $hi:tt:$lo:tt $field:ident ?=> $try_into_type:ty 451b7b8b4ccSAlexandre Courbot ) => { 452b7b8b4ccSAlexandre Courbot ::kernel::macros::paste!( 453b7b8b4ccSAlexandre Courbot 454b7b8b4ccSAlexandre Courbot $(#[doc = $doc])* 455b7b8b4ccSAlexandre Courbot #[doc = "Returns the value of this field."] 456b7b8b4ccSAlexandre Courbot #[inline(always)] 457b7b8b4ccSAlexandre Courbot $vis fn $field(self) -> 458b7b8b4ccSAlexandre Courbot ::core::result::Result< 459b7b8b4ccSAlexandre Courbot $try_into_type, 460b7b8b4ccSAlexandre Courbot <$try_into_type as ::core::convert::TryFrom< 461b7b8b4ccSAlexandre Courbot ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> 462b7b8b4ccSAlexandre Courbot >>::Error 463b7b8b4ccSAlexandre Courbot > 464b7b8b4ccSAlexandre Courbot { 465b7b8b4ccSAlexandre Courbot self.[<__ $field>]().try_into() 466b7b8b4ccSAlexandre Courbot } 467b7b8b4ccSAlexandre Courbot 468b7b8b4ccSAlexandre Courbot $(#[doc = $doc])* 469b7b8b4ccSAlexandre Courbot #[doc = "Sets this field to the given `value`."] 470b7b8b4ccSAlexandre Courbot #[inline(always)] 471b7b8b4ccSAlexandre Courbot $vis fn [<with_ $field>](self, value: $try_into_type) -> Self 472b7b8b4ccSAlexandre Courbot { 473b7b8b4ccSAlexandre Courbot self.[<__with_ $field>](value.into()) 474b7b8b4ccSAlexandre Courbot } 475b7b8b4ccSAlexandre Courbot 476b7b8b4ccSAlexandre Courbot ); 477b7b8b4ccSAlexandre Courbot }; 478b7b8b4ccSAlexandre Courbot 479b7b8b4ccSAlexandre Courbot // Public accessors for fields not converted to a type. 480b7b8b4ccSAlexandre Courbot ( 481b7b8b4ccSAlexandre Courbot @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : 482b7b8b4ccSAlexandre Courbot $hi:tt:$lo:tt $field:ident 483b7b8b4ccSAlexandre Courbot ) => { 484b7b8b4ccSAlexandre Courbot ::kernel::macros::paste!( 485b7b8b4ccSAlexandre Courbot 486b7b8b4ccSAlexandre Courbot $(#[doc = $doc])* 487b7b8b4ccSAlexandre Courbot #[doc = "Returns the value of this field."] 488b7b8b4ccSAlexandre Courbot #[inline(always)] 489b7b8b4ccSAlexandre Courbot $vis fn $field(self) -> 490b7b8b4ccSAlexandre Courbot ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> 491b7b8b4ccSAlexandre Courbot { 492b7b8b4ccSAlexandre Courbot self.[<__ $field>]() 493b7b8b4ccSAlexandre Courbot } 494b7b8b4ccSAlexandre Courbot 495b7b8b4ccSAlexandre Courbot $(#[doc = $doc])* 496b7b8b4ccSAlexandre Courbot #[doc = "Sets this field to the compile-time constant `VALUE`."] 497b7b8b4ccSAlexandre Courbot #[inline(always)] 498b7b8b4ccSAlexandre Courbot $vis const fn [<with_const_ $field>]<const VALUE: $storage>(self) -> Self { 499b7b8b4ccSAlexandre Courbot self.[<__with_ $field>]( 500b7b8b4ccSAlexandre Courbot ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new::<VALUE>() 501b7b8b4ccSAlexandre Courbot ) 502b7b8b4ccSAlexandre Courbot } 503b7b8b4ccSAlexandre Courbot 504b7b8b4ccSAlexandre Courbot $(#[doc = $doc])* 505b7b8b4ccSAlexandre Courbot #[doc = "Sets this field to the given `value`."] 506b7b8b4ccSAlexandre Courbot #[inline(always)] 507b7b8b4ccSAlexandre Courbot $vis fn [<with_ $field>]<T>( 508b7b8b4ccSAlexandre Courbot self, 509b7b8b4ccSAlexandre Courbot value: T, 510b7b8b4ccSAlexandre Courbot ) -> Self 511b7b8b4ccSAlexandre Courbot where T: ::core::convert::Into<::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>>, 512b7b8b4ccSAlexandre Courbot { 513b7b8b4ccSAlexandre Courbot self.[<__with_ $field>](value.into()) 514b7b8b4ccSAlexandre Courbot } 515b7b8b4ccSAlexandre Courbot 516b7b8b4ccSAlexandre Courbot $(#[doc = $doc])* 517b7b8b4ccSAlexandre Courbot #[doc = "Tries to set this field to `value`, returning an error if it is out of range."] 518b7b8b4ccSAlexandre Courbot #[inline(always)] 519b7b8b4ccSAlexandre Courbot $vis fn [<try_with_ $field>]<T>( 520b7b8b4ccSAlexandre Courbot self, 521b7b8b4ccSAlexandre Courbot value: T, 522b7b8b4ccSAlexandre Courbot ) -> ::kernel::error::Result<Self> 523b7b8b4ccSAlexandre Courbot where T: ::kernel::num::TryIntoBounded<$storage, { $hi + 1 - $lo }>, 524b7b8b4ccSAlexandre Courbot { 525b7b8b4ccSAlexandre Courbot Ok( 526b7b8b4ccSAlexandre Courbot self.[<__with_ $field>]( 527b7b8b4ccSAlexandre Courbot value.try_into_bounded().ok_or(::kernel::error::code::EOVERFLOW)? 528b7b8b4ccSAlexandre Courbot ) 529b7b8b4ccSAlexandre Courbot ) 530b7b8b4ccSAlexandre Courbot } 531b7b8b4ccSAlexandre Courbot 532b7b8b4ccSAlexandre Courbot ); 533b7b8b4ccSAlexandre Courbot }; 534b7b8b4ccSAlexandre Courbot 535b7b8b4ccSAlexandre Courbot // `Debug` implementation. 536b7b8b4ccSAlexandre Courbot (@debug $name:ident { $($field:ident;)* }) => { 537b7b8b4ccSAlexandre Courbot impl ::kernel::fmt::Debug for $name { 538*f09d2312SGary Guo #[inline] 539b7b8b4ccSAlexandre Courbot fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result { 540b7b8b4ccSAlexandre Courbot f.debug_struct(stringify!($name)) 541b7b8b4ccSAlexandre Courbot .field("<raw>", &::kernel::prelude::fmt!("{:#x}", self.inner)) 542b7b8b4ccSAlexandre Courbot $( 543b7b8b4ccSAlexandre Courbot .field(stringify!($field), &self.$field()) 544b7b8b4ccSAlexandre Courbot )* 545b7b8b4ccSAlexandre Courbot .finish() 546b7b8b4ccSAlexandre Courbot } 547b7b8b4ccSAlexandre Courbot } 548b7b8b4ccSAlexandre Courbot }; 549b7b8b4ccSAlexandre Courbot } 5507f502747SJoel Fernandes 5517f502747SJoel Fernandes #[cfg(CONFIG_RUST_BITFIELD_KUNIT_TEST)] 5527f502747SJoel Fernandes #[::kernel::macros::kunit_tests(rust_kernel_bitfield)] 5537f502747SJoel Fernandes mod tests { 5547f502747SJoel Fernandes use core::convert::TryFrom; 5557f502747SJoel Fernandes 5567f502747SJoel Fernandes use pin_init::Zeroable; 5577f502747SJoel Fernandes 5587f502747SJoel Fernandes use kernel::num::Bounded; 5597f502747SJoel Fernandes 5607f502747SJoel Fernandes // Enum types for testing `=>` and `?=>` conversions. 5617f502747SJoel Fernandes 5627f502747SJoel Fernandes #[derive(Debug, Clone, Copy, PartialEq)] 5637f502747SJoel Fernandes enum MemoryType { 5647f502747SJoel Fernandes Unmapped = 0, 5657f502747SJoel Fernandes Normal = 1, 5667f502747SJoel Fernandes Device = 2, 5677f502747SJoel Fernandes Reserved = 3, 5687f502747SJoel Fernandes } 5697f502747SJoel Fernandes 5707f502747SJoel Fernandes impl TryFrom<Bounded<u64, 4>> for MemoryType { 5717f502747SJoel Fernandes type Error = u64; try_from(value: Bounded<u64, 4>) -> Result<Self, Self::Error>5727f502747SJoel Fernandes fn try_from(value: Bounded<u64, 4>) -> Result<Self, Self::Error> { 5737f502747SJoel Fernandes match value.get() { 5747f502747SJoel Fernandes 0 => Ok(MemoryType::Unmapped), 5757f502747SJoel Fernandes 1 => Ok(MemoryType::Normal), 5767f502747SJoel Fernandes 2 => Ok(MemoryType::Device), 5777f502747SJoel Fernandes 3 => Ok(MemoryType::Reserved), 5787f502747SJoel Fernandes _ => Err(value.get()), 5797f502747SJoel Fernandes } 5807f502747SJoel Fernandes } 5817f502747SJoel Fernandes } 5827f502747SJoel Fernandes 5837f502747SJoel Fernandes impl From<MemoryType> for Bounded<u64, 4> { 5847f502747SJoel Fernandes #[inline(always)] from(mt: MemoryType) -> Bounded<u64, 4>5857f502747SJoel Fernandes fn from(mt: MemoryType) -> Bounded<u64, 4> { 5867f502747SJoel Fernandes Bounded::from_expr(mt as u64) 5877f502747SJoel Fernandes } 5887f502747SJoel Fernandes } 5897f502747SJoel Fernandes 5907f502747SJoel Fernandes #[derive(Debug, Clone, Copy, PartialEq)] 5917f502747SJoel Fernandes enum Priority { 5927f502747SJoel Fernandes Low = 0, 5937f502747SJoel Fernandes Medium = 1, 5947f502747SJoel Fernandes High = 2, 5957f502747SJoel Fernandes Critical = 3, 5967f502747SJoel Fernandes } 5977f502747SJoel Fernandes 5987f502747SJoel Fernandes impl From<Bounded<u16, 2>> for Priority { from(value: Bounded<u16, 2>) -> Self5997f502747SJoel Fernandes fn from(value: Bounded<u16, 2>) -> Self { 6007f502747SJoel Fernandes match value & 0x3 { 6017f502747SJoel Fernandes 0 => Priority::Low, 6027f502747SJoel Fernandes 1 => Priority::Medium, 6037f502747SJoel Fernandes 2 => Priority::High, 6047f502747SJoel Fernandes _ => Priority::Critical, 6057f502747SJoel Fernandes } 6067f502747SJoel Fernandes } 6077f502747SJoel Fernandes } 6087f502747SJoel Fernandes 6097f502747SJoel Fernandes impl From<Priority> for Bounded<u16, 2> { 6107f502747SJoel Fernandes #[inline(always)] from(p: Priority) -> Bounded<u16, 2>6117f502747SJoel Fernandes fn from(p: Priority) -> Bounded<u16, 2> { 6127f502747SJoel Fernandes Bounded::from_expr(p as u16) 6137f502747SJoel Fernandes } 6147f502747SJoel Fernandes } 6157f502747SJoel Fernandes 6167f502747SJoel Fernandes bitfield! { 6177f502747SJoel Fernandes struct TestU64(u64) { 6187f502747SJoel Fernandes 63:63 field_63; 6197f502747SJoel Fernandes 61:52 field_61_52; 6207f502747SJoel Fernandes 51:16 field_51_16; 6217f502747SJoel Fernandes 15:12 field_15_12 ?=> MemoryType; 6227f502747SJoel Fernandes 11:9 field_11_9; 6237f502747SJoel Fernandes 1:1 field_1; 6247f502747SJoel Fernandes 0:0 field_0; 6257f502747SJoel Fernandes } 6267f502747SJoel Fernandes } 6277f502747SJoel Fernandes 6287f502747SJoel Fernandes bitfield! { 6297f502747SJoel Fernandes struct TestU16(u16) { 6307f502747SJoel Fernandes 15:8 field_15_8; 6317f502747SJoel Fernandes 7:4 field_7_4; // Partial overlap with `field_5_4`. 6327f502747SJoel Fernandes 5:4 field_5_4 => Priority; 6337f502747SJoel Fernandes 3:1 field_3_1; 6347f502747SJoel Fernandes 0:0 field_0; 6357f502747SJoel Fernandes } 6367f502747SJoel Fernandes } 6377f502747SJoel Fernandes 6387f502747SJoel Fernandes bitfield! { 6397f502747SJoel Fernandes struct TestU8(u8) { 6407f502747SJoel Fernandes 7:0 field_7_0; // Full byte overlap. 6417f502747SJoel Fernandes 7:4 field_7_4; 6427f502747SJoel Fernandes 3:2 field_3_2; 6437f502747SJoel Fernandes 1:1 field_1; 6447f502747SJoel Fernandes 0:0 field_0; 6457f502747SJoel Fernandes } 6467f502747SJoel Fernandes } 6477f502747SJoel Fernandes 6487f502747SJoel Fernandes // Single and multi-bit fields basic access. 6497f502747SJoel Fernandes #[test] test_basic_access()6507f502747SJoel Fernandes fn test_basic_access() { 6517f502747SJoel Fernandes // `TestU64`. 6527f502747SJoel Fernandes let mut val = TestU64::zeroed(); 6537f502747SJoel Fernandes assert_eq!(val.into_raw(), 0x0); 6547f502747SJoel Fernandes 6557f502747SJoel Fernandes val = val.with_field_0(true); 6567f502747SJoel Fernandes assert!(val.field_0().into_bool()); 6577f502747SJoel Fernandes assert_eq!(val.into_raw(), 0x1); 6587f502747SJoel Fernandes 6597f502747SJoel Fernandes val = val.with_field_1(true); 6607f502747SJoel Fernandes assert!(val.field_1().into_bool()); 6617f502747SJoel Fernandes val = val.with_field_1(false); 6627f502747SJoel Fernandes assert!(!val.field_1().into_bool()); 6637f502747SJoel Fernandes assert_eq!(val.into_raw(), 0x1); 6647f502747SJoel Fernandes 6657f502747SJoel Fernandes val = val.with_const_field_11_9::<0x5>(); 6667f502747SJoel Fernandes assert_eq!(val.field_11_9(), 0x5); 6677f502747SJoel Fernandes assert_eq!(val.into_raw(), 0xA01); 6687f502747SJoel Fernandes 6697f502747SJoel Fernandes val = val.with_const_field_51_16::<0x123456>(); 6707f502747SJoel Fernandes assert_eq!(val.field_51_16(), 0x123456); 6717f502747SJoel Fernandes assert_eq!(val.into_raw(), 0x0012_3456_0A01); 6727f502747SJoel Fernandes 6737f502747SJoel Fernandes const MAX_FIELD_51_16: u64 = ::kernel::bits::genmask_u64(0..=35); 6747f502747SJoel Fernandes val = val.with_const_field_51_16::<{ MAX_FIELD_51_16 }>(); 6757f502747SJoel Fernandes assert_eq!(val.field_51_16(), MAX_FIELD_51_16); 6767f502747SJoel Fernandes 6777f502747SJoel Fernandes val = val.with_const_field_61_52::<0x3FF>(); 6787f502747SJoel Fernandes assert_eq!(val.field_61_52(), 0x3FF); 6797f502747SJoel Fernandes 6807f502747SJoel Fernandes val = val.with_field_63(true); 6817f502747SJoel Fernandes assert!(val.field_63().into_bool()); 6827f502747SJoel Fernandes 6837f502747SJoel Fernandes // `TestU16`. 6847f502747SJoel Fernandes let mut val = TestU16::zeroed(); 6857f502747SJoel Fernandes assert_eq!(val.into_raw(), 0x0); 6867f502747SJoel Fernandes 6877f502747SJoel Fernandes val = val.with_field_0(true); 6887f502747SJoel Fernandes assert!(val.field_0().into_bool()); 6897f502747SJoel Fernandes assert_eq!(val.into_raw(), 0x1); 6907f502747SJoel Fernandes 6917f502747SJoel Fernandes val = val.with_const_field_3_1::<0x5>(); 6927f502747SJoel Fernandes assert_eq!(val.field_3_1(), 0x5); 6937f502747SJoel Fernandes assert_eq!(val.into_raw(), 0xB); 6947f502747SJoel Fernandes 6957f502747SJoel Fernandes val = val.with_const_field_7_4::<0xA>(); 6967f502747SJoel Fernandes assert_eq!(val.field_7_4(), 0xA); 6977f502747SJoel Fernandes assert_eq!(val.into_raw(), 0xAB); 6987f502747SJoel Fernandes 6997f502747SJoel Fernandes val = val.with_const_field_15_8::<0x42>(); 7007f502747SJoel Fernandes assert_eq!(val.field_15_8(), 0x42); 7017f502747SJoel Fernandes assert_eq!(val.into_raw(), 0x42AB); 7027f502747SJoel Fernandes 7037f502747SJoel Fernandes // `TestU8`. 7047f502747SJoel Fernandes let mut val = TestU8::zeroed(); 7057f502747SJoel Fernandes assert_eq!(val.into_raw(), 0x0); 7067f502747SJoel Fernandes 7077f502747SJoel Fernandes val = val.with_field_0(true); 7087f502747SJoel Fernandes assert!(val.field_0().into_bool()); 7097f502747SJoel Fernandes assert_eq!(val.into_raw(), 0x1); 7107f502747SJoel Fernandes 7117f502747SJoel Fernandes val = val.with_field_1(true); 7127f502747SJoel Fernandes assert!(val.field_1().into_bool()); 7137f502747SJoel Fernandes assert_eq!(val.into_raw(), 0x3); 7147f502747SJoel Fernandes 7157f502747SJoel Fernandes val = val.with_const_field_3_2::<0x3>(); 7167f502747SJoel Fernandes assert_eq!(val.field_3_2(), 0x3); 7177f502747SJoel Fernandes assert_eq!(val.into_raw(), 0xF); 7187f502747SJoel Fernandes 7197f502747SJoel Fernandes val = val.with_const_field_7_4::<0xA>(); 7207f502747SJoel Fernandes assert_eq!(val.field_7_4(), 0xA); 7217f502747SJoel Fernandes assert_eq!(val.into_raw(), 0xAF); 7227f502747SJoel Fernandes } 7237f502747SJoel Fernandes 7247f502747SJoel Fernandes // `=>` infallible conversion. 7257f502747SJoel Fernandes #[test] test_infallible_conversion()7267f502747SJoel Fernandes fn test_infallible_conversion() { 7277f502747SJoel Fernandes let mut val = TestU16::zeroed(); 7287f502747SJoel Fernandes 7297f502747SJoel Fernandes val = val.with_field_5_4(Priority::Low); 7307f502747SJoel Fernandes assert_eq!(val.field_5_4(), Priority::Low); 7317f502747SJoel Fernandes assert_eq!(val.into_raw() & 0x30, 0x00); 7327f502747SJoel Fernandes 7337f502747SJoel Fernandes val = val.with_field_5_4(Priority::Medium); 7347f502747SJoel Fernandes assert_eq!(val.field_5_4(), Priority::Medium); 7357f502747SJoel Fernandes assert_eq!(val.into_raw() & 0x30, 0x10); 7367f502747SJoel Fernandes 7377f502747SJoel Fernandes val = val.with_field_5_4(Priority::High); 7387f502747SJoel Fernandes assert_eq!(val.field_5_4(), Priority::High); 7397f502747SJoel Fernandes assert_eq!(val.into_raw() & 0x30, 0x20); 7407f502747SJoel Fernandes 7417f502747SJoel Fernandes val = val.with_field_5_4(Priority::Critical); 7427f502747SJoel Fernandes assert_eq!(val.field_5_4(), Priority::Critical); 7437f502747SJoel Fernandes assert_eq!(val.into_raw() & 0x30, 0x30); 7447f502747SJoel Fernandes } 7457f502747SJoel Fernandes 7467f502747SJoel Fernandes // `?=>` fallible conversion. 7477f502747SJoel Fernandes #[test] test_fallible_conversion()7487f502747SJoel Fernandes fn test_fallible_conversion() { 7497f502747SJoel Fernandes let mut val = TestU64::zeroed(); 7507f502747SJoel Fernandes 7517f502747SJoel Fernandes val = val.with_field_15_12(MemoryType::Unmapped); 7527f502747SJoel Fernandes assert_eq!(val.field_15_12(), Ok(MemoryType::Unmapped)); 7537f502747SJoel Fernandes val = val.with_field_15_12(MemoryType::Normal); 7547f502747SJoel Fernandes assert_eq!(val.field_15_12(), Ok(MemoryType::Normal)); 7557f502747SJoel Fernandes val = val.with_field_15_12(MemoryType::Device); 7567f502747SJoel Fernandes assert_eq!(val.field_15_12(), Ok(MemoryType::Device)); 7577f502747SJoel Fernandes val = val.with_field_15_12(MemoryType::Reserved); 7587f502747SJoel Fernandes assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved)); 7597f502747SJoel Fernandes 7607f502747SJoel Fernandes // `field_15_12` is 4 bits wide (0-15); `MemoryType` only covers 0-3, so 4-15 return `Err`. 7617f502747SJoel Fernandes let raw = (val.into_raw() & !::kernel::bits::genmask_u64(12..=15)) | (0x7 << 12); 7627f502747SJoel Fernandes assert_eq!(TestU64::from_raw(raw).field_15_12(), Err(0x7)); 7637f502747SJoel Fernandes } 7647f502747SJoel Fernandes 7657f502747SJoel Fernandes // Test that setting an overlapping field affects the overlapped one as expected. 7667f502747SJoel Fernandes #[test] test_overlapping_fields()7677f502747SJoel Fernandes fn test_overlapping_fields() { 7687f502747SJoel Fernandes let mut val = TestU16::zeroed(); 7697f502747SJoel Fernandes 7707f502747SJoel Fernandes val = val.with_field_5_4(Priority::High); // High == 2 == 0b10. 7717f502747SJoel Fernandes assert_eq!(val.field_5_4(), Priority::High); 7727f502747SJoel Fernandes assert_eq!(val.field_7_4(), 0x2); // Bits 7:6 == 0, bits 5:4 == 0b10. 7737f502747SJoel Fernandes 7747f502747SJoel Fernandes val = val.with_const_field_7_4::<0xF>(); 7757f502747SJoel Fernandes assert_eq!(val.field_7_4(), 0xF); 7767f502747SJoel Fernandes assert_eq!(val.field_5_4(), Priority::Critical); // Bits 5:4 == 0b11. 7777f502747SJoel Fernandes 7787f502747SJoel Fernandes // `field_7_0` should encompass all other fields. 7797f502747SJoel Fernandes let mut val = TestU8::zeroed() 7807f502747SJoel Fernandes .with_field_0(true) 7817f502747SJoel Fernandes .with_field_1(true) 7827f502747SJoel Fernandes .with_const_field_3_2::<0x3>() 7837f502747SJoel Fernandes .with_const_field_7_4::<0xA>(); 7847f502747SJoel Fernandes assert_eq!(val.into_raw(), 0xAF); 7857f502747SJoel Fernandes 7867f502747SJoel Fernandes val = val.with_field_7_0(0x55); 7877f502747SJoel Fernandes assert_eq!(val.field_7_0(), 0x55); 7887f502747SJoel Fernandes assert!(val.field_0().into_bool()); 7897f502747SJoel Fernandes assert!(!val.field_1().into_bool()); 7907f502747SJoel Fernandes assert_eq!(val.field_3_2(), 0x1); 7917f502747SJoel Fernandes assert_eq!(val.field_7_4(), 0x5); 7927f502747SJoel Fernandes } 7937f502747SJoel Fernandes 7947f502747SJoel Fernandes // Checks that bits not mapped to any field are left untouched. 7957f502747SJoel Fernandes #[test] test_unallocated_bits()7967f502747SJoel Fernandes fn test_unallocated_bits() { 7977f502747SJoel Fernandes let gap_bits = (1u64 << 62) | 0x1FC; 7987f502747SJoel Fernandes 7997f502747SJoel Fernandes let set_all_fields = |val: TestU64| { 8007f502747SJoel Fernandes val.with_field_63(true) 8017f502747SJoel Fernandes .with_const_field_61_52::<0x155>() 8027f502747SJoel Fernandes .with_const_field_51_16::<0x123456>() 8037f502747SJoel Fernandes .with_field_15_12(MemoryType::Device) 8047f502747SJoel Fernandes .with_const_field_11_9::<0x5>() 8057f502747SJoel Fernandes .with_field_1(true) 8067f502747SJoel Fernandes .with_field_0(true) 8077f502747SJoel Fernandes }; 8087f502747SJoel Fernandes 8097f502747SJoel Fernandes // Gap bits to 0. 8107f502747SJoel Fernandes let val = set_all_fields(TestU64::from_raw(0)); 8117f502747SJoel Fernandes assert_eq!(val.into_raw() & gap_bits, 0); 8127f502747SJoel Fernandes 8137f502747SJoel Fernandes // Gap bits to 1. 8147f502747SJoel Fernandes let val = set_all_fields(TestU64::from_raw(gap_bits)); 8157f502747SJoel Fernandes assert_eq!(val.into_raw() & gap_bits, gap_bits); 8167f502747SJoel Fernandes } 8177f502747SJoel Fernandes 8187f502747SJoel Fernandes #[test] test_try_with()8197f502747SJoel Fernandes fn test_try_with() { 8207f502747SJoel Fernandes let val = TestU64::zeroed().try_with_field_51_16(0x123456).unwrap(); 8217f502747SJoel Fernandes assert_eq!(val.field_51_16(), 0x123456); 8227f502747SJoel Fernandes 8237f502747SJoel Fernandes let err = TestU64::zeroed().try_with_field_51_16(u64::MAX); 8247f502747SJoel Fernandes assert_eq!(err, Err(::kernel::error::code::EOVERFLOW)); 8257f502747SJoel Fernandes 8267f502747SJoel Fernandes let val = TestU64::zeroed() 8277f502747SJoel Fernandes .try_with_field_51_16(0xABCDEF) 8287f502747SJoel Fernandes .and_then(|p| p.try_with_field_0(1)) 8297f502747SJoel Fernandes .unwrap(); 8307f502747SJoel Fernandes assert_eq!(val.field_51_16(), 0xABCDEF); 8317f502747SJoel Fernandes assert!(val.field_0().into_bool()); 8327f502747SJoel Fernandes } 8337f502747SJoel Fernandes 8347f502747SJoel Fernandes // `from_raw`/`into_raw` and `From`/`Into` round-trips. 8357f502747SJoel Fernandes #[test] test_raw()8367f502747SJoel Fernandes fn test_raw() { 8377f502747SJoel Fernandes let raw: u64 = 0xBFF0_0000_3123_3E03; 8387f502747SJoel Fernandes let val = TestU64::from_raw(raw); 8397f502747SJoel Fernandes assert_eq!(u64::from(val), raw); 8407f502747SJoel Fernandes assert!(val.field_0().into_bool()); 8417f502747SJoel Fernandes assert!(val.field_1().into_bool()); 8427f502747SJoel Fernandes assert_eq!(val.field_11_9(), 0x7); 8437f502747SJoel Fernandes assert_eq!(val.field_51_16(), 0x3123); 8447f502747SJoel Fernandes assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved)); 8457f502747SJoel Fernandes assert_eq!(val.field_61_52(), 0x3FF); 8467f502747SJoel Fernandes assert!(val.field_63().into_bool()); 8477f502747SJoel Fernandes 8487f502747SJoel Fernandes let raw: u16 = 0x42AB; 8497f502747SJoel Fernandes let val = TestU16::from_raw(raw); 8507f502747SJoel Fernandes assert_eq!(u16::from(val), raw); 8517f502747SJoel Fernandes assert!(val.field_0().into_bool()); 8527f502747SJoel Fernandes assert_eq!(val.field_3_1(), 0x5); 8537f502747SJoel Fernandes assert_eq!(val.field_7_4(), 0xA); 8547f502747SJoel Fernandes assert_eq!(val.field_15_8(), 0x42); 8557f502747SJoel Fernandes 8567f502747SJoel Fernandes let raw: u8 = 0xAF; 8577f502747SJoel Fernandes let val = TestU8::from_raw(raw); 8587f502747SJoel Fernandes assert_eq!(u8::from(val), raw); 8597f502747SJoel Fernandes assert!(val.field_0().into_bool()); 8607f502747SJoel Fernandes assert!(val.field_1().into_bool()); 8617f502747SJoel Fernandes assert_eq!(val.field_3_2(), 0x3); 8627f502747SJoel Fernandes assert_eq!(val.field_7_4(), 0xA); 8637f502747SJoel Fernandes assert_eq!(val.field_7_0(), 0xAF); 864 } 865 } 866