863 lines · 27.1 KB · Rust
RawDownload
// SPDX-License-Identifier: GPL-2.0 //! Support for defining bitfields as Rust structures.//!//! The [`bitfield!`](kernel::bitfield!) macro declares integer types that are split into distinct//! bit fields of arbitrary length. Each field is typed using [`Bounded`](kernel::num::Bounded) to//! ensure values are properly validated and to avoid implicit data loss.//!//! # Example//!//! ```rust//! use kernel::bitfield;//! use kernel::num::Bounded;//!//! bitfield! {//!     pub struct Rgb(u16) {//!         15:11 blue;//!         10:5 green;//!         4:0 red;//!     }//! }//!//! // Valid value for the `blue` field.//! let blue = Bounded::<u16, 5>::new::<0x18>();//!//! // Setters can be chained. Values ranges are checked at compile-time.//! let color = Rgb::zeroed()//!     // Compile-time bounds check of constant value.//!     .with_const_red::<0x10>()//!     .with_const_green::<0x1f>()//!     // A `Bounded` can also be passed.//!     .with_blue(blue);//!//! assert_eq!(color.red(), 0x10);//! assert_eq!(color.green(), 0x1f);//! assert_eq!(color.blue(), 0x18);//! assert_eq!(//!     color.into_raw(),//!     (0x18 << Rgb::BLUE_SHIFT) + (0x1f << Rgb::GREEN_SHIFT) + 0x10,//! );//!//! // Convert to/from the backing storage type.//! let raw: u16 = color.into();//! assert_eq!(Rgb::from(raw), color);//! ```//!//! # Syntax//!//! ```text//! bitfield! {//!     #[attributes]//!     // Documentation for `Name`.//!     pub struct Name(storage_type) {//!         // `field_1` documentation.//!         hi:lo field_1;//!         // `field_2` documentation.//!         hi:lo field_2 => ConvertedType;//!         // `field_3` documentation.//!         hi:lo field_3 ?=> ConvertedType;//!         ...//!     }//! }//! ```//!//! - `storage_type`: The underlying unsigned integer type ([`u8`], [`u16`], [`u32`], [`u64`]).//!   Signed integer storage types are not supported.//! - `hi:lo`: Bit range (inclusive), where `hi >= lo`.//! - `=> Type`: Optional infallible conversion (see [below](#infallible-conversion-)).//! - `?=> Type`: Optional fallible conversion (see [below](#fallible-conversion-)).//! - Documentation strings and attributes are optional.//!//! # Generated code//!//! Each field is internally represented as a [`Bounded`] parameterized by its bit width. Field//! values can either be set/retrieved directly, or converted from/to another type.//!//! The use of [`Bounded`] for each field enforces bounds-checking (at build time or runtime) of//! every value assigned to a field. This ensures that data is never accidentally truncated.//!//! The macro generates the bitfield type, [`From`] and [`Into`] implementations for its storage//! type, as well as [`Debug`] and [`Zeroable`](pin_init::Zeroable) implementations.//!//! For each field, it also generates://!//! - `field()`: Getter method for the field value.//! - `with_field(value)`: Infallible setter; the argument type must fit within the field's width.//! - `with_const_field::<VALUE>()`: `const` setter; the value is validated at compile time.//!   Usually shorter to use than `with_field` for constant values as it doesn't require//!   constructing a [`Bounded`].//! - `try_with_field(value)`: Fallible setter. Returns an error if the value is out of range.//! - `FIELD_MASK`, `FIELD_SHIFT`, `FIELD_RANGE`: Constants for manual bit manipulation.//!//! # Reserved names for field identifiers//!//! Field identifiers are used to generate methods and associated constants on the bitfield type.//! For a field named `field`, the macro may generate methods named `field`, `with_field`,//! `with_const_field`, `try_with_field`, `__field` and `__with_field`, as well as constants named//! `FIELD_MASK`, `FIELD_SHIFT` and `FIELD_RANGE`.//!//! Therefore, field identifiers must not use names that would collide with generated items for//! any field in the same bitfield. The following prefixes are thus reserved for field identifiers://!//! - `with_`//! - `const_`//! - `try_with_`//! - `__`//!//! The field identifiers `from_raw`, `into_raw`, and `into` are also reserved.//!//! In addition, field identifiers should follow Rust `snake_case` conventions, since the associated//! constants are generated by uppercasing the field name.//!//! # Implicit conversions//!//! Types that fit entirely within a field's bit width can be used directly with setters. For//! example, [`bool`] works with single-bit fields, and [`u8`] works with 8-bit fields://!//! ```rust//! use kernel::bitfield;//!//! bitfield! {//!     pub struct Flags(u32) {//!         15:8 byte_field;//!         0:0 flag;//!     }//! }//!//! let flags = Flags::zeroed()//!     .with_byte_field(0x42_u8)//!     .with_flag(true);//!//! assert_eq!(flags.into_raw(), (0x42 << Flags::BYTE_FIELD_SHIFT) | 1);//! ```//!//! # Runtime bounds checking//!//! When a value is not known at compile time, use `try_with_field()` to check bounds at runtime://!//! ```rust//! use kernel::bitfield;//!//! bitfield! {//!     pub struct Config(u8) {//!         3:0 nibble;//!     }//! }//!//! fn set_nibble(config: Config, value: u8) -> Result<Config, Error> {//!     // Returns `EOVERFLOW` if `value > 0xf`.//!     config.try_with_nibble(value)//! }//! # Ok::<(), Error>(())//! ```//!//! # Type conversion//!//! Fields can be automatically converted to/from a custom type using `=>` (infallible) or `?=>`//! (fallible). The custom type must implement the appropriate [`From`] or [`TryFrom`] traits with//! [`Bounded`].//!//! ## Infallible conversion (`=>`)//!//! Use this when all possible bit patterns of a field map to valid values://!//! ```rust//! use kernel::bitfield;//! use kernel::num::Bounded;//!//! #[derive(Debug, Clone, Copy, PartialEq)]//! enum Power {//!     Off,//!     On,//! }//!//! impl From<Bounded<u32, 1>> for Power {//!     fn from(v: Bounded<u32, 1>) -> Self {//!         match *v {//!             0 => Power::Off,//!             _ => Power::On,//!         }//!     }//! }//!//! impl From<Power> for Bounded<u32, 1> {//!     fn from(p: Power) -> Self {//!         (p as u32 != 0).into()//!     }//! }//!//! bitfield! {//!     pub struct Control(u32) {//!         0:0 power => Power;//!     }//! }//!//! let ctrl = Control::zeroed().with_power(Power::On);//! assert_eq!(ctrl.power(), Power::On);//! ```//!//! ## Fallible conversion (`?=>`)//!//! Use this when some bit patterns of a field are invalid. The getter returns a [`Result`]://!//! ```rust//! use kernel::bitfield;//! use kernel::num::Bounded;//!//! #[derive(Debug, Clone, Copy, PartialEq)]//! enum Mode {//!     Low = 0,//!     High = 1,//!     Auto = 2,//!     // 3 is invalid//! }//!//! impl TryFrom<Bounded<u32, 2>> for Mode {//!     type Error = u32;//!//!     fn try_from(v: Bounded<u32, 2>) -> Result<Self, u32> {//!         match *v {//!             0 => Ok(Mode::Low),//!             1 => Ok(Mode::High),//!             2 => Ok(Mode::Auto),//!             n => Err(n),//!         }//!     }//! }//!//! impl From<Mode> for Bounded<u32, 2> {//!     fn from(m: Mode) -> Self {//!         match m {//!             Mode::Low => Bounded::<u32, _>::new::<0>(),//!             Mode::High => Bounded::<u32, _>::new::<1>(),//!             Mode::Auto => Bounded::<u32, _>::new::<2>(),//!         }//!     }//! }//!//! bitfield! {//!     pub struct Config(u32) {//!         1:0 mode ?=> Mode;//!     }//! }//!//! let cfg = Config::zeroed().with_mode(Mode::Auto);//! assert_eq!(cfg.mode(), Ok(Mode::Auto));//!//! // Invalid bit pattern returns an error.//! assert_eq!(Config::from(0b11).mode(), Err(3));//! ```//!//! # Bits outside of declared fields//!//! Bits of the storage type that are not part of any declared field are preserved by the setter//! methods, and can only be modified through `from_raw` or the [`From`] implementation from the//! storage type.//!//! ```rust//! use kernel::bitfield;//!//! bitfield! {//!     pub struct Sparse(u8) {//!         7:6 high;//!         // Bits 5:1 are not covered by any field.//!         0:0 low;//!     }//! }//!//! // Set the gap bits via `from_raw`, then mutate the declared fields.//! let val = Sparse::from_raw(0b0010_1010)//!     .with_const_high::<0b11>()//!     .with_low(true);//!//! // Bits 5:1 are unchanged.//! assert_eq!(val.into_raw(), 0b1110_1011);//! ```//!//! # Signed field values//!//! Bitfield storage types are unsigned. Since field getter methods return a [`Bounded`] of the//! storage type, fields are also unsigned by default.//!//! If a field needs to encode a signed value, use a custom conversion type with `=>` or `?=>` to//! perform the sign interpretation explicitly.//!//! [`Bounded`]: kernel::num::Bounded /// Defines a bitfield struct with bounds-checked accessors for individual bit ranges.////// See the [`mod@kernel::bitfield`] module for full documentation and examples.#[macro_export]macro_rules! bitfield {    // Entry point defining the bitfield struct, its implementations and its field accessors.    (        $(#[$attr:meta])* $vis:vis struct $name:ident($storage:ty) { $($fields:tt)* }    ) => {        $crate::bitfield!(@core            #[allow(non_camel_case_types)]            $(#[$attr])* $vis $name $storage        );        $crate::bitfield!(@fields $vis $name $storage { $($fields)* });    };     // All rules below are helpers.     // Defines the wrapper `$name` type and its conversions from/to the storage type.    (@core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) => {        $(#[$attr])*        #[repr(transparent)]        #[derive(Clone, Copy, PartialEq, Eq)]        $vis struct $name {            inner: $storage,        }         #[allow(dead_code)]        impl $name {            /// Creates a bitfield from a raw value.            #[inline(always)]            $vis const fn from_raw(value: $storage) -> Self {                Self{ inner: value }            }             /// Turns this bitfield into its raw value.            ///            /// This is similar to the [`From`] implementation, but is shorter to invoke in            /// most cases.            #[inline(always)]            $vis const fn into_raw(self) -> $storage {                self.inner            }        }         // SAFETY: `$storage` is `Zeroable` and `$name` is transparent.        unsafe impl ::pin_init::Zeroable for $name {}         impl ::core::convert::From<$name> for $storage {            #[inline(always)]            fn from(val: $name) -> $storage {                val.into_raw()            }        }         impl ::core::convert::From<$storage> for $name {            #[inline(always)]            fn from(val: $storage) -> $name {                Self::from_raw(val)            }        }    };     // Definitions requiring knowledge of individual fields: private and public field accessors,    // and `Debug` implementation.    (@fields $vis:vis $name:ident $storage:ty {        $($(#[doc = $doc:expr])* $hi:literal:$lo:literal $field:ident            $(?=> $try_into_type:ty)?            $(=> $into_type:ty)?        ;        )*    }    ) => {        #[allow(dead_code)]        impl $name {        $(        $crate::bitfield!(@private_field_accessors $vis $name $storage : $hi:$lo $field);        $crate::bitfield!(            @public_field_accessors $(#[doc = $doc])* $vis $name $storage : $hi:$lo $field            $(?=> $try_into_type)?            $(=> $into_type)?        );        )*        }         $crate::bitfield!(@debug $name { $($field;)* });    };     // Private field accessors working with the exact `Bounded` type for the field.    (        @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident    ) => {        ::kernel::macros::paste!(        $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi;        $vis const [<$field:upper _MASK>]: $storage =            ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1);        $vis const [<$field:upper _SHIFT>]: u32 = $lo;        );         ::kernel::macros::paste!(        #[inline(always)]        fn [<__ $field>](self) ->            ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> {            // Left shift to align the field's MSB with the storage MSB.            const ALIGN_TOP: u32 = $storage::BITS - ($hi + 1);            // Right shift to move the top-aligned field to bit 0 of the storage.            const ALIGN_BOTTOM: u32 = ALIGN_TOP + $lo;             // Extract the field using two shifts. `Bounded::shr` produces the correctly-sized            // output type.            let val = ::kernel::num::Bounded::<$storage, { $storage::BITS }>::from(                self.inner << ALIGN_TOP            );            val.shr::<ALIGN_BOTTOM, { $hi + 1 - $lo } >()        }         #[inline(always)]        const fn [<__with_ $field>](            mut self,            value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>,        ) -> Self        {            const MASK: $storage = <$name>::[<$field:upper _MASK>];            const SHIFT: u32 = <$name>::[<$field:upper _SHIFT>];             let value = value.get() << SHIFT;            self.inner = (self.inner & !MASK) | value;             self        }        );    };     // Public accessors for fields infallibly (`=>`) converted to a type.    (        @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :            $hi:literal:$lo:literal $field:ident => $into_type:ty    ) => {        ::kernel::macros::paste!(         $(#[doc = $doc])*        #[doc = "Returns the value of this field."]        #[inline(always)]        $vis fn $field(self) -> $into_type        {            self.[<__ $field>]().into()        }         $(#[doc = $doc])*        #[doc = "Sets this field to the given `value`."]        #[inline(always)]        $vis fn [<with_ $field>](self, value: $into_type) -> Self        {            self.[<__with_ $field>](value.into())        }         );    };     // Public accessors for fields fallibly (`?=>`) converted to a type.    (        @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :            $hi:tt:$lo:tt $field:ident ?=> $try_into_type:ty    ) => {        ::kernel::macros::paste!(         $(#[doc = $doc])*        #[doc = "Returns the value of this field."]        #[inline(always)]        $vis fn $field(self) ->            ::core::result::Result<                $try_into_type,                <$try_into_type as ::core::convert::TryFrom<                    ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>                >>::Error            >        {            self.[<__ $field>]().try_into()        }         $(#[doc = $doc])*        #[doc = "Sets this field to the given `value`."]        #[inline(always)]        $vis fn [<with_ $field>](self, value: $try_into_type) -> Self        {            self.[<__with_ $field>](value.into())        }         );    };     // Public accessors for fields not converted to a type.    (        @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty :            $hi:tt:$lo:tt $field:ident    ) => {        ::kernel::macros::paste!(         $(#[doc = $doc])*        #[doc = "Returns the value of this field."]        #[inline(always)]        $vis fn $field(self) ->            ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>        {            self.[<__ $field>]()        }         $(#[doc = $doc])*        #[doc = "Sets this field to the compile-time constant `VALUE`."]        #[inline(always)]        $vis const fn [<with_const_ $field>]<const VALUE: $storage>(self) -> Self {            self.[<__with_ $field>](                ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new::<VALUE>()

Lines 1–500 of 863.