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 350 // Definitions requiring knowledge of individual fields: private and public field accessors, 351 // and `Debug` implementation. 352 (@fields $vis:vis $name:ident $storage:ty { 353 $($(#[doc = $doc:expr])* $hi:literal:$lo:literal $field:ident 354 $(?=> $try_into_type:ty)? 355 $(=> $into_type:ty)? 356 ; 357 )* 358 } 359 ) => { 360 #[allow(dead_code)] 361 impl $name { 362 $( 363 $crate::bitfield!(@private_field_accessors $vis $name $storage : $hi:$lo $field); 364 $crate::bitfield!( 365 @public_field_accessors $(#[doc = $doc])* $vis $name $storage : $hi:$lo $field 366 $(?=> $try_into_type)? 367 $(=> $into_type)? 368 ); 369 )* 370 } 371 372 $crate::bitfield!(@debug $name { $($field;)* }); 373 }; 374 375 // Private field accessors working with the exact `Bounded` type for the field. 376 ( 377 @private_field_accessors $vis:vis $name:ident $storage:ty : $hi:tt:$lo:tt $field:ident 378 ) => { 379 ::kernel::macros::paste!( 380 $vis const [<$field:upper _RANGE>]: ::core::ops::RangeInclusive<u8> = $lo..=$hi; 381 $vis const [<$field:upper _MASK>]: $storage = 382 ((((1 << $hi) - 1) << 1) + 1) - ((1 << $lo) - 1); 383 $vis const [<$field:upper _SHIFT>]: u32 = $lo; 384 ); 385 386 ::kernel::macros::paste!( 387 #[inline(always)] 388 fn [<__ $field>](self) -> 389 ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> { 390 // Left shift to align the field's MSB with the storage MSB. 391 const ALIGN_TOP: u32 = $storage::BITS - ($hi + 1); 392 // Right shift to move the top-aligned field to bit 0 of the storage. 393 const ALIGN_BOTTOM: u32 = ALIGN_TOP + $lo; 394 395 // Extract the field using two shifts. `Bounded::shr` produces the correctly-sized 396 // output type. 397 let val = ::kernel::num::Bounded::<$storage, { $storage::BITS }>::from( 398 self.inner << ALIGN_TOP 399 ); 400 val.shr::<ALIGN_BOTTOM, { $hi + 1 - $lo } >() 401 } 402 403 #[inline(always)] 404 const fn [<__with_ $field>]( 405 mut self, 406 value: ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>, 407 ) -> Self 408 { 409 const MASK: $storage = <$name>::[<$field:upper _MASK>]; 410 const SHIFT: u32 = <$name>::[<$field:upper _SHIFT>]; 411 412 let value = value.get() << SHIFT; 413 self.inner = (self.inner & !MASK) | value; 414 415 self 416 } 417 ); 418 }; 419 420 // Public accessors for fields infallibly (`=>`) converted to a type. 421 ( 422 @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : 423 $hi:literal:$lo:literal $field:ident => $into_type:ty 424 ) => { 425 ::kernel::macros::paste!( 426 427 $(#[doc = $doc])* 428 #[doc = "Returns the value of this field."] 429 #[inline(always)] 430 $vis fn $field(self) -> $into_type 431 { 432 self.[<__ $field>]().into() 433 } 434 435 $(#[doc = $doc])* 436 #[doc = "Sets this field to the given `value`."] 437 #[inline(always)] 438 $vis fn [<with_ $field>](self, value: $into_type) -> Self 439 { 440 self.[<__with_ $field>](value.into()) 441 } 442 443 ); 444 }; 445 446 // Public accessors for fields fallibly (`?=>`) converted to a type. 447 ( 448 @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : 449 $hi:tt:$lo:tt $field:ident ?=> $try_into_type:ty 450 ) => { 451 ::kernel::macros::paste!( 452 453 $(#[doc = $doc])* 454 #[doc = "Returns the value of this field."] 455 #[inline(always)] 456 $vis fn $field(self) -> 457 ::core::result::Result< 458 $try_into_type, 459 <$try_into_type as ::core::convert::TryFrom< 460 ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> 461 >>::Error 462 > 463 { 464 self.[<__ $field>]().try_into() 465 } 466 467 $(#[doc = $doc])* 468 #[doc = "Sets this field to the given `value`."] 469 #[inline(always)] 470 $vis fn [<with_ $field>](self, value: $try_into_type) -> Self 471 { 472 self.[<__with_ $field>](value.into()) 473 } 474 475 ); 476 }; 477 478 // Public accessors for fields not converted to a type. 479 ( 480 @public_field_accessors $(#[doc = $doc:expr])* $vis:vis $name:ident $storage:ty : 481 $hi:tt:$lo:tt $field:ident 482 ) => { 483 ::kernel::macros::paste!( 484 485 $(#[doc = $doc])* 486 #[doc = "Returns the value of this field."] 487 #[inline(always)] 488 $vis fn $field(self) -> 489 ::kernel::num::Bounded<$storage, { $hi + 1 - $lo }> 490 { 491 self.[<__ $field>]() 492 } 493 494 $(#[doc = $doc])* 495 #[doc = "Sets this field to the compile-time constant `VALUE`."] 496 #[inline(always)] 497 $vis const fn [<with_const_ $field>]<const VALUE: $storage>(self) -> Self { 498 self.[<__with_ $field>]( 499 ::kernel::num::Bounded::<$storage, { $hi + 1 - $lo }>::new::<VALUE>() 500 ) 501 } 502 503 $(#[doc = $doc])* 504 #[doc = "Sets this field to the given `value`."] 505 #[inline(always)] 506 $vis fn [<with_ $field>]<T>( 507 self, 508 value: T, 509 ) -> Self 510 where T: ::core::convert::Into<::kernel::num::Bounded<$storage, { $hi + 1 - $lo }>>, 511 { 512 self.[<__with_ $field>](value.into()) 513 } 514 515 $(#[doc = $doc])* 516 #[doc = "Tries to set this field to `value`, returning an error if it is out of range."] 517 #[inline(always)] 518 $vis fn [<try_with_ $field>]<T>( 519 self, 520 value: T, 521 ) -> ::kernel::error::Result<Self> 522 where T: ::kernel::num::TryIntoBounded<$storage, { $hi + 1 - $lo }>, 523 { 524 Ok( 525 self.[<__with_ $field>]( 526 value.try_into_bounded().ok_or(::kernel::error::code::EOVERFLOW)? 527 ) 528 ) 529 } 530 531 ); 532 }; 533 534 // `Debug` implementation. 535 (@debug $name:ident { $($field:ident;)* }) => { 536 impl ::kernel::fmt::Debug for $name { 537 #[inline] 538 fn fmt(&self, f: &mut ::kernel::fmt::Formatter<'_>) -> ::kernel::fmt::Result { 539 f.debug_struct(stringify!($name)) 540 .field("<raw>", &::kernel::prelude::fmt!("{:#x}", self.inner)) 541 $( 542 .field(stringify!($field), &self.$field()) 543 )* 544 .finish() 545 } 546 } 547 }; 548 } 549 550 #[cfg(CONFIG_RUST_BITFIELD_KUNIT_TEST)] 551 #[::kernel::macros::kunit_tests(rust_kernel_bitfield)] 552 mod tests { 553 use core::convert::TryFrom; 554 555 use pin_init::Zeroable; 556 557 use kernel::num::Bounded; 558 559 // Enum types for testing `=>` and `?=>` conversions. 560 561 #[derive(Debug, Clone, Copy, PartialEq)] 562 enum MemoryType { 563 Unmapped = 0, 564 Normal = 1, 565 Device = 2, 566 Reserved = 3, 567 } 568 569 impl TryFrom<Bounded<u64, 4>> for MemoryType { 570 type Error = u64; 571 fn try_from(value: Bounded<u64, 4>) -> Result<Self, Self::Error> { 572 match value.get() { 573 0 => Ok(MemoryType::Unmapped), 574 1 => Ok(MemoryType::Normal), 575 2 => Ok(MemoryType::Device), 576 3 => Ok(MemoryType::Reserved), 577 _ => Err(value.get()), 578 } 579 } 580 } 581 582 impl From<MemoryType> for Bounded<u64, 4> { 583 #[inline(always)] 584 fn from(mt: MemoryType) -> Bounded<u64, 4> { 585 Bounded::from_expr(mt as u64) 586 } 587 } 588 589 #[derive(Debug, Clone, Copy, PartialEq)] 590 enum Priority { 591 Low = 0, 592 Medium = 1, 593 High = 2, 594 Critical = 3, 595 } 596 597 impl From<Bounded<u16, 2>> for Priority { 598 fn from(value: Bounded<u16, 2>) -> Self { 599 match value & 0x3 { 600 0 => Priority::Low, 601 1 => Priority::Medium, 602 2 => Priority::High, 603 _ => Priority::Critical, 604 } 605 } 606 } 607 608 impl From<Priority> for Bounded<u16, 2> { 609 #[inline(always)] 610 fn from(p: Priority) -> Bounded<u16, 2> { 611 Bounded::from_expr(p as u16) 612 } 613 } 614 615 bitfield! { 616 struct TestU64(u64) { 617 63:63 field_63; 618 61:52 field_61_52; 619 51:16 field_51_16; 620 15:12 field_15_12 ?=> MemoryType; 621 11:9 field_11_9; 622 1:1 field_1; 623 0:0 field_0; 624 } 625 } 626 627 bitfield! { 628 struct TestU16(u16) { 629 15:8 field_15_8; 630 7:4 field_7_4; // Partial overlap with `field_5_4`. 631 5:4 field_5_4 => Priority; 632 3:1 field_3_1; 633 0:0 field_0; 634 } 635 } 636 637 bitfield! { 638 struct TestU8(u8) { 639 7:0 field_7_0; // Full byte overlap. 640 7:4 field_7_4; 641 3:2 field_3_2; 642 1:1 field_1; 643 0:0 field_0; 644 } 645 } 646 647 // Single and multi-bit fields basic access. 648 #[test] 649 fn test_basic_access() { 650 // `TestU64`. 651 let mut val = TestU64::zeroed(); 652 assert_eq!(val.into_raw(), 0x0); 653 654 val = val.with_field_0(true); 655 assert!(val.field_0().into_bool()); 656 assert_eq!(val.into_raw(), 0x1); 657 658 val = val.with_field_1(true); 659 assert!(val.field_1().into_bool()); 660 val = val.with_field_1(false); 661 assert!(!val.field_1().into_bool()); 662 assert_eq!(val.into_raw(), 0x1); 663 664 val = val.with_const_field_11_9::<0x5>(); 665 assert_eq!(val.field_11_9(), 0x5); 666 assert_eq!(val.into_raw(), 0xA01); 667 668 val = val.with_const_field_51_16::<0x123456>(); 669 assert_eq!(val.field_51_16(), 0x123456); 670 assert_eq!(val.into_raw(), 0x0012_3456_0A01); 671 672 const MAX_FIELD_51_16: u64 = ::kernel::bits::genmask_u64(0..=35); 673 val = val.with_const_field_51_16::<{ MAX_FIELD_51_16 }>(); 674 assert_eq!(val.field_51_16(), MAX_FIELD_51_16); 675 676 val = val.with_const_field_61_52::<0x3FF>(); 677 assert_eq!(val.field_61_52(), 0x3FF); 678 679 val = val.with_field_63(true); 680 assert!(val.field_63().into_bool()); 681 682 // `TestU16`. 683 let mut val = TestU16::zeroed(); 684 assert_eq!(val.into_raw(), 0x0); 685 686 val = val.with_field_0(true); 687 assert!(val.field_0().into_bool()); 688 assert_eq!(val.into_raw(), 0x1); 689 690 val = val.with_const_field_3_1::<0x5>(); 691 assert_eq!(val.field_3_1(), 0x5); 692 assert_eq!(val.into_raw(), 0xB); 693 694 val = val.with_const_field_7_4::<0xA>(); 695 assert_eq!(val.field_7_4(), 0xA); 696 assert_eq!(val.into_raw(), 0xAB); 697 698 val = val.with_const_field_15_8::<0x42>(); 699 assert_eq!(val.field_15_8(), 0x42); 700 assert_eq!(val.into_raw(), 0x42AB); 701 702 // `TestU8`. 703 let mut val = TestU8::zeroed(); 704 assert_eq!(val.into_raw(), 0x0); 705 706 val = val.with_field_0(true); 707 assert!(val.field_0().into_bool()); 708 assert_eq!(val.into_raw(), 0x1); 709 710 val = val.with_field_1(true); 711 assert!(val.field_1().into_bool()); 712 assert_eq!(val.into_raw(), 0x3); 713 714 val = val.with_const_field_3_2::<0x3>(); 715 assert_eq!(val.field_3_2(), 0x3); 716 assert_eq!(val.into_raw(), 0xF); 717 718 val = val.with_const_field_7_4::<0xA>(); 719 assert_eq!(val.field_7_4(), 0xA); 720 assert_eq!(val.into_raw(), 0xAF); 721 } 722 723 // `=>` infallible conversion. 724 #[test] 725 fn test_infallible_conversion() { 726 let mut val = TestU16::zeroed(); 727 728 val = val.with_field_5_4(Priority::Low); 729 assert_eq!(val.field_5_4(), Priority::Low); 730 assert_eq!(val.into_raw() & 0x30, 0x00); 731 732 val = val.with_field_5_4(Priority::Medium); 733 assert_eq!(val.field_5_4(), Priority::Medium); 734 assert_eq!(val.into_raw() & 0x30, 0x10); 735 736 val = val.with_field_5_4(Priority::High); 737 assert_eq!(val.field_5_4(), Priority::High); 738 assert_eq!(val.into_raw() & 0x30, 0x20); 739 740 val = val.with_field_5_4(Priority::Critical); 741 assert_eq!(val.field_5_4(), Priority::Critical); 742 assert_eq!(val.into_raw() & 0x30, 0x30); 743 } 744 745 // `?=>` fallible conversion. 746 #[test] 747 fn test_fallible_conversion() { 748 let mut val = TestU64::zeroed(); 749 750 val = val.with_field_15_12(MemoryType::Unmapped); 751 assert_eq!(val.field_15_12(), Ok(MemoryType::Unmapped)); 752 val = val.with_field_15_12(MemoryType::Normal); 753 assert_eq!(val.field_15_12(), Ok(MemoryType::Normal)); 754 val = val.with_field_15_12(MemoryType::Device); 755 assert_eq!(val.field_15_12(), Ok(MemoryType::Device)); 756 val = val.with_field_15_12(MemoryType::Reserved); 757 assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved)); 758 759 // `field_15_12` is 4 bits wide (0-15); `MemoryType` only covers 0-3, so 4-15 return `Err`. 760 let raw = (val.into_raw() & !::kernel::bits::genmask_u64(12..=15)) | (0x7 << 12); 761 assert_eq!(TestU64::from_raw(raw).field_15_12(), Err(0x7)); 762 } 763 764 // Test that setting an overlapping field affects the overlapped one as expected. 765 #[test] 766 fn test_overlapping_fields() { 767 let mut val = TestU16::zeroed(); 768 769 val = val.with_field_5_4(Priority::High); // High == 2 == 0b10. 770 assert_eq!(val.field_5_4(), Priority::High); 771 assert_eq!(val.field_7_4(), 0x2); // Bits 7:6 == 0, bits 5:4 == 0b10. 772 773 val = val.with_const_field_7_4::<0xF>(); 774 assert_eq!(val.field_7_4(), 0xF); 775 assert_eq!(val.field_5_4(), Priority::Critical); // Bits 5:4 == 0b11. 776 777 // `field_7_0` should encompass all other fields. 778 let mut val = TestU8::zeroed() 779 .with_field_0(true) 780 .with_field_1(true) 781 .with_const_field_3_2::<0x3>() 782 .with_const_field_7_4::<0xA>(); 783 assert_eq!(val.into_raw(), 0xAF); 784 785 val = val.with_field_7_0(0x55); 786 assert_eq!(val.field_7_0(), 0x55); 787 assert!(val.field_0().into_bool()); 788 assert!(!val.field_1().into_bool()); 789 assert_eq!(val.field_3_2(), 0x1); 790 assert_eq!(val.field_7_4(), 0x5); 791 } 792 793 // Checks that bits not mapped to any field are left untouched. 794 #[test] 795 fn test_unallocated_bits() { 796 let gap_bits = (1u64 << 62) | 0x1FC; 797 798 let set_all_fields = |val: TestU64| { 799 val.with_field_63(true) 800 .with_const_field_61_52::<0x155>() 801 .with_const_field_51_16::<0x123456>() 802 .with_field_15_12(MemoryType::Device) 803 .with_const_field_11_9::<0x5>() 804 .with_field_1(true) 805 .with_field_0(true) 806 }; 807 808 // Gap bits to 0. 809 let val = set_all_fields(TestU64::from_raw(0)); 810 assert_eq!(val.into_raw() & gap_bits, 0); 811 812 // Gap bits to 1. 813 let val = set_all_fields(TestU64::from_raw(gap_bits)); 814 assert_eq!(val.into_raw() & gap_bits, gap_bits); 815 } 816 817 #[test] 818 fn test_try_with() { 819 let val = TestU64::zeroed().try_with_field_51_16(0x123456).unwrap(); 820 assert_eq!(val.field_51_16(), 0x123456); 821 822 let err = TestU64::zeroed().try_with_field_51_16(u64::MAX); 823 assert_eq!(err, Err(::kernel::error::code::EOVERFLOW)); 824 825 let val = TestU64::zeroed() 826 .try_with_field_51_16(0xABCDEF) 827 .and_then(|p| p.try_with_field_0(1)) 828 .unwrap(); 829 assert_eq!(val.field_51_16(), 0xABCDEF); 830 assert!(val.field_0().into_bool()); 831 } 832 833 // `from_raw`/`into_raw` and `From`/`Into` round-trips. 834 #[test] 835 fn test_raw() { 836 let raw: u64 = 0xBFF0_0000_3123_3E03; 837 let val = TestU64::from_raw(raw); 838 assert_eq!(u64::from(val), raw); 839 assert!(val.field_0().into_bool()); 840 assert!(val.field_1().into_bool()); 841 assert_eq!(val.field_11_9(), 0x7); 842 assert_eq!(val.field_51_16(), 0x3123); 843 assert_eq!(val.field_15_12(), Ok(MemoryType::Reserved)); 844 assert_eq!(val.field_61_52(), 0x3FF); 845 assert!(val.field_63().into_bool()); 846 847 let raw: u16 = 0x42AB; 848 let val = TestU16::from_raw(raw); 849 assert_eq!(u16::from(val), raw); 850 assert!(val.field_0().into_bool()); 851 assert_eq!(val.field_3_1(), 0x5); 852 assert_eq!(val.field_7_4(), 0xA); 853 assert_eq!(val.field_15_8(), 0x42); 854 855 let raw: u8 = 0xAF; 856 let val = TestU8::from_raw(raw); 857 assert_eq!(u8::from(val), raw); 858 assert!(val.field_0().into_bool()); 859 assert!(val.field_1().into_bool()); 860 assert_eq!(val.field_3_2(), 0x3); 861 assert_eq!(val.field_7_4(), 0xA); 862 assert_eq!(val.field_7_0(), 0xAF); 863 } 864 } 865