1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Support for defining bitfields as Rust structures. 4 //! 5 //! The [`bitfield!`](kernel::bitfield!) macro declares integer types that are split into distinct 6 //! bit fields of arbitrary length. Each field is typed using [`Bounded`](kernel::num::Bounded) to 7 //! ensure values are properly validated and to avoid implicit data loss. 8 //! 9 //! # Example 10 //! 11 //! ```rust 12 //! use kernel::bitfield; 13 //! use kernel::num::Bounded; 14 //! 15 //! bitfield! { 16 //! pub struct Rgb(u16) { 17 //! 15:11 blue; 18 //! 10:5 green; 19 //! 4:0 red; 20 //! } 21 //! } 22 //! 23 //! // Valid value for the `blue` field. 24 //! let blue = Bounded::<u16, 5>::new::<0x18>(); 25 //! 26 //! // Setters can be chained. Values ranges are checked at compile-time. 27 //! let color = Rgb::zeroed() 28 //! // Compile-time bounds check of constant value. 29 //! .with_const_red::<0x10>() 30 //! .with_const_green::<0x1f>() 31 //! // A `Bounded` can also be passed. 32 //! .with_blue(blue); 33 //! 34 //! assert_eq!(color.red(), 0x10); 35 //! assert_eq!(color.green(), 0x1f); 36 //! assert_eq!(color.blue(), 0x18); 37 //! assert_eq!( 38 //! color.into_raw(), 39 //! (0x18 << Rgb::BLUE_SHIFT) + (0x1f << Rgb::GREEN_SHIFT) + 0x10, 40 //! ); 41 //! 42 //! // Convert to/from the backing storage type. 43 //! let raw: u16 = color.into(); 44 //! assert_eq!(Rgb::from(raw), color); 45 //! ``` 46 //! 47 //! # Syntax 48 //! 49 //! ```text 50 //! bitfield! { 51 //! #[attributes] 52 //! // Documentation for `Name`. 53 //! pub struct Name(storage_type) { 54 //! // `field_1` documentation. 55 //! hi:lo field_1; 56 //! // `field_2` documentation. 57 //! hi:lo field_2 => ConvertedType; 58 //! // `field_3` documentation. 59 //! hi:lo field_3 ?=> ConvertedType; 60 //! ... 61 //! } 62 //! } 63 //! ``` 64 //! 65 //! - `storage_type`: The underlying unsigned integer type ([`u8`], [`u16`], [`u32`], [`u64`]). 66 //! Signed integer storage types are not supported. 67 //! - `hi:lo`: Bit range (inclusive), where `hi >= lo`. 68 //! - `=> Type`: Optional infallible conversion (see [below](#infallible-conversion-)). 69 //! - `?=> Type`: Optional fallible conversion (see [below](#fallible-conversion-)). 70 //! - Documentation strings and attributes are optional. 71 //! 72 //! # Generated code 73 //! 74 //! Each field is internally represented as a [`Bounded`] parameterized by its bit width. Field 75 //! values can either be set/retrieved directly, or converted from/to another type. 76 //! 77 //! The use of [`Bounded`] for each field enforces bounds-checking (at build time or runtime) of 78 //! every value assigned to a field. This ensures that data is never accidentally truncated. 79 //! 80 //! The macro generates the bitfield type, [`From`] and [`Into`] implementations for its storage 81 //! type, as well as [`Debug`] and [`Zeroable`](pin_init::Zeroable) implementations. 82 //! 83 //! For each field, it also generates: 84 //! 85 //! - `field()`: Getter method for the field value. 86 //! - `with_field(value)`: Infallible setter; the argument type must fit within the field's width. 87 //! - `with_const_field::<VALUE>()`: `const` setter; the value is validated at compile time. 88 //! Usually shorter to use than `with_field` for constant values as it doesn't require 89 //! constructing a [`Bounded`]. 90 //! - `try_with_field(value)`: Fallible setter. Returns an error if the value is out of range. 91 //! - `FIELD_MASK`, `FIELD_SHIFT`, `FIELD_RANGE`: Constants for manual bit manipulation. 92 //! 93 //! # Reserved names for field identifiers 94 //! 95 //! Field identifiers are used to generate methods and associated constants on the bitfield type. 96 //! For a field named `field`, the macro may generate methods named `field`, `with_field`, 97 //! `with_const_field`, `try_with_field`, `__field` and `__with_field`, as well as constants named 98 //! `FIELD_MASK`, `FIELD_SHIFT` and `FIELD_RANGE`. 99 //! 100 //! Therefore, field identifiers must not use names that would collide with generated items for 101 //! any field in the same bitfield. The following prefixes are thus reserved for field identifiers: 102 //! 103 //! - `with_` 104 //! - `const_` 105 //! - `try_with_` 106 //! - `__` 107 //! 108 //! The field identifiers `from_raw`, `into_raw`, and `into` are also reserved. 109 //! 110 //! In addition, field identifiers should follow Rust `snake_case` conventions, since the associated 111 //! constants are generated by uppercasing the field name. 112 //! 113 //! # Implicit conversions 114 //! 115 //! Types that fit entirely within a field's bit width can be used directly with setters. For 116 //! example, [`bool`] works with single-bit fields, and [`u8`] works with 8-bit fields: 117 //! 118 //! ```rust 119 //! use kernel::bitfield; 120 //! 121 //! bitfield! { 122 //! pub struct Flags(u32) { 123 //! 15:8 byte_field; 124 //! 0:0 flag; 125 //! } 126 //! } 127 //! 128 //! let flags = Flags::zeroed() 129 //! .with_byte_field(0x42_u8) 130 //! .with_flag(true); 131 //! 132 //! assert_eq!(flags.into_raw(), (0x42 << Flags::BYTE_FIELD_SHIFT) | 1); 133 //! ``` 134 //! 135 //! # Runtime bounds checking 136 //! 137 //! When a value is not known at compile time, use `try_with_field()` to check bounds at runtime: 138 //! 139 //! ```rust 140 //! use kernel::bitfield; 141 //! 142 //! bitfield! { 143 //! pub struct Config(u8) { 144 //! 3:0 nibble; 145 //! } 146 //! } 147 //! 148 //! fn set_nibble(config: Config, value: u8) -> Result<Config, Error> { 149 //! // Returns `EOVERFLOW` if `value > 0xf`. 150 //! config.try_with_nibble(value) 151 //! } 152 //! # Ok::<(), Error>(()) 153 //! ``` 154 //! 155 //! # Type conversion 156 //! 157 //! Fields can be automatically converted to/from a custom type using `=>` (infallible) or `?=>` 158 //! (fallible). The custom type must implement the appropriate [`From`] or [`TryFrom`] traits with 159 //! [`Bounded`]. 160 //! 161 //! ## Infallible conversion (`=>`) 162 //! 163 //! Use this when all possible bit patterns of a field map to valid values: 164 //! 165 //! ```rust 166 //! use kernel::bitfield; 167 //! use kernel::num::Bounded; 168 //! 169 //! #[derive(Debug, Clone, Copy, PartialEq)] 170 //! enum Power { 171 //! Off, 172 //! On, 173 //! } 174 //! 175 //! impl From<Bounded<u32, 1>> for Power { 176 //! fn from(v: Bounded<u32, 1>) -> Self { 177 //! match *v { 178 //! 0 => Power::Off, 179 //! _ => Power::On, 180 //! } 181 //! } 182 //! } 183 //! 184 //! impl From<Power> for Bounded<u32, 1> { 185 //! fn from(p: Power) -> Self { 186 //! (p as u32 != 0).into() 187 //! } 188 //! } 189 //! 190 //! bitfield! { 191 //! pub struct Control(u32) { 192 //! 0:0 power => Power; 193 //! } 194 //! } 195 //! 196 //! let ctrl = Control::zeroed().with_power(Power::On); 197 //! assert_eq!(ctrl.power(), Power::On); 198 //! ``` 199 //! 200 //! ## Fallible conversion (`?=>`) 201 //! 202 //! Use this when some bit patterns of a field are invalid. The getter returns a [`Result`]: 203 //! 204 //! ```rust 205 //! use kernel::bitfield; 206 //! use kernel::num::Bounded; 207 //! 208 //! #[derive(Debug, Clone, Copy, PartialEq)] 209 //! enum Mode { 210 //! Low = 0, 211 //! High = 1, 212 //! Auto = 2, 213 //! // 3 is invalid 214 //! } 215 //! 216 //! impl TryFrom<Bounded<u32, 2>> for Mode { 217 //! type Error = u32; 218 //! 219 //! fn try_from(v: Bounded<u32, 2>) -> Result<Self, u32> { 220 //! match *v { 221 //! 0 => Ok(Mode::Low), 222 //! 1 => Ok(Mode::High), 223 //! 2 => Ok(Mode::Auto), 224 //! n => Err(n), 225 //! } 226 //! } 227 //! } 228 //! 229 //! impl From<Mode> for Bounded<u32, 2> { 230 //! fn from(m: Mode) -> Self { 231 //! match m { 232 //! Mode::Low => Bounded::<u32, _>::new::<0>(), 233 //! Mode::High => Bounded::<u32, _>::new::<1>(), 234 //! Mode::Auto => Bounded::<u32, _>::new::<2>(), 235 //! } 236 //! } 237 //! } 238 //! 239 //! bitfield! { 240 //! pub struct Config(u32) { 241 //! 1:0 mode ?=> Mode; 242 //! } 243 //! } 244 //! 245 //! let cfg = Config::zeroed().with_mode(Mode::Auto); 246 //! assert_eq!(cfg.mode(), Ok(Mode::Auto)); 247 //! 248 //! // Invalid bit pattern returns an error. 249 //! assert_eq!(Config::from(0b11).mode(), Err(3)); 250 //! ``` 251 //! 252 //! # Bits outside of declared fields 253 //! 254 //! Bits of the storage type that are not part of any declared field are preserved by the setter 255 //! methods, and can only be modified through `from_raw` or the [`From`] implementation from the 256 //! storage type. 257 //! 258 //! ```rust 259 //! use kernel::bitfield; 260 //! 261 //! bitfield! { 262 //! pub struct Sparse(u8) { 263 //! 7:6 high; 264 //! // Bits 5:1 are not covered by any field. 265 //! 0:0 low; 266 //! } 267 //! } 268 //! 269 //! // Set the gap bits via `from_raw`, then mutate the declared fields. 270 //! let val = Sparse::from_raw(0b0010_1010) 271 //! .with_const_high::<0b11>() 272 //! .with_low(true); 273 //! 274 //! // Bits 5:1 are unchanged. 275 //! assert_eq!(val.into_raw(), 0b1110_1011); 276 //! ``` 277 //! 278 //! # Signed field values 279 //! 280 //! Bitfield storage types are unsigned. Since field getter methods return a [`Bounded`] of the 281 //! storage type, fields are also unsigned by default. 282 //! 283 //! If a field needs to encode a signed value, use a custom conversion type with `=>` or `?=>` to 284 //! perform the sign interpretation explicitly. 285 //! 286 //! [`Bounded`]: kernel::num::Bounded 287 288 /// Defines a bitfield struct with bounds-checked accessors for individual bit ranges. 289 /// 290 /// See the [`mod@kernel::bitfield`] module for full documentation and examples. 291 #[macro_export] 292 macro_rules! bitfield { 293 // Entry point defining the bitfield struct, its implementations and its field accessors. 294 ( 295 $(#[$attr:meta])* $vis:vis struct $name:ident($storage:ty) { $($fields:tt)* } 296 ) => { 297 $crate::bitfield!(@core 298 $(#[$attr])* $vis $name $storage 299 ); 300 $crate::bitfield!(@fields $vis $name $storage { $($fields)* }); 301 }; 302 303 // All rules below are helpers. 304 305 // Defines the wrapper `$name` type and its conversions from/to the storage type. 306 (@core $(#[$attr:meta])* $vis:vis $name:ident $storage:ty) => { 307 $(#[$attr])* 308 #[repr(transparent)] 309 #[derive(Clone, Copy, PartialEq, Eq)] 310 $vis struct $name { 311 inner: $storage, 312 } 313 314 #[allow(dead_code)] 315 impl $name { 316 /// Creates a bitfield from a raw value. 317 #[inline(always)] 318 $vis const fn from_raw(value: $storage) -> Self { 319 Self{ inner: value } 320 } 321 322 /// Turns this bitfield into its raw value. 323 /// 324 /// This is similar to the [`From`] implementation, but is shorter to invoke in 325 /// most cases. 326 #[inline(always)] 327 $vis const fn into_raw(self) -> $storage { 328 self.inner 329 } 330 } 331 332 // SAFETY: `$storage` is `Zeroable` and `$name` is transparent. 333 unsafe impl ::pin_init::Zeroable for $name {} 334 335 impl ::core::convert::From<$name> for $storage { 336 #[inline(always)] 337 fn from(val: $name) -> $storage { 338 val.into_raw() 339 } 340 } 341 342 impl ::core::convert::From<$storage> for $name { 343 #[inline(always)] 344 fn from(val: $storage) -> $name { 345 Self::from_raw(val) 346 } 347 } 348 349 // SAFETY: `$name` is transparent over `$storage` and `$storage` has no interior mutability. 350 unsafe impl $crate::mem::AsRepr for $name { 351 // Normalize `$storage` to the canonical repr type in case it is signed. 352 type Repr = <$storage as $crate::mem::AsRepr>::Repr; 353 } 354 355 // SAFETY: `$name` is transparent over `$storage`. 356 unsafe impl $crate::mem::AsReprMut for $name {} 357 }; 358 359 // Definitions requiring knowledge of individual fields: private and public field accessors, 360 // and `Debug` implementation. 361 (@fields $vis:vis $name:ident $storage:ty { 362 $($(#[doc = $doc:expr])* $hi:literal:$lo:literal $field:ident 363 $(?=> $try_into_type:ty)? 364 $(=> $into_type:ty)? 365 ; 366 )* 367 } 368 ) => { 369 #[allow(dead_code)] 370 impl $name { 371 $( 372 $crate::bitfield!(@private_field_accessors $vis $name $storage : $hi:$lo $field); 373 $crate::bitfield!( 374 @public_field_accessors $(#[doc = $doc])* $vis $name $storage : $hi:$lo $field 375 $(?=> $try_into_type)? 376 $(=> $into_type)? 377 ); 378 )* 379 } 380 381 $crate::bitfield!(@debug $name { $($field;)* }); 382 }; 383 384 // Private field accessors working with the exact `Bounded` type for the field. 385 ( 386 @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident 387 ) => { 388 ::kernel::macros::paste!( 389 $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi; 390 $vis const [<$field:upper _MASK>]: $storage = 391 ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1); 392 $vis const [<$field:upper _SHIFT>]: u32 = $lo; 393 ); 394 395 ::kernel::macros::paste!( 396 #[inline(always)] 397 fn [<__ $field>](self) -> 398 ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> { 399 // Left shift to align the field's MSB with the storage MSB. 400 const ALIGN_TOP: u32 = $storage::BITS - ($hi + 1); 401 // Right shift to move the top-aligned field to bit 0 of the storage. 402 const ALIGN_BOTTOM: u32 = ALIGN_TOP + $lo; 403 404 // Extract the field using two shifts. `Bounded::shr` produces the correctly-sized 405 // output type. 406 let val = ::kernel::num::Bounded::<$storage, { $storage::BITS }>::from( 407 self.inner << ALIGN_TOP 408 ); 409 val.shr::<ALIGN_BOTTOM, { $hi + 1 - $lo } >() 410 } 411 412 #[inline(always)] 413 const fn [<__with_ $field>]( 414 mut self, 415 value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>, 416 ) -> Self 417 { 418 const MASK: $storage = <$name>::[<$field:upper _MASK>]; 419 const SHIFT: u32 = <$name>::[<$field:upper _SHIFT>]; 420 421 let value = value.get() << SHIFT; 422 self.inner = (self.inner & !MASK) | value; 423 424 self 425 } 426 ); 427 }; 428 429 // Public accessors for fields infallibly (`=>`) converted to a type. 430 ( 431 @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : 432 $hi:literal:$lo:literal $field:ident => $into_type:ty 433 ) => { 434 ::kernel::macros::paste!( 435 436 $(#[doc = $doc])* 437 #[doc = "Returns the value of this field."] 438 #[inline(always)] 439 $vis fn $field(self) -> $into_type 440 { 441 self.[<__ $field>]().into() 442 } 443 444 $(#[doc = $doc])* 445 #[doc = "Sets this field to the given `value`."] 446 #[inline(always)] 447 $vis fn [<with_ $field>](self, value: $into_type) -> Self 448 { 449 self.[<__with_ $field>](value.into()) 450 } 451 452 ); 453 }; 454 455 // Public accessors for fields fallibly (`?=>`) converted to a type. 456 ( 457 @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : 458 $hi:tt:$lo:tt $field:ident ?=> $try_into_type:ty 459 ) => { 460 ::kernel::macros::paste!( 461 462 $(#[doc = $doc])* 463 #[doc = "Returns the value of this field."] 464 #[inline(always)] 465 $vis fn $field(self) -> 466 ::core::result::Result< 467 $try_into_type, 468 <$try_into_type as ::core::convert::TryFrom< 469 ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> 470 >>::Error 471 > 472 { 473 self.[<__ $field>]().try_into() 474 } 475 476 $(#[doc = $doc])* 477 #[doc = "Sets this field to the given `value`."] 478 #[inline(always)] 479 $vis fn [<with_ $field>](self, value: $try_into_type) -> Self 480 { 481 self.[<__with_ $field>](value.into()) 482 } 483 484 ); 485 }; 486 487 // Public accessors for fields not converted to a type. 488 ( 489 @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : 490 $hi:tt:$lo:tt $field:ident 491 ) => { 492 ::kernel::macros::paste!( 493 494 $(#[doc = $doc])* 495 #[doc = "Returns the value of this field."] 496 #[inline(always)] 497 $vis fn $field(self) -> 498 ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> 499 { 500 self.[<__ $field>]() 501 } 502 503 $(#[doc = $doc])* 504 #[doc = "Sets this field to the compile-time constant `VALUE`."] 505 #[inline(always)] 506 $vis const fn [<with_const_ $field>]<const VALUE: $storage>(self) -> Self { 507 self.[<__with_ $field>]( 508 ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new::<VALUE>() 509 ) 510 } 511 512 $(#[doc = $doc])* 513 #[doc = "Sets this field to the given `value`."] 514 #[inline(always)] 515 $vis fn [<with_ $field>]<T>( 516 self, 517 value: T, 518 ) -> Self 519 where T: ::core::convert::Into<::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>>, 520 { 521 self.[<__with_ $field>](value.into()) 522 } 523 524 $(#[doc = $doc])* 525 #[doc = "Tries to set this field to `value`, returning an error if it is out of range."] 526 #[inline(always)] 527 $vis fn [<try_with_ $field>]<T>( 528 self, 529 value: T, 530 ) -> ::kernel::error::Result<Self> 531 where T: ::kernel::num::TryIntoBounded<$storage, { $hi + 1 - $lo }>, 532 { 533 Ok( 534 self.[<__with_ $field>]( 535 value.try_into_bounded().ok_or(::kernel::error::code::EOVERFLOW)? 536 ) 537 ) 538 } 539 540 ); 541 }; 542 543 // `Debug` implementation. 544 (@debug $name:ident { $($field:ident;)* }) => { 545 impl ::kernel::fmt::Debug for $name { 546 #[inline] 547 fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result { 548 f.debug_struct(stringify!($name)) 549 .field("<raw>", &::kernel::prelude::fmt!("{:#x}", self.inner)) 550 $( 551 .field(stringify!($field), &self.$field()) 552 )* 553 .finish() 554 } 555 } 556 }; 557 } 558 559 #[cfg(CONFIG_RUST_BITFIELD_KUNIT_TEST)] 560 #[::kernel::macros::kunit_tests(rust_kernel_bitfield)] 561 mod tests { 562 use core::convert::TryFrom; 563 564 use pin_init::Zeroable; 565 566 use kernel::num::Bounded; 567 568 // Enum types for testing `=>` and `?=>` conversions. 569 570 #[derive(Debug, Clone, Copy, PartialEq)] 571 enum MemoryType { 572 Unmapped = 0, 573 Normal = 1, 574 Device = 2, 575 Reserved = 3, 576 } 577 578 impl TryFrom<Bounded<u64, 4>> for MemoryType { 579 type Error = u64; 580 fn try_from(value: Bounded<u64, 4>) -> Result<Self, Self::Error> { 581 match value.get() { 582 0 => Ok(MemoryType::Unmapped), 583 1 => Ok(MemoryType::Normal), 584 2 => Ok(MemoryType::Device), 585 3 => Ok(MemoryType::Reserved), 586 _ => Err(value.get()), 587 } 588 } 589 } 590 591 impl From<MemoryType> for Bounded<u64, 4> { 592 #[inline(always)] 593 fn from(mt: MemoryType) -> Bounded<u64, 4> { 594 Bounded::from_expr(mt as u64) 595 } 596 } 597 598 #[derive(Debug, Clone, Copy, PartialEq)] 599 enum Priority { 600 Low = 0, 601 Medium = 1, 602 High = 2, 603 Critical = 3, 604 } 605 606 impl From<Bounded<u16, 2>> for Priority { 607 fn from(value: Bounded<u16, 2>) -> Self { 608 match value & 0x3 { 609 0 => Priority::Low, 610 1 => Priority::Medium, 611 2 => Priority::High, 612 _ => Priority::Critical, 613 } 614 } 615 } 616 617 impl From<Priority> for Bounded<u16, 2> { 618 #[inline(always)] 619 fn from(p: Priority) -> Bounded<u16, 2> { 620 Bounded::from_expr(p as u16) 621 } 622 } 623 624 bitfield! { 625 struct TestU64(u64) { 626 63:63 field_63; 627 61:52 field_61_52; 628 51:16 field_51_16; 629 15:12 field_15_12 ?=> MemoryType; 630 11:9 field_11_9; 631 1:1 field_1; 632 0:0 field_0; 633 } 634 } 635 636 bitfield! { 637 struct TestU16(u16) { 638 15:8 field_15_8; 639 7:4 field_7_4; // Partial overlap with `field_5_4`. 640 5:4 field_5_4 => Priority; 641 3:1 field_3_1; 642 0:0 field_0; 643 } 644 } 645 646 bitfield! { 647 struct TestU8(u8) { 648 7:0 field_7_0; // Full byte overlap. 649 7:4 field_7_4; 650 3:2 field_3_2; 651 1:1 field_1; 652 0:0 field_0; 653 } 654 } 655 656 // Single and multi-bit fields basic access. 657 #[test] 658 fn test_basic_access() { 659 // `TestU64`. 660 let mut val = TestU64::zeroed(); 661 assert_eq!(val.into_raw(), 0x0); 662 663 val = val.with_field_0(true); 664 assert!(val.field_0().into_bool()); 665 assert_eq!(val.into_raw(), 0x1); 666 667 val = val.with_field_1(true); 668 assert!(val.field_1().into_bool()); 669 val = val.with_field_1(false); 670 assert!(!val.field_1().into_bool()); 671 assert_eq!(val.into_raw(), 0x1); 672 673 val = val.with_const_field_11_9::<0x5>(); 674 assert_eq!(val.field_11_9(), 0x5); 675 assert_eq!(val.into_raw(), 0xA01); 676 677 val = val.with_const_field_51_16::<0x123456>(); 678 assert_eq!(val.field_51_16(), 0x123456); 679 assert_eq!(val.into_raw(), 0x0012_3456_0A01); 680 681 const MAX_FIELD_51_16: u64 = ::kernel::bits::genmask_u64(0..=35); 682 val = val.with_const_field_51_16::<{ MAX_FIELD_51_16 }>(); 683 assert_eq!(val.field_51_16(), MAX_FIELD_51_16); 684 685 val = val.with_const_field_61_52::<0x3FF>(); 686 assert_eq!(val.field_61_52(), 0x3FF); 687 688 val = val.with_field_63(true); 689 assert!(val.field_63().into_bool()); 690 691 // `TestU16`. 692 let mut val = TestU16::zeroed(); 693 assert_eq!(val.into_raw(), 0x0); 694 695 val = val.with_field_0(true); 696 assert!(val.field_0().into_bool()); 697 assert_eq!(val.into_raw(), 0x1); 698 699 val = val.with_const_field_3_1::<0x5>(); 700 assert_eq!(val.field_3_1(), 0x5); 701 assert_eq!(val.into_raw(), 0xB); 702 703 val = val.with_const_field_7_4::<0xA>(); 704 assert_eq!(val.field_7_4(), 0xA); 705 assert_eq!(val.into_raw(), 0xAB); 706 707 val = val.with_const_field_15_8::<0x42>(); 708 assert_eq!(val.field_15_8(), 0x42); 709 assert_eq!(val.into_raw(), 0x42AB); 710 711 // `TestU8`. 712 let mut val = TestU8::zeroed(); 713 assert_eq!(val.into_raw(), 0x0); 714 715 val = val.with_field_0(true); 716 assert!(val.field_0().into_bool()); 717 assert_eq!(val.into_raw(), 0x1); 718 719 val = val.with_field_1(true); 720 assert!(val.field_1().into_bool()); 721 assert_eq!(val.into_raw(), 0x3); 722 723 val = val.with_const_field_3_2::<0x3>(); 724 assert_eq!(val.field_3_2(), 0x3); 725 assert_eq!(val.into_raw(), 0xF); 726 727 val = val.with_const_field_7_4::<0xA>(); 728 assert_eq!(val.field_7_4(), 0xA); 729 assert_eq!(val.into_raw(), 0xAF); 730 } 731 732 // `=>` infallible conversion. 733 #[test] 734 fn test_infallible_conversion() { 735 let mut val = TestU16::zeroed(); 736 737 val = val.with_field_5_4(Priority::Low); 738 assert_eq!(val.field_5_4(), Priority::Low); 739 assert_eq!(val.into_raw() & 0x30, 0x00); 740 741 val = val.with_field_5_4(Priority::Medium); 742 assert_eq!(val.field_5_4(), Priority::Medium); 743 assert_eq!(val.into_raw() & 0x30, 0x10); 744 745 val = val.with_field_5_4(Priority::High); 746 assert_eq!(val.field_5_4(), Priority::High); 747 assert_eq!(val.into_raw() & 0x30, 0x20); 748 749 val = val.with_field_5_4(Priority::Critical); 750 assert_eq!(val.field_5_4(), Priority::Critical); 751 assert_eq!(val.into_raw() & 0x30, 0x30); 752 } 753 754 // `?=>` fallible conversion. 755 #[test] 756 fn test_fallible_conversion() { 757 let mut val = TestU64::zeroed(); 758 759 val = val.with_field_15_12(MemoryType::Unmapped); 760 assert_eq!(val.field_15_12(), Ok(MemoryType::Unmapped)); 761 val = val.with_field_15_12(MemoryType::Normal); 762 assert_eq!(val.field_15_12(), Ok(MemoryType::Normal)); 763 val = val.with_field_15_12(MemoryType::Device); 764 assert_eq!(val.field_15_12(), Ok(MemoryType::Device)); 765 val = val.with_field_15_12(MemoryType::Reserved); 766 assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved)); 767 768 // `field_15_12` is 4 bits wide (0-15); `MemoryType` only covers 0-3, so 4-15 return `Err`. 769 let raw = (val.into_raw() & !::kernel::bits::genmask_u64(12..=15)) | (0x7 << 12); 770 assert_eq!(TestU64::from_raw(raw).field_15_12(), Err(0x7)); 771 } 772 773 // Test that setting an overlapping field affects the overlapped one as expected. 774 #[test] 775 fn test_overlapping_fields() { 776 let mut val = TestU16::zeroed(); 777 778 val = val.with_field_5_4(Priority::High); // High == 2 == 0b10. 779 assert_eq!(val.field_5_4(), Priority::High); 780 assert_eq!(val.field_7_4(), 0x2); // Bits 7:6 == 0, bits 5:4 == 0b10. 781 782 val = val.with_const_field_7_4::<0xF>(); 783 assert_eq!(val.field_7_4(), 0xF); 784 assert_eq!(val.field_5_4(), Priority::Critical); // Bits 5:4 == 0b11. 785 786 // `field_7_0` should encompass all other fields. 787 let mut val = TestU8::zeroed() 788 .with_field_0(true) 789 .with_field_1(true) 790 .with_const_field_3_2::<0x3>() 791 .with_const_field_7_4::<0xA>(); 792 assert_eq!(val.into_raw(), 0xAF); 793 794 val = val.with_field_7_0(0x55); 795 assert_eq!(val.field_7_0(), 0x55); 796 assert!(val.field_0().into_bool()); 797 assert!(!val.field_1().into_bool()); 798 assert_eq!(val.field_3_2(), 0x1); 799 assert_eq!(val.field_7_4(), 0x5); 800 } 801 802 // Checks that bits not mapped to any field are left untouched. 803 #[test] 804 fn test_unallocated_bits() { 805 let gap_bits = (1u64 << 62) | 0x1FC; 806 807 let set_all_fields = |val: TestU64| { 808 val.with_field_63(true) 809 .with_const_field_61_52::<0x155>() 810 .with_const_field_51_16::<0x123456>() 811 .with_field_15_12(MemoryType::Device) 812 .with_const_field_11_9::<0x5>() 813 .with_field_1(true) 814 .with_field_0(true) 815 }; 816 817 // Gap bits to 0. 818 let val = set_all_fields(TestU64::from_raw(0)); 819 assert_eq!(val.into_raw() & gap_bits, 0); 820 821 // Gap bits to 1. 822 let val = set_all_fields(TestU64::from_raw(gap_bits)); 823 assert_eq!(val.into_raw() & gap_bits, gap_bits); 824 } 825 826 #[test] 827 fn test_try_with() { 828 let val = TestU64::zeroed().try_with_field_51_16(0x123456).unwrap(); 829 assert_eq!(val.field_51_16(), 0x123456); 830 831 let err = TestU64::zeroed().try_with_field_51_16(u64::MAX); 832 assert_eq!(err, Err(::kernel::error::code::EOVERFLOW)); 833 834 let val = TestU64::zeroed() 835 .try_with_field_51_16(0xABCDEF) 836 .and_then(|p| p.try_with_field_0(1)) 837 .unwrap(); 838 assert_eq!(val.field_51_16(), 0xABCDEF); 839 assert!(val.field_0().into_bool()); 840 } 841 842 // `from_raw`/`into_raw` and `From`/`Into` round-trips. 843 #[test] 844 fn test_raw() { 845 let raw: u64 = 0xBFF0_0000_3123_3E03; 846 let val = TestU64::from_raw(raw); 847 assert_eq!(u64::from(val), raw); 848 assert!(val.field_0().into_bool()); 849 assert!(val.field_1().into_bool()); 850 assert_eq!(val.field_11_9(), 0x7); 851 assert_eq!(val.field_51_16(), 0x3123); 852 assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved)); 853 assert_eq!(val.field_61_52(), 0x3FF); 854 assert!(val.field_63().into_bool()); 855 856 let raw: u16 = 0x42AB; 857 let val = TestU16::from_raw(raw); 858 assert_eq!(u16::from(val), raw); 859 assert!(val.field_0().into_bool()); 860 assert_eq!(val.field_3_1(), 0x5); 861 assert_eq!(val.field_7_4(), 0xA); 862 assert_eq!(val.field_15_8(), 0x42); 863 864 let raw: u8 = 0xAF; 865 let val = TestU8::from_raw(raw); 866 assert_eq!(u8::from(val), raw); 867 assert!(val.field_0().into_bool()); 868 assert!(val.field_1().into_bool()); 869 assert_eq!(val.field_3_2(), 0x3); 870 assert_eq!(val.field_7_4(), 0xA); 871 assert_eq!(val.field_7_0(), 0xAF); 872 } 873 } 874