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