1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Memory-mapped IO. 4 //! 5 //! C header: [`include/asm-generic/io.h`](srctree/include/asm-generic/io.h) 6 7 use core::{ 8 marker::PhantomData, 9 mem::MaybeUninit, // 10 }; 11 12 use crate::{ 13 bindings, 14 prelude::*, 15 ptr::{ 16 Alignment, 17 KnownSize, // 18 }, // 19 }; 20 21 pub mod mem; 22 pub mod poll; 23 pub mod register; 24 pub mod resource; 25 26 pub use crate::register; 27 pub use resource::Resource; 28 29 use register::LocatedRegister; 30 31 /// Physical address type. 32 /// 33 /// This is a type alias to either `u32` or `u64` depending on the config option 34 /// `CONFIG_PHYS_ADDR_T_64BIT`, and it can be a u64 even on 32-bit architectures. 35 pub type PhysAddr = bindings::phys_addr_t; 36 37 /// Resource Size type. 38 /// 39 /// This is a type alias to either `u32` or `u64` depending on the config option 40 /// `CONFIG_PHYS_ADDR_T_64BIT`, and it can be a u64 even on 32-bit architectures. 41 pub type ResourceSize = bindings::resource_size_t; 42 43 /// Untyped I/O region. 44 /// 45 /// This type can be used when an I/O region without known type information has a compile-time known 46 /// minimum size (and a runtime known actual size). 47 /// 48 /// # Invariants 49 /// 50 /// - Size of the region is at least as large as the `SIZE` generic parameter. 51 /// - Size of the region is multiple of 4. 52 #[repr(C, align(4))] 53 #[derive(FromBytes)] 54 pub struct Region<const SIZE: usize = 0> { 55 inner: [u8], 56 } 57 58 impl<const SIZE: usize> Region<SIZE> { 59 /// Create a raw mutable pointer from given base address and size. 60 /// 61 /// `size` should be at least as large as the minimum size `SIZE`, and `base` and `size` should 62 /// be 4-byte aligned to uphold the type invariant. 63 /// 64 /// Just like other methods on raw pointers, it is not unsafe to create a raw pointer 65 /// that does not uphold the type invariants. However such pointers are not valid. 66 #[inline] 67 pub fn ptr_from_raw_parts_mut(base: *mut u8, size: usize) -> *mut Self { 68 core::ptr::slice_from_raw_parts_mut(base, size) as *mut Region<SIZE> 69 } 70 71 /// Create a raw mutable pointer from given base address and size. 72 /// 73 /// The alignment of `base` is checked, and `size` is checked against the minimum size specified 74 /// via const generics. 75 #[inline] 76 pub fn ptr_try_from_raw_parts_mut(base: *mut u8, size: usize) -> Result<*mut Self> { 77 if size < SIZE || base.align_offset(4) != 0 || !size.is_multiple_of(4) { 78 return Err(EINVAL); 79 } 80 81 Ok(Self::ptr_from_raw_parts_mut(base, size)) 82 } 83 } 84 85 impl<const SIZE: usize> KnownSize for Region<SIZE> { 86 const MIN_SIZE: usize = SIZE; 87 // Alignment of 4 is the most common; different base types can be added once required. 88 const MIN_ALIGN: Alignment = Alignment::new::<4>(); 89 90 #[inline(always)] 91 fn size(p: *const Self) -> usize { 92 (p as *const [u8]).len() 93 } 94 } 95 96 // SAFETY: 97 // - Values read from I/O are always treated as initialized. 98 // - Per type invariant the size is multiple of 4 and the type is 4-byte aligned, so it is padding 99 // free. 100 // 101 // This cannot be derived as `derive(IntoBytes)` as the padding free property comes from type 102 // invariant which the macro does not know. 103 unsafe impl<const SIZE: usize> IntoBytes for Region<SIZE> { 104 #[inline] 105 #[allow(unused)] // Rust 1.87+ stops requiring this and will emit unused warnings. 106 fn only_derive_is_allowed_to_implement_this_trait() {} 107 } 108 109 /// Raw representation of an MMIO region. 110 /// 111 /// `MmioRaw<T>` is equivalent to `T __iomem *` in C. 112 /// 113 /// By itself, the existence of an instance of this structure does not provide any guarantees that 114 /// the represented MMIO region does exist or is properly mapped. 115 /// 116 /// Instead, the bus specific MMIO implementation must convert this raw representation into an 117 /// `Mmio` instance providing the actual memory accessors. Only by the conversion into an `Mmio` 118 /// structure any guarantees are given. 119 pub struct MmioRaw<T: ?Sized> { 120 /// Pointer is in I/O address space. 121 /// 122 /// The provenance does not matter, only the address and metadata do. 123 ptr: *mut T, 124 } 125 126 impl<T: ?Sized> Copy for MmioRaw<T> {} 127 impl<T: ?Sized> Clone for MmioRaw<T> { 128 #[inline] 129 fn clone(&self) -> Self { 130 *self 131 } 132 } 133 134 // SAFETY: `MmioRaw` is just an address, so is thread-safe. 135 unsafe impl<T: ?Sized> Send for MmioRaw<T> {} 136 // SAFETY: `MmioRaw` is just an address, so is thread-safe. 137 unsafe impl<T: ?Sized> Sync for MmioRaw<T> {} 138 139 impl<T> MmioRaw<T> { 140 /// Create a `MmioRaw` from address. 141 #[inline] 142 pub fn new(addr: usize) -> Self { 143 Self { 144 ptr: core::ptr::without_provenance_mut(addr), 145 } 146 } 147 } 148 149 impl<const SIZE: usize> MmioRaw<Region<SIZE>> { 150 /// Create a `MmioRaw` representing a I/O region with given size. 151 /// 152 /// The size is checked against the minimum size specified via const generics. 153 #[inline] 154 pub fn new_region(addr: usize, size: usize) -> Result<Self> { 155 Ok(Self { 156 ptr: Region::ptr_try_from_raw_parts_mut(core::ptr::without_provenance_mut(addr), size)?, 157 }) 158 } 159 } 160 161 impl<T: ?Sized + KnownSize> MmioRaw<T> { 162 /// Returns the base address of the MMIO region. 163 #[inline] 164 pub fn addr(&self) -> usize { 165 self.ptr.addr() 166 } 167 168 /// Returns the size of the MMIO region. 169 #[inline] 170 pub fn size(&self) -> usize { 171 KnownSize::size(self.ptr) 172 } 173 } 174 175 /// Checks whether an access of type `U` at the given `base` and the given `offset` 176 /// is valid within this region. 177 /// 178 /// The `base` is used for alignment checking only. This can be set to 0 to skip the check. 179 #[inline] 180 const fn offset_valid<U>(base: usize, offset: usize, size: usize) -> bool { 181 if let Some(end) = offset.checked_add(size_of::<U>()) { 182 end <= size && (base.wrapping_add(offset) % align_of::<U>() == 0) 183 } else { 184 false 185 } 186 } 187 188 /// Returns a view for a given `offset`, performing compile-time bound checks. 189 // Always inline to optimize out error path of `build_assert`. 190 #[inline(always)] 191 fn io_view_assert<'a, IO: Io<'a>, U>( 192 this: IO, 193 offset: usize, 194 ) -> <IO::Backend as IoBackend>::View<'a, U> { 195 // We cannot check alignment with `offset_valid` using `ptr.addr()`. So set 0 for it and 196 // ensure alignment by checking that the alignment of `U` is smaller or equal to the 197 // alignment of `IO::Target`. 198 const_assert!(Alignment::of::<U>().as_usize() <= IO::Target::MIN_ALIGN.as_usize()); 199 build_assert!(offset_valid::<U>(0, offset, IO::Target::MIN_SIZE)); 200 201 let view = this.as_view(); 202 let ptr = IO::Backend::as_ptr(view); 203 let projected_ptr = ptr.cast::<U>().wrapping_byte_add(offset); 204 // SAFETY: `offset_valid` checks for size and alignment and therefore `projected_ptr` is a 205 // valid projection. 206 unsafe { IO::Backend::project_view(view, projected_ptr) } 207 } 208 209 /// Returns a view for a given `offset`, performing runtime bound checks. 210 #[inline] 211 fn io_view<'a, IO: Io<'a>, U>( 212 this: IO, 213 offset: usize, 214 ) -> Result<<IO::Backend as IoBackend>::View<'a, U>> { 215 let view = this.as_view(); 216 let ptr = IO::Backend::as_ptr(view); 217 218 if !offset_valid::<U>(ptr.addr(), offset, KnownSize::size(ptr)) { 219 return Err(EINVAL); 220 } 221 222 let projected_ptr = ptr.cast::<U>().wrapping_byte_add(offset); 223 // SAFETY: `offset_valid` checks for size and alignment and therefore `projected_ptr` is a 224 // valid projection. 225 Ok(unsafe { IO::Backend::project_view(view, projected_ptr) }) 226 } 227 228 /// I/O backends. 229 /// 230 /// This is an abstract representation to be implemented by arbitrary I/O 231 /// backends (e.g. MMIO, PCI config space, etc.). 232 /// 233 /// The base trait only defines the projection operations; which I/O methods are available depends 234 /// on which [`IoCapable<T>`] traits are implemented for the type. For example, for MMIO regions, 235 /// all widths (u8, u16, u32, and u64 on 64-bit systems) are typically supported. For PCI 236 /// configuration space, u8, u16, and u32 are supported but u64 is not. 237 /// 238 /// This trait is separate from the `Io` trait as multiple different I/O types may share the same 239 /// operation. 240 pub trait IoBackend { 241 /// View type for this I/O backend. 242 type View<'a, T: ?Sized + KnownSize>: IoBase<'a, Backend = Self, Target = T>; 243 244 /// Convert a `view` to a raw pointer for projection. 245 /// 246 /// The returned pointer is private implementation detail of the backend; it is likely not 247 /// valid. It should not be dereferenced. 248 fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T; 249 250 /// Project `view` to its subregion indicated by `ptr`. 251 /// 252 /// If input `view` is valid, returned view must also be valid. 253 /// 254 /// # Safety 255 /// 256 /// `ptr` must be a projection of `Self::as_ptr(view)`. 257 unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>( 258 view: Self::View<'a, T>, 259 ptr: *mut U, 260 ) -> Self::View<'a, U>; 261 } 262 263 /// Trait indicating that an I/O backend supports operations of a certain type and providing an 264 /// implementation for these operations. 265 /// 266 /// Different I/O backends can implement this trait to expose only the operations they support. 267 /// 268 /// For example, a PCI configuration space may implement `IoCapable<u8>`, `IoCapable<u16>`, 269 /// and `IoCapable<u32>`, but not `IoCapable<u64>`, while an MMIO region on a 64-bit 270 /// system might implement all four. 271 pub trait IoCapable<T>: IoBackend { 272 /// Performs an I/O read of type `T` at `view` and returns the result. 273 fn io_read<'a>(view: Self::View<'a, T>) -> T; 274 275 /// Performs an I/O write of `value` at `view`. 276 fn io_write<'a>(view: Self::View<'a, T>, value: T); 277 } 278 279 /// Trait indicating that an I/O backend supports memory copy operations. 280 pub trait IoCopyable: IoBackend { 281 /// Copy contents of `view` to `buffer`. 282 /// 283 /// # Safety 284 /// 285 /// - `buffer` is valid for volatile write for `view.size()` bytes. 286 /// - `buffer` should not overlap with `view`. 287 unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8); 288 289 /// Copy contents from `buffer` to `view`. 290 /// 291 /// # Safety 292 /// 293 /// - `buffer` is valid for volatile read for `view.size()` bytes. 294 /// - `buffer` should not overlap with `view`. 295 unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8); 296 297 /// Copy from `view` and return the value. 298 #[inline] 299 fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { 300 // Project `self` to `[u8]`. 301 let ptr = Self::as_ptr(view); 302 // SAFETY: This is a identity projection. 303 let slice_view = unsafe { 304 Self::project_view( 305 view, 306 core::ptr::slice_from_raw_parts_mut::<u8>(ptr.cast(), size_of::<T>()), 307 ) 308 }; 309 310 let mut buf = MaybeUninit::<T>::uninit(); 311 // SAFETY: 312 // - `buf.as_mut_ptr()` is valid for write for `size_of::<T>()` bytes. 313 // - `buf` is local so `buf.as_mut_ptr()` cannot overlap with `slice_view`. 314 unsafe { Self::copy_from_io(slice_view, buf.as_mut_ptr().cast()) }; 315 // SAFETY: `T: FromBytes` guarantee that all bit patterns are valid. 316 unsafe { buf.assume_init() } 317 } 318 319 /// Copy `value` to `view`. 320 /// 321 /// Destructor of `value` will not be executed, consistent with [`zerocopy::transmute`]. 322 #[inline] 323 fn copy_write<T: IntoBytes>(view: Self::View<'_, T>, value: T) { 324 // Project `self` to `[u8]`. 325 let ptr = Self::as_ptr(view); 326 // SAFETY: This is a identity projection. 327 let slice_view = unsafe { 328 Self::project_view( 329 view, 330 core::ptr::slice_from_raw_parts_mut::<u8>(ptr.cast(), size_of::<T>()), 331 ) 332 }; 333 334 // SAFETY: 335 // - `&raw const value` is valid for read for `size_of::<T>()` bytes. 336 // - `value` is local so `&raw const value` cannot overlap with `slice_view`. 337 unsafe { Self::copy_to_io(slice_view, (&raw const value).cast()) }; 338 core::mem::forget(value); 339 } 340 } 341 342 /// Describes a given I/O location: its offset, width, and type to convert the raw value from and 343 /// into. 344 /// 345 /// This trait is the key abstraction allowing [`Io::read`], [`Io::write`], and [`Io::update`] (and 346 /// their fallible [`try_read`](Io::try_read), [`try_write`](Io::try_write) and 347 /// [`try_update`](Io::try_update) counterparts) to work uniformly with both raw [`usize`] offsets 348 /// (for primitive types like [`u32`]) and typed ones (like those generated by the [`register!`] 349 /// macro). 350 /// 351 /// An `IoLoc<Base, T>` carries the following pieces of information: 352 /// 353 /// - The valid `Base` to operate on. For most registers, this should be [`Region`]. 354 /// - The offset to access (returned by [`IoLoc::offset`]), 355 /// - The width of the access (determined by [`IoLoc::IoType`]), 356 /// - The type `T` in which the raw data is returned or provided. 357 /// 358 /// `T` and `IoLoc::IoType` may differ: for instance, a typed register has `T` = the register type 359 /// with its bitfields, and `IoType` = its backing primitive (e.g. `u32`). 360 pub trait IoLoc<Base: ?Sized, T> { 361 /// Size ([`u8`], [`u16`], etc) of the I/O performed on the returned [`offset`](IoLoc::offset). 362 type IoType: Into<T> + From<T>; 363 364 /// Consumes `self` and returns the offset of this location. 365 fn offset(self) -> usize; 366 } 367 368 /// Implements [`IoLoc<Region<SIZE>, $ty>`] for [`usize`], allowing [`usize`] to be used as a 369 /// parameter of [`Io::read`] and [`Io::write`]. 370 macro_rules! impl_usize_ioloc { 371 ($($ty:ty),*) => { 372 $( 373 impl<const SIZE: usize> IoLoc<Region<SIZE>, $ty> for usize { 374 type IoType = $ty; 375 376 #[inline(always)] 377 fn offset(self) -> usize { 378 self 379 } 380 } 381 )* 382 } 383 } 384 385 // Provide the ability to read any primitive type from a [`usize`]. 386 impl_usize_ioloc!(u8, u16, u32, u64); 387 388 /// Types implementing this trait (e.g. MMIO BARs or PCI config regions) 389 /// can perform I/O operations on regions of memory. 390 /// 391 /// This trait defines which backend shall be used for I/O operations and provides a method to 392 /// convert into [`IoBackend::View`]. Users should use the [`Io`] trait which provides the actual 393 /// methods to perform I/O operations. 394 /// 395 /// This should be implemented on cheaply copyable handles, such as references or view types. 396 pub trait IoBase<'a>: Copy { 397 /// Type that defines all I/O operations. 398 type Backend: IoBackend; 399 400 /// Type of this I/O region. For untyped regions, [`Region`] can be used. 401 type Target: ?Sized + KnownSize; 402 403 /// Return a view that covers the full region. 404 fn as_view(self) -> <Self::Backend as IoBackend>::View<'a, Self::Target>; 405 } 406 407 /// Extension trait to provide I/O operation methods to types that implement [`IoBase`]. 408 /// 409 /// This trait provides: 410 /// - Helper methods for offset validation and address calculation 411 /// - Fallible (runtime checked) accessors for different data widths 412 /// 413 /// Which I/O methods are available depends on the associated [`IoBackend`] implementation. 414 pub trait Io<'a>: IoBase<'a> { 415 /// Returns the size of this I/O region. 416 #[inline] 417 fn size(self) -> usize { 418 KnownSize::size(Self::Backend::as_ptr(self.as_view())) 419 } 420 421 /// Returns the length of the slice in number of elements. 422 #[inline] 423 fn len<T>(self) -> usize 424 where 425 Self: Io<'a, Target = [T]>, 426 { 427 Self::Backend::as_ptr(self.as_view()).len() 428 } 429 430 /// Returns `true` if the slice has a length of 0. 431 #[inline] 432 fn is_empty<T>(self) -> bool 433 where 434 Self: Io<'a, Target = [T]>, 435 { 436 self.len() == 0 437 } 438 439 /// Try to convert into a different typed I/O view. 440 /// 441 /// A runtime check is performed to ensure that the target type is of same or smaller size to 442 /// current type, and the current view is properly aligned for the target type. Returns 443 /// `Err(EINVAL)` if the runtime check fails. 444 /// 445 /// # Examples 446 /// 447 /// ```no_run 448 /// use kernel::io::{ 449 /// io_project, 450 /// Mmio, 451 /// Io, 452 /// Region, 453 /// }; 454 /// #[derive(FromBytes, IntoBytes)] 455 /// #[repr(C)] 456 /// struct MyStruct { field: u32, } 457 /// 458 /// # fn test(mmio: &Mmio<'_, Region>) -> Result { 459 /// // let mmio: Mmio<'_, Region>; 460 /// let whole: Mmio<'_, MyStruct> = mmio.try_cast()?; 461 /// # Ok::<(), Error>(()) } 462 /// ``` 463 #[inline] 464 fn try_cast<U>(self) -> Result<<Self::Backend as IoBackend>::View<'a, U>> 465 where 466 Self::Target: FromBytes + IntoBytes, 467 U: FromBytes + IntoBytes, 468 { 469 let view = self.as_view(); 470 let ptr = Self::Backend::as_ptr(view); 471 472 if size_of::<U>() > KnownSize::size(ptr) { 473 return Err(EINVAL); 474 } 475 476 if ptr.addr() % align_of::<U>() != 0 { 477 return Err(EINVAL); 478 } 479 480 // SAFETY: We have checked bounds and alignment, so this is a valid projection. 481 Ok(unsafe { Self::Backend::project_view(view, ptr.cast()) }) 482 } 483 484 /// Read a value from I/O. 485 /// 486 /// This only works for primitives supported by the I/O backend. 487 /// 488 /// # Examples 489 /// 490 /// ```no_run 491 /// # use kernel::io::*; 492 /// # fn test_read_val(mmio: Mmio<'_, u32>) { 493 /// // let mmio: Mmio<'_, u32>; 494 /// let val: u32 = mmio.read_val(); 495 /// # } 496 /// ``` 497 #[inline] 498 fn read_val(self) -> Self::Target 499 where 500 Self::Backend: IoCapable<Self::Target>, 501 Self::Target: Sized, 502 { 503 Self::Backend::io_read(self.as_view()) 504 } 505 506 /// Write a value to I/O. 507 /// 508 /// This only works for primitives supported by the I/O backend. 509 /// 510 /// # Examples 511 /// 512 /// ```no_run 513 /// # use kernel::io::*; 514 /// # fn test_write_val(mmio: Mmio<'_, u32>) { 515 /// // let mmio: Mmio<'_, u32>; 516 /// mmio.write_val(1u32); 517 /// # } 518 /// ``` 519 #[inline] 520 fn write_val(self, value: Self::Target) 521 where 522 Self::Backend: IoCapable<Self::Target>, 523 Self::Target: Sized, 524 { 525 Self::Backend::io_write(self.as_view(), value) 526 } 527 528 /// Copy-read from I/O memory. 529 /// 530 /// This is equivalent to reading from the I/O memory with byte-wise copy, although the actual 531 /// implementation might be more efficient. There is no atomicity guarantee. Note that for some 532 /// backends (e.g. `Mmio`), this can read different value compared to [`read_val`] as 533 /// byte-swapping is not performed. 534 /// 535 /// [`read_val`]: Io::read_val 536 /// 537 /// # Examples 538 /// 539 /// ```no_run 540 /// # use kernel::io::*; 541 /// # fn test_copy_read(mmio: Mmio<'_, [u8; 6]>) { 542 /// // let mmio: Mmio<'_, [u8; 6]>; 543 /// let val: [u8; 6] = mmio.copy_read(); 544 /// # } 545 /// ``` 546 #[inline] 547 fn copy_read(self) -> Self::Target 548 where 549 Self::Backend: IoCopyable, 550 Self::Target: Sized + FromBytes, 551 { 552 Self::Backend::copy_read(self.as_view()) 553 } 554 555 /// Copy-write to I/O memory. 556 /// 557 /// This is equivalent to writing to the I/O memory with byte-wise copy, although the actual 558 /// implementation might be more efficient. There is no atomicity guarantee. Note that for some 559 /// backends (e.g. `Mmio`), this can write different value compared to [`write_val`] as 560 /// byte-swapping is not performed. 561 /// 562 /// [`write_val`]: Io::write_val 563 /// 564 /// # Examples 565 /// 566 /// ```no_run 567 /// # use kernel::io::*; 568 /// # fn test_copy_write(mmio: Mmio<'_, [u8; 6]>) { 569 /// // let mmio: Mmio<'_, [u8; 6]>; 570 /// mmio.copy_write([0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]); 571 /// # } 572 /// ``` 573 #[inline] 574 fn copy_write(self, value: Self::Target) 575 where 576 Self::Backend: IoCopyable, 577 Self::Target: Sized + IntoBytes, 578 { 579 Self::Backend::copy_write(self.as_view(), value); 580 } 581 582 /// Copy bytes from `data` to I/O memory. 583 /// 584 /// # Panics 585 /// 586 /// This function will panic if the length of `self` differs from the length of `data`, similar 587 /// to [`[u8]::copy_from_slice`]. 588 /// 589 /// # Examples 590 /// 591 /// ```no_run 592 /// # use kernel::io::*; 593 /// # fn test_copy_write(mmio: Mmio<'_, [u8]>) { 594 /// // let mmio: Mmio<'_, [u8]>; 595 /// mmio.copy_from_slice(&[0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]); 596 /// # } 597 /// ``` 598 #[inline] 599 fn copy_from_slice(self, data: &[u8]) 600 where 601 Self::Backend: IoCopyable, 602 Self: Io<'a, Target = [u8]>, 603 { 604 assert_eq!(self.len(), data.len()); 605 606 // SAFETY: `data.as_ptr()` is valid for read for `self.size()` bytes. 607 unsafe { 608 Self::Backend::copy_to_io(self.as_view(), data.as_ptr()); 609 } 610 } 611 612 /// Copy bytes from I/O memory to `data`. 613 /// 614 /// # Panics 615 /// 616 /// This function will panic if the length of `self` differs from the length of `data`, similar 617 /// to [`[u8]::copy_from_slice`]. 618 /// 619 /// # Examples 620 /// 621 /// ```no_run 622 /// # use kernel::io::*; 623 /// # fn test_copy_write(mmio: Mmio<'_, [u8]>) { 624 /// // let mmio: Mmio<'_, [u8]>; 625 /// let mut buf = [0; 6]; 626 /// mmio.copy_to_slice(&mut buf); 627 /// # } 628 /// ``` 629 #[inline] 630 fn copy_to_slice(self, data: &mut [u8]) 631 where 632 Self::Backend: IoCopyable, 633 Self: Io<'a, Target = [u8]>, 634 { 635 assert_eq!(self.len(), data.len()); 636 637 // SAFETY: `data.as_mut_ptr()` is valid for write for `self.size()` bytes. 638 unsafe { 639 Self::Backend::copy_from_io(self.as_view(), data.as_mut_ptr()); 640 } 641 } 642 643 /// Fallible 8-bit read with runtime bounds check. 644 #[inline(always)] 645 fn try_read8(self, offset: usize) -> Result<u8> 646 where 647 usize: IoLoc<Self::Target, u8, IoType = u8>, 648 Self::Backend: IoCapable<u8>, 649 { 650 self.try_read(offset) 651 } 652 653 /// Fallible 16-bit read with runtime bounds check. 654 #[inline(always)] 655 fn try_read16(self, offset: usize) -> Result<u16> 656 where 657 usize: IoLoc<Self::Target, u16, IoType = u16>, 658 Self::Backend: IoCapable<u16>, 659 { 660 self.try_read(offset) 661 } 662 663 /// Fallible 32-bit read with runtime bounds check. 664 #[inline(always)] 665 fn try_read32(self, offset: usize) -> Result<u32> 666 where 667 usize: IoLoc<Self::Target, u32, IoType = u32>, 668 Self::Backend: IoCapable<u32>, 669 { 670 self.try_read(offset) 671 } 672 673 /// Fallible 64-bit read with runtime bounds check. 674 #[inline(always)] 675 fn try_read64(self, offset: usize) -> Result<u64> 676 where 677 usize: IoLoc<Self::Target, u64, IoType = u64>, 678 Self::Backend: IoCapable<u64>, 679 { 680 self.try_read(offset) 681 } 682 683 /// Fallible 8-bit write with runtime bounds check. 684 #[inline(always)] 685 fn try_write8(self, value: u8, offset: usize) -> Result 686 where 687 usize: IoLoc<Self::Target, u8, IoType = u8>, 688 Self::Backend: IoCapable<u8>, 689 { 690 self.try_write(offset, value) 691 } 692 693 /// Fallible 16-bit write with runtime bounds check. 694 #[inline(always)] 695 fn try_write16(self, value: u16, offset: usize) -> Result 696 where 697 usize: IoLoc<Self::Target, u16, IoType = u16>, 698 Self::Backend: IoCapable<u16>, 699 { 700 self.try_write(offset, value) 701 } 702 703 /// Fallible 32-bit write with runtime bounds check. 704 #[inline(always)] 705 fn try_write32(self, value: u32, offset: usize) -> Result 706 where 707 usize: IoLoc<Self::Target, u32, IoType = u32>, 708 Self::Backend: IoCapable<u32>, 709 { 710 self.try_write(offset, value) 711 } 712 713 /// Fallible 64-bit write with runtime bounds check. 714 #[inline(always)] 715 fn try_write64(self, value: u64, offset: usize) -> Result 716 where 717 usize: IoLoc<Self::Target, u64, IoType = u64>, 718 Self::Backend: IoCapable<u64>, 719 { 720 self.try_write(offset, value) 721 } 722 723 /// Infallible 8-bit read with compile-time bounds check. 724 #[inline(always)] 725 fn read8(self, offset: usize) -> u8 726 where 727 usize: IoLoc<Self::Target, u8, IoType = u8>, 728 Self::Backend: IoCapable<u8>, 729 { 730 self.read(offset) 731 } 732 733 /// Infallible 16-bit read with compile-time bounds check. 734 #[inline(always)] 735 fn read16(self, offset: usize) -> u16 736 where 737 usize: IoLoc<Self::Target, u16, IoType = u16>, 738 Self::Backend: IoCapable<u16>, 739 { 740 self.read(offset) 741 } 742 743 /// Infallible 32-bit read with compile-time bounds check. 744 #[inline(always)] 745 fn read32(self, offset: usize) -> u32 746 where 747 usize: IoLoc<Self::Target, u32, IoType = u32>, 748 Self::Backend: IoCapable<u32>, 749 { 750 self.read(offset) 751 } 752 753 /// Infallible 64-bit read with compile-time bounds check. 754 #[inline(always)] 755 fn read64(self, offset: usize) -> u64 756 where 757 usize: IoLoc<Self::Target, u64, IoType = u64>, 758 Self::Backend: IoCapable<u64>, 759 { 760 self.read(offset) 761 } 762 763 /// Infallible 8-bit write with compile-time bounds check. 764 #[inline(always)] 765 fn write8(self, value: u8, offset: usize) 766 where 767 usize: IoLoc<Self::Target, u8, IoType = u8>, 768 Self::Backend: IoCapable<u8>, 769 { 770 self.write(offset, value) 771 } 772 773 /// Infallible 16-bit write with compile-time bounds check. 774 #[inline(always)] 775 fn write16(self, value: u16, offset: usize) 776 where 777 usize: IoLoc<Self::Target, u16, IoType = u16>, 778 Self::Backend: IoCapable<u16>, 779 { 780 self.write(offset, value) 781 } 782 783 /// Infallible 32-bit write with compile-time bounds check. 784 #[inline(always)] 785 fn write32(self, value: u32, offset: usize) 786 where 787 usize: IoLoc<Self::Target, u32, IoType = u32>, 788 Self::Backend: IoCapable<u32>, 789 { 790 self.write(offset, value) 791 } 792 793 /// Infallible 64-bit write with compile-time bounds check. 794 #[inline(always)] 795 fn write64(self, value: u64, offset: usize) 796 where 797 usize: IoLoc<Self::Target, u64, IoType = u64>, 798 Self::Backend: IoCapable<u64>, 799 { 800 self.write(offset, value) 801 } 802 803 /// Generic fallible read with runtime bounds check. 804 /// 805 /// # Examples 806 /// 807 /// Read a primitive type from an I/O address: 808 /// 809 /// ```no_run 810 /// use kernel::io::{ 811 /// Io, 812 /// Mmio, 813 /// Region, 814 /// }; 815 /// 816 /// fn do_reads(io: Mmio<'_, Region>) -> Result { 817 /// // 32-bit read from address `0x10`. 818 /// let v: u32 = io.try_read(0x10)?; 819 /// 820 /// // 8-bit read from address `0xfff`. 821 /// let v: u8 = io.try_read(0xfff)?; 822 /// 823 /// Ok(()) 824 /// } 825 /// ``` 826 #[inline(always)] 827 fn try_read<T, L>(self, location: L) -> Result<T> 828 where 829 L: IoLoc<Self::Target, T>, 830 Self::Backend: IoCapable<L::IoType>, 831 { 832 let view = io_view::<Self, L::IoType>(self, location.offset())?; 833 Ok(Self::Backend::io_read(view).into()) 834 } 835 836 /// Generic fallible write with runtime bounds check. 837 /// 838 /// # Examples 839 /// 840 /// Write a primitive type to an I/O address: 841 /// 842 /// ```no_run 843 /// use kernel::io::{ 844 /// Io, 845 /// Mmio, 846 /// Region, 847 /// }; 848 /// 849 /// fn do_writes(io: Mmio<'_, Region>) -> Result { 850 /// // 32-bit write of value `1` at address `0x10`. 851 /// io.try_write(0x10, 1u32)?; 852 /// 853 /// // 8-bit write of value `0xff` at address `0xfff`. 854 /// io.try_write(0xfff, 0xffu8)?; 855 /// 856 /// Ok(()) 857 /// } 858 /// ``` 859 #[inline(always)] 860 fn try_write<T, L>(self, location: L, value: T) -> Result 861 where 862 L: IoLoc<Self::Target, T>, 863 Self::Backend: IoCapable<L::IoType>, 864 { 865 let view = io_view::<Self, L::IoType>(self, location.offset())?; 866 let io_value = value.into(); 867 Self::Backend::io_write(view, io_value); 868 Ok(()) 869 } 870 871 /// Generic fallible write of a fully-located register value. 872 /// 873 /// # Examples 874 /// 875 /// Tuples carrying a location and a value can be used with this method: 876 /// 877 /// ```no_run 878 /// use kernel::io::{ 879 /// register, 880 /// Io, 881 /// Mmio, 882 /// Region, 883 /// }; 884 /// 885 /// register! { 886 /// VERSION(u32) @ 0x100 { 887 /// 15:8 major; 888 /// 7:0 minor; 889 /// } 890 /// } 891 /// 892 /// impl VERSION { 893 /// fn new(major: u8, minor: u8) -> Self { 894 /// VERSION::zeroed().with_major(major).with_minor(minor) 895 /// } 896 /// } 897 /// 898 /// fn do_write_reg(io: Mmio<'_, Region>) -> Result { 899 /// 900 /// io.try_write_reg(VERSION::new(1, 0)) 901 /// } 902 /// ``` 903 #[inline(always)] 904 fn try_write_reg<T, L, V>(self, value: V) -> Result 905 where 906 L: IoLoc<Self::Target, T>, 907 V: LocatedRegister<Self::Target, Location = L, Value = T>, 908 Self::Backend: IoCapable<L::IoType>, 909 { 910 let (location, value) = value.into_io_op(); 911 912 self.try_write(location, value) 913 } 914 915 /// Generic fallible update with runtime bounds check. 916 /// 917 /// Note: this does not perform any synchronization. The caller is responsible for ensuring 918 /// exclusive access if required. 919 /// 920 /// # Examples 921 /// 922 /// Read the u32 value at address `0x10`, increment it, and store the updated value back: 923 /// 924 /// ```no_run 925 /// use kernel::io::{ 926 /// Io, 927 /// Mmio, 928 /// Region, 929 /// }; 930 /// 931 /// fn do_update(io: Mmio<'_, Region<0x1000>>) -> Result { 932 /// io.try_update(0x10, |v: u32| { 933 /// v + 1 934 /// }) 935 /// } 936 /// ``` 937 #[inline(always)] 938 fn try_update<T, L, F>(self, location: L, f: F) -> Result 939 where 940 L: IoLoc<Self::Target, T>, 941 Self::Backend: IoCapable<L::IoType>, 942 F: FnOnce(T) -> T, 943 { 944 let view = io_view::<Self, L::IoType>(self, location.offset())?; 945 946 let value: T = Self::Backend::io_read(view).into(); 947 let io_value = f(value).into(); 948 Self::Backend::io_write(view, io_value); 949 950 Ok(()) 951 } 952 953 /// Generic infallible read with compile-time bounds check. 954 /// 955 /// # Examples 956 /// 957 /// Read a primitive type from an I/O address: 958 /// 959 /// ```no_run 960 /// use kernel::io::{ 961 /// Io, 962 /// Mmio, 963 /// Region, 964 /// }; 965 /// 966 /// fn do_reads(io: Mmio<'_, Region<0x1000>>) { 967 /// // 32-bit read from address `0x10`. 968 /// let v: u32 = io.read(0x10); 969 /// 970 /// // 8-bit read from the top of the I/O space. 971 /// let v: u8 = io.read(0xfff); 972 /// } 973 /// ``` 974 #[inline(always)] 975 fn read<T, L>(self, location: L) -> T 976 where 977 L: IoLoc<Self::Target, T>, 978 Self::Backend: IoCapable<L::IoType>, 979 { 980 let view = io_view_assert::<Self, L::IoType>(self, location.offset()); 981 Self::Backend::io_read(view).into() 982 } 983 984 /// Generic infallible write with compile-time bounds check. 985 /// 986 /// # Examples 987 /// 988 /// Write a primitive type to an I/O address: 989 /// 990 /// ```no_run 991 /// use kernel::io::{ 992 /// Io, 993 /// Mmio, 994 /// Region, 995 /// }; 996 /// 997 /// fn do_writes(io: Mmio<'_, Region<0x1000>>) { 998 /// // 32-bit write of value `1` at address `0x10`. 999 /// io.write(0x10, 1u32); 1000 /// 1001 /// // 8-bit write of value `0xff` at the top of the I/O space. 1002 /// io.write(0xfff, 0xffu8); 1003 /// } 1004 /// ``` 1005 #[inline(always)] 1006 fn write<T, L>(self, location: L, value: T) 1007 where 1008 L: IoLoc<Self::Target, T>, 1009 Self::Backend: IoCapable<L::IoType>, 1010 { 1011 let view = io_view_assert::<Self, L::IoType>(self, location.offset()); 1012 let io_value = value.into(); 1013 Self::Backend::io_write(view, io_value); 1014 } 1015 1016 /// Generic infallible write of a fully-located register value. 1017 /// 1018 /// # Examples 1019 /// 1020 /// Tuples carrying a location and a value can be used with this method: 1021 /// 1022 /// ```no_run 1023 /// use kernel::io::{ 1024 /// register, 1025 /// Io, 1026 /// Mmio, 1027 /// Region, 1028 /// }; 1029 /// 1030 /// register! { 1031 /// VERSION(u32) @ 0x100 { 1032 /// 15:8 major; 1033 /// 7:0 minor; 1034 /// } 1035 /// } 1036 /// 1037 /// impl VERSION { 1038 /// fn new(major: u8, minor: u8) -> Self { 1039 /// VERSION::zeroed().with_major(major).with_minor(minor) 1040 /// } 1041 /// } 1042 /// 1043 /// fn do_write_reg(io: Mmio<'_, Region<0x1000>>) { 1044 /// io.write_reg(VERSION::new(1, 0)); 1045 /// } 1046 /// ``` 1047 #[inline(always)] 1048 fn write_reg<T, L, V>(self, value: V) 1049 where 1050 L: IoLoc<Self::Target, T>, 1051 V: LocatedRegister<Self::Target, Location = L, Value = T>, 1052 Self::Backend: IoCapable<L::IoType>, 1053 { 1054 let (location, value) = value.into_io_op(); 1055 1056 self.write(location, value) 1057 } 1058 1059 /// Generic infallible update with compile-time bounds check. 1060 /// 1061 /// Note: this does not perform any synchronization. The caller is responsible for ensuring 1062 /// exclusive access if required. 1063 /// 1064 /// # Examples 1065 /// 1066 /// Read the u32 value at address `0x10`, increment it, and store the updated value back: 1067 /// 1068 /// ```no_run 1069 /// use kernel::io::{ 1070 /// Io, 1071 /// Mmio, 1072 /// Region, 1073 /// }; 1074 /// 1075 /// fn do_update(io: Mmio<'_, Region<0x1000>>) { 1076 /// io.update(0x10, |v: u32| { 1077 /// v + 1 1078 /// }) 1079 /// } 1080 /// ``` 1081 #[inline(always)] 1082 fn update<T, L, F>(self, location: L, f: F) 1083 where 1084 L: IoLoc<Self::Target, T>, 1085 Self::Backend: IoCapable<L::IoType>, 1086 F: FnOnce(T) -> T, 1087 { 1088 let view = io_view_assert::<Self, L::IoType>(self, location.offset()); 1089 let value: T = Self::Backend::io_read(view).into(); 1090 let io_value = f(value).into(); 1091 Self::Backend::io_write(view, io_value); 1092 } 1093 } 1094 1095 // Blanket implementation ensures that provided methods cannot be arbitrarily overridden by 1096 // implementers, which is relied upon for correctness and soundness. 1097 impl<'a, T: IoBase<'a>> Io<'a> for T {} 1098 1099 /// A view of memory-mapped I/O region. 1100 /// 1101 /// # Invariant 1102 /// 1103 /// `ptr` points to a valid and aligned memory-mapped I/O region for the duration lifetime `'a`. 1104 pub struct Mmio<'a, T: ?Sized> { 1105 ptr: *mut T, 1106 phantom: PhantomData<&'a ()>, 1107 } 1108 1109 impl<T: ?Sized> Copy for Mmio<'_, T> {} 1110 impl<T: ?Sized> Clone for Mmio<'_, T> { 1111 #[inline] 1112 fn clone(&self) -> Self { 1113 *self 1114 } 1115 } 1116 1117 impl<'a, T: ?Sized> Mmio<'a, T> { 1118 /// Create a `Mmio`, providing the accessors to the MMIO mapping. 1119 /// 1120 /// # Safety 1121 /// 1122 /// `raw` represents a valid and aligned memory-mapped I/O region while `'a` is alive. 1123 #[inline] 1124 pub unsafe fn from_raw(raw: MmioRaw<T>) -> Self { 1125 // INVARIANT: Per safety requirement. 1126 Self { 1127 ptr: raw.ptr, 1128 phantom: PhantomData, 1129 } 1130 } 1131 } 1132 1133 // SAFETY: `Mmio<'_, T>` is conceptually `&T` but in I/O memory. 1134 unsafe impl<T: ?Sized + Sync> Send for Mmio<'_, T> {} 1135 1136 // SAFETY: `Mmio<'_, T>` is conceptually `&T` but in I/O memory. 1137 unsafe impl<T: ?Sized + Sync> Sync for Mmio<'_, T> {} 1138 1139 impl<'a, T: ?Sized + KnownSize> IoBase<'a> for Mmio<'a, T> { 1140 type Backend = MmioBackend; 1141 type Target = T; 1142 1143 #[inline] 1144 fn as_view(self) -> Mmio<'a, T> { 1145 self 1146 } 1147 } 1148 1149 /// I/O Backend for memory-mapped I/O. 1150 pub struct MmioBackend; 1151 1152 impl IoBackend for MmioBackend { 1153 type View<'a, T: ?Sized + KnownSize> = Mmio<'a, T>; 1154 1155 #[inline] 1156 fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T { 1157 view.ptr 1158 } 1159 1160 #[inline] 1161 unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>( 1162 _view: Self::View<'a, T>, 1163 ptr: *mut U, 1164 ) -> Self::View<'a, U> { 1165 // INVARIANT: Per safety requirement, `ptr` is projection from `view`, so it is also a valid 1166 // memory-mapped I/O region. 1167 Mmio { 1168 ptr, 1169 phantom: PhantomData, 1170 } 1171 } 1172 } 1173 1174 /// Implements [`IoCapable`] on `$backend` for `$ty` using `$read_fn` and `$write_fn`. 1175 macro_rules! impl_mmio_io_capable { 1176 ($backend: ident, $ty:ty, $read_fn:ident, $write_fn:ident) => { 1177 impl IoCapable<$ty> for $backend { 1178 #[inline] 1179 fn io_read(view: <$backend as IoBackend>::View<'_, $ty>) -> $ty { 1180 // SAFETY: `$backend::as_ptr(view)` is a valid pointer for MMIO operations for both 1181 // `MmioBackend` and `RelaxedMmioBackend`. 1182 unsafe { bindings::$read_fn($backend::as_ptr(view).cast_const().cast()) } 1183 } 1184 1185 #[inline] 1186 fn io_write(view: <$backend as IoBackend>::View<'_, $ty>, value: $ty) { 1187 // SAFETY: `$backend::as_ptr(view)` is a valid pointer for MMIO operations for both 1188 // `MmioBackend` and `RelaxedMmioBackend`. 1189 unsafe { bindings::$write_fn(value, $backend::as_ptr(view).cast()) } 1190 } 1191 } 1192 }; 1193 } 1194 1195 // MMIO regions support 8, 16, and 32-bit accesses. 1196 impl_mmio_io_capable!(MmioBackend, u8, readb, writeb); 1197 impl_mmio_io_capable!(MmioBackend, u16, readw, writew); 1198 impl_mmio_io_capable!(MmioBackend, u32, readl, writel); 1199 // MMIO regions on 64-bit systems also support 64-bit accesses. 1200 #[cfg(CONFIG_64BIT)] 1201 impl_mmio_io_capable!(MmioBackend, u64, readq, writeq); 1202 1203 impl IoCopyable for MmioBackend { 1204 #[inline] 1205 unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { 1206 // SAFETY: 1207 // - `view.ptr` is valid MMIO memory for `view.size()` bytes. 1208 // - `buffer` is valid for write for `view.size()` bytes. 1209 unsafe { 1210 bindings::memcpy_fromio(buffer.cast(), view.ptr.cast(), view.size()); 1211 } 1212 } 1213 1214 #[inline] 1215 unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { 1216 // SAFETY: 1217 // - `view.ptr` is valid MMIO memory for `view.size()` bytes. 1218 // - `buffer` is valid for read for `view.size()` bytes. 1219 unsafe { 1220 bindings::memcpy_toio(view.ptr.cast(), buffer.cast(), view.size()); 1221 } 1222 } 1223 } 1224 1225 /// [`Mmio`] but using relaxed accessors. 1226 /// 1227 /// This type provides an implementation of [`Io`] that uses relaxed I/O MMIO operands instead of 1228 /// the regular ones. 1229 /// 1230 /// See [`Mmio::relaxed`] for a usage example. 1231 pub struct RelaxedMmio<'a, T: ?Sized>(Mmio<'a, T>); 1232 1233 impl<T: ?Sized> Copy for RelaxedMmio<'_, T> {} 1234 impl<T: ?Sized> Clone for RelaxedMmio<'_, T> { 1235 #[inline] 1236 fn clone(&self) -> Self { 1237 *self 1238 } 1239 } 1240 1241 /// I/O Backend for memory-mapped I/O, with relaxed access semantics. 1242 pub struct RelaxedMmioBackend; 1243 1244 impl IoBackend for RelaxedMmioBackend { 1245 type View<'a, T: ?Sized + KnownSize> = RelaxedMmio<'a, T>; 1246 1247 #[inline] 1248 fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T { 1249 MmioBackend::as_ptr(view.0) 1250 } 1251 1252 #[inline] 1253 unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>( 1254 view: Self::View<'a, T>, 1255 ptr: *mut U, 1256 ) -> Self::View<'a, U> { 1257 // SAFETY: Per safety requirement. 1258 RelaxedMmio(unsafe { MmioBackend::project_view(view.0, ptr) }) 1259 } 1260 } 1261 1262 impl<'a, T: ?Sized + KnownSize> IoBase<'a> for RelaxedMmio<'a, T> { 1263 type Backend = RelaxedMmioBackend; 1264 type Target = T; 1265 1266 #[inline] 1267 fn as_view(self) -> RelaxedMmio<'a, T> { 1268 self 1269 } 1270 } 1271 1272 impl<'a, T: ?Sized> Mmio<'a, T> { 1273 /// Returns a [`RelaxedMmio`] that performs relaxed I/O operations. 1274 /// 1275 /// Relaxed accessors do not provide ordering guarantees with respect to DMA or memory accesses 1276 /// and can be used when such ordering is not required. 1277 /// 1278 /// # Examples 1279 /// 1280 /// ```no_run 1281 /// use kernel::io::{ 1282 /// Io, 1283 /// Mmio, 1284 /// Region, 1285 /// RelaxedMmio, 1286 /// }; 1287 /// 1288 /// fn do_io(io: Mmio<'_, Region<0x100>>) { 1289 /// // The access is performed using `readl_relaxed` instead of `readl`. 1290 /// let v = io.relaxed().read32(0x10); 1291 /// } 1292 /// 1293 /// ``` 1294 #[inline] 1295 pub fn relaxed(self) -> RelaxedMmio<'a, T> { 1296 RelaxedMmio(self) 1297 } 1298 } 1299 1300 // MMIO regions support 8, 16, and 32-bit accesses. 1301 impl_mmio_io_capable!(RelaxedMmioBackend, u8, readb_relaxed, writeb_relaxed); 1302 impl_mmio_io_capable!(RelaxedMmioBackend, u16, readw_relaxed, writew_relaxed); 1303 impl_mmio_io_capable!(RelaxedMmioBackend, u32, readl_relaxed, writel_relaxed); 1304 // MMIO regions on 64-bit systems also support 64-bit accesses. 1305 #[cfg(CONFIG_64BIT)] 1306 impl_mmio_io_capable!(RelaxedMmioBackend, u64, readq_relaxed, writeq_relaxed); 1307 1308 /// I/O Backend for system memory. 1309 pub struct SysMemBackend; 1310 1311 impl IoBackend for SysMemBackend { 1312 type View<'a, T: ?Sized + KnownSize> = SysMem<'a, T>; 1313 1314 #[inline] 1315 fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T { 1316 view.ptr 1317 } 1318 1319 #[inline] 1320 unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>( 1321 _view: Self::View<'a, T>, 1322 ptr: *mut U, 1323 ) -> Self::View<'a, U> { 1324 // INVARIANT: Per safety requirement, `ptr` is projection from `view`, so it is also a valid 1325 // kernel accessible memory region. 1326 SysMem { 1327 ptr, 1328 phantom: PhantomData, 1329 } 1330 } 1331 } 1332 1333 /// Implements [`IoCapable`] on `SysMemBackend` for `$ty` using `read_volatile` and 1334 /// `write_volatile`. 1335 macro_rules! impl_sysmem_io_capable { 1336 ($ty:ty) => { 1337 impl IoCapable<$ty> for SysMemBackend { 1338 #[inline] 1339 fn io_read(view: SysMem<'_, $ty>) -> $ty { 1340 // SAFETY: 1341 // - Per type invariant, `ptr` is valid and aligned. 1342 // - Using read_volatile() here so that race with hardware is well-defined. 1343 // - Using read_volatile() here is not sound if it races with other CPU per Rust 1344 // rules, but this is allowed per LKMM. 1345 // - The macro is only used on primitives so all bit patterns are valid. 1346 unsafe { view.ptr.read_volatile() } 1347 } 1348 1349 #[inline] 1350 fn io_write(view: SysMem<'_, $ty>, value: $ty) { 1351 // SAFETY: 1352 // - Per type invariant, `ptr` is valid and aligned. 1353 // - Using write_volatile() here so that race with hardware is well-defined. 1354 // - Using write_volatile() here is not sound if it races with other CPU per Rust 1355 // rules, but this is allowed per LKMM. 1356 unsafe { view.ptr.write_volatile(value) } 1357 } 1358 } 1359 }; 1360 } 1361 1362 impl_sysmem_io_capable!(u8); 1363 impl_sysmem_io_capable!(u16); 1364 impl_sysmem_io_capable!(u32); 1365 #[cfg(CONFIG_64BIT)] 1366 impl_sysmem_io_capable!(u64); 1367 1368 impl IoCopyable for SysMemBackend { 1369 #[inline] 1370 unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { 1371 // Use `bindings::memcpy` instead of `copy_nonoverlapping` for volatile. 1372 // SAFETY: 1373 // - `view.ptr` is in CPU address space and valid for read. 1374 // - `buffer` is valid for write for `view.size()` bytes which is equal to `view.ptr.len()`. 1375 unsafe { bindings::memcpy(buffer.cast(), view.ptr.cast(), view.ptr.len()) }; 1376 } 1377 1378 #[inline] 1379 unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { 1380 // Use `bindings::memcpy` instead of `copy_nonoverlapping` for volatile. 1381 // SAFETY: 1382 // - `view.ptr` is in CPU address space and valid for write. 1383 // - `buffer` is valid for read for `view.size()` bytes which is equal to `view.ptr.len()`. 1384 unsafe { bindings::memcpy(view.ptr.cast(), buffer.cast(), view.ptr.len()) }; 1385 } 1386 1387 #[inline] 1388 fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { 1389 // SAFETY: 1390 // - Per type invariant, `ptr` is valid and aligned. 1391 // - Using read_volatile() here so that race with hardware is well-defined. 1392 // - Using read_volatile() here is not sound if it races with other CPU per Rust 1393 // rules, but this is allowed per LKMM. 1394 // - `T: FromBytes` so all bit patterns are valid. 1395 unsafe { view.ptr.read_volatile() } 1396 } 1397 1398 #[inline] 1399 fn copy_write<T: IntoBytes>(view: Self::View<'_, T>, value: T) { 1400 // SAFETY: 1401 // - Per type invariant, `ptr` is valid and aligned. 1402 // - Using write_volatile() here so that race with hardware is well-defined. 1403 // - Using write_volatile() here is not sound if it races with other CPU per Rust 1404 // rules, but this is allowed per LKMM. 1405 unsafe { view.ptr.write_volatile(value) } 1406 } 1407 } 1408 1409 /// A view of a system memory region. 1410 /// 1411 /// Provides `Io` trait implementation for kernel virtual address ranges, 1412 /// using volatile read/write to safely access shared memory that may be 1413 /// concurrently accessed by external hardware. 1414 /// 1415 /// # Invariants 1416 /// 1417 /// `self.ptr.addr() .. self.ptr.addr() + KnownSize::size(self.ptr)` is valid and aligned kernel 1418 /// accessible memory region for the lifetime `'a`. 1419 pub struct SysMem<'a, T: ?Sized> { 1420 ptr: *mut T, 1421 phantom: PhantomData<&'a ()>, 1422 } 1423 1424 impl<T: ?Sized> Copy for SysMem<'_, T> {} 1425 impl<T: ?Sized> Clone for SysMem<'_, T> { 1426 #[inline] 1427 fn clone(&self) -> Self { 1428 *self 1429 } 1430 } 1431 1432 // SAFETY: `SysMem<'_, T>` is conceptually `&T`. 1433 unsafe impl<T: ?Sized + Sync> Send for SysMem<'_, T> {} 1434 1435 // SAFETY: `SysMem<'_, T>` is conceptually `&T`. 1436 unsafe impl<T: ?Sized + Sync> Sync for SysMem<'_, T> {} 1437 1438 impl<'a, T: ?Sized> SysMem<'a, T> { 1439 /// Create a `SysMem` from a raw pointer. 1440 /// 1441 /// # Safety 1442 /// 1443 /// `ptr.addr() .. ptr.addr() + KnownSize::size(ptr)` must be valid and aligned kernel 1444 /// accessible memory region for the lifetime `'a`. 1445 #[inline] 1446 pub unsafe fn new(ptr: *mut T) -> Self { 1447 // INVARIANT: Per safety requirement. 1448 Self { 1449 ptr, 1450 phantom: PhantomData, 1451 } 1452 } 1453 1454 /// Obtain the raw pointer to the memory. 1455 #[inline] 1456 pub fn as_ptr(self) -> *mut T { 1457 self.ptr 1458 } 1459 } 1460 1461 impl<'a, T: ?Sized + KnownSize> IoBase<'a> for SysMem<'a, T> { 1462 type Backend = SysMemBackend; 1463 type Target = T; 1464 1465 #[inline] 1466 fn as_view(self) -> <Self::Backend as IoBackend>::View<'a, Self::Target> { 1467 self 1468 } 1469 } 1470 1471 /// I/O Backend for [`IoSysMap`]. 1472 pub struct IoSysMapBackend; 1473 1474 /// Either [`Mmio`] or [`SysMem`]. 1475 /// 1476 /// This can be used when a piece of logic may wish to handle both MMIO or system memory but does 1477 /// not want or cannot be generic over I/O backends. This serves a similar purpose to 1478 /// [`include/linux/iosys-map.h`] in C. 1479 /// 1480 /// This type can be used like any other types that implements [`Io`]; this also include 1481 /// [`io_project!`], [`io_read!`], [`io_write!`]. 1482 /// 1483 /// [`include/linux/iosys-map.h`]: srctree/include/linux/iosys-map.h 1484 pub enum IoSysMap<'a, T: ?Sized> { 1485 /// The view is I/O memory. 1486 Io(Mmio<'a, T>), 1487 /// The view is system memory. 1488 Sys(SysMem<'a, T>), 1489 } 1490 1491 impl<T: ?Sized> Copy for IoSysMap<'_, T> {} 1492 impl<T: ?Sized> Clone for IoSysMap<'_, T> { 1493 #[inline] 1494 fn clone(&self) -> Self { 1495 *self 1496 } 1497 } 1498 1499 impl<'a, T: ?Sized> From<Mmio<'a, T>> for IoSysMap<'a, T> { 1500 #[inline] 1501 fn from(value: Mmio<'a, T>) -> Self { 1502 IoSysMap::Io(value) 1503 } 1504 } 1505 1506 impl<'a, T: ?Sized> From<SysMem<'a, T>> for IoSysMap<'a, T> { 1507 #[inline] 1508 fn from(value: SysMem<'a, T>) -> Self { 1509 IoSysMap::Sys(value) 1510 } 1511 } 1512 1513 impl IoBackend for IoSysMapBackend { 1514 type View<'a, T: ?Sized + KnownSize> = IoSysMap<'a, T>; 1515 1516 #[inline] 1517 fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T { 1518 match view { 1519 IoSysMap::Io(l) => MmioBackend::as_ptr(l), 1520 IoSysMap::Sys(r) => SysMemBackend::as_ptr(r), 1521 } 1522 } 1523 1524 #[inline] 1525 unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>( 1526 view: Self::View<'a, T>, 1527 ptr: *mut U, 1528 ) -> Self::View<'a, U> { 1529 match view { 1530 // SAFETY: Per safety requirement. 1531 IoSysMap::Io(l) => IoSysMap::Io(unsafe { MmioBackend::project_view(l, ptr) }), 1532 // SAFETY: Per safety requirement. 1533 IoSysMap::Sys(r) => IoSysMap::Sys(unsafe { SysMemBackend::project_view(r, ptr) }), 1534 } 1535 } 1536 } 1537 1538 impl<T> IoCapable<T> for IoSysMapBackend 1539 where 1540 MmioBackend: IoCapable<T>, 1541 SysMemBackend: IoCapable<T>, 1542 { 1543 #[inline] 1544 fn io_read(view: Self::View<'_, T>) -> T { 1545 match view { 1546 IoSysMap::Io(l) => MmioBackend::io_read(l), 1547 IoSysMap::Sys(r) => SysMemBackend::io_read(r), 1548 } 1549 } 1550 1551 #[inline] 1552 fn io_write<'a>(view: Self::View<'a, T>, value: T) { 1553 match view { 1554 IoSysMap::Io(l) => MmioBackend::io_write(l, value), 1555 IoSysMap::Sys(r) => SysMemBackend::io_write(r, value), 1556 } 1557 } 1558 } 1559 1560 impl IoCopyable for IoSysMapBackend { 1561 #[inline] 1562 unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { 1563 match view { 1564 // SAFETY: Per safety requirement. 1565 IoSysMap::Io(l) => unsafe { MmioBackend::copy_from_io(l, buffer) }, 1566 // SAFETY: Per safety requirement. 1567 IoSysMap::Sys(r) => unsafe { SysMemBackend::copy_from_io(r, buffer) }, 1568 } 1569 } 1570 1571 #[inline] 1572 unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { 1573 match view { 1574 // SAFETY: Per safety requirement. 1575 IoSysMap::Io(l) => unsafe { MmioBackend::copy_to_io(l, buffer) }, 1576 // SAFETY: Per safety requirement. 1577 IoSysMap::Sys(r) => unsafe { SysMemBackend::copy_to_io(r, buffer) }, 1578 } 1579 } 1580 1581 #[inline] 1582 fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { 1583 match view { 1584 IoSysMap::Io(l) => MmioBackend::copy_read(l), 1585 IoSysMap::Sys(r) => SysMemBackend::copy_read(r), 1586 } 1587 } 1588 1589 #[inline] 1590 fn copy_write<T: IntoBytes>(view: Self::View<'_, T>, value: T) { 1591 match view { 1592 IoSysMap::Io(l) => MmioBackend::copy_write(l, value), 1593 IoSysMap::Sys(r) => SysMemBackend::copy_write(r, value), 1594 } 1595 } 1596 } 1597 1598 impl<'a, T: ?Sized + KnownSize> IoBase<'a> for IoSysMap<'a, T> { 1599 type Backend = IoSysMapBackend; 1600 type Target = T; 1601 1602 #[inline] 1603 fn as_view(self) -> IoSysMap<'a, T> { 1604 self 1605 } 1606 } 1607 1608 // This helper turns associated functions to methods so it can be invoked in macro. 1609 // Used by `io_project!()` only. 1610 #[doc(hidden)] 1611 #[derive(Clone, Copy)] 1612 pub struct ProjectHelper<T>(pub T); 1613 1614 impl<'a, T> ProjectHelper<T> 1615 where 1616 T: Io<'a, Backend: IoBackend<View<'a, T::Target> = T>>, 1617 { 1618 // These helper methods must not have symbols present in the binary to avoid confusion. 1619 #[inline(always)] 1620 pub fn as_ptr(self) -> *mut T::Target { 1621 T::Backend::as_ptr(self.0) 1622 } 1623 1624 /// # Safety 1625 /// 1626 /// Same as `IoBackend::project_view` 1627 #[inline(always)] 1628 pub unsafe fn project_view<U: ?Sized + KnownSize>( 1629 self, 1630 ptr: *mut U, 1631 ) -> <T::Backend as IoBackend>::View<'a, U> { 1632 // SAFETY: Per safety requirement. 1633 unsafe { T::Backend::project_view::<T::Target, _>(self.0, ptr) } 1634 } 1635 } 1636 1637 /// Project an I/O type to a subview of it. 1638 /// 1639 /// The syntax is of form `io_project!(io, proj)` where `io` is an expression to a type that 1640 /// implements [`Io`] and `proj` is a [projection specification](kernel::ptr::project!). 1641 /// 1642 /// # Examples 1643 /// 1644 /// ``` 1645 /// use kernel::io::{ 1646 /// io_project, 1647 /// Mmio, 1648 /// }; 1649 /// #[repr(C)] 1650 /// struct MyStruct { field: u32, } 1651 /// 1652 /// # fn test(mmio: Mmio<'_, [MyStruct]>) -> Result { 1653 /// // let mmio: Mmio<[MyStruct]>; 1654 /// let field: Mmio<'_, u32> = io_project!(mmio, [try: 1].field); 1655 /// let whole: Mmio<'_, MyStruct> = io_project!(mmio, [try: 2]); 1656 /// let nested: Mmio<'_, u32> = io_project!(whole, .field); 1657 /// # Ok::<(), Error>(()) } 1658 /// ``` 1659 #[macro_export] 1660 #[doc(hidden)] 1661 macro_rules! io_project { 1662 ($io:expr, $($proj:tt)*) => {{ 1663 #[allow(unused)] 1664 use $crate::io::IoBase as _; 1665 let view = $crate::io::ProjectHelper($io.as_view()); 1666 let ptr = $crate::ptr::project!( 1667 mut view.as_ptr(), $($proj)* 1668 ); 1669 #[allow(unused_unsafe)] 1670 // SAFETY: `ptr` is a projection. 1671 unsafe { view.project_view(ptr) } 1672 }}; 1673 } 1674 #[doc(inline)] 1675 pub use crate::io_project; 1676 1677 /// Read from I/O memory. 1678 /// 1679 /// The syntax is of form `io_read!(io, proj)` where `io` is an expression to a type that 1680 /// implements [`Io`] and `proj` is a [projection specification](kernel::ptr::project!). 1681 /// 1682 /// # Examples 1683 /// 1684 /// ``` 1685 /// #[repr(C)] 1686 /// struct MyStruct { field: u32, } 1687 /// 1688 /// # fn test(mmio: kernel::io::Mmio<'_, [MyStruct]>) -> Result { 1689 /// // let mmio: Mmio<'_, [MyStruct]>; 1690 /// let field: u32 = kernel::io::io_read!(mmio, [try: 2].field); 1691 /// # Ok::<(), Error>(()) } 1692 /// ``` 1693 #[macro_export] 1694 #[doc(hidden)] 1695 macro_rules! io_read { 1696 ($io:expr, $($proj:tt)*) => { 1697 $crate::io::Io::read_val($crate::io_project!($io, $($proj)*)) 1698 }; 1699 } 1700 #[doc(inline)] 1701 pub use crate::io_read; 1702 1703 /// Writes to I/O memory. 1704 /// 1705 /// The syntax is of form `io_write!(io, proj, val)` where `io` is an expression to a type that 1706 /// implements [`Io`] and `proj` is a [projection specification](kernel::ptr::project!), 1707 /// and `val` is the value to be written to the projected location. 1708 /// 1709 /// # Examples 1710 /// 1711 /// ``` 1712 /// #[repr(C)] 1713 /// struct MyStruct { field: u32, } 1714 /// 1715 /// # fn test(mmio: kernel::io::Mmio<'_, [MyStruct]>) -> Result { 1716 /// // let mmio: Mmio<'_, [MyStruct]>; 1717 /// kernel::io::io_write!(mmio, [try: 2].field, 10); 1718 /// # Ok::<(), Error>(()) } 1719 /// ``` 1720 #[macro_export] 1721 #[doc(hidden)] 1722 macro_rules! io_write { 1723 (@parse [$io:expr] [$($proj:tt)*] [, $val:expr]) => { 1724 $crate::io::Io::write_val($crate::io_project!($io, $($proj)*), $val) 1725 }; 1726 (@parse [$io:expr] [$($proj:tt)*] [.$field:tt $($rest:tt)*]) => { 1727 $crate::io_write!(@parse [$io] [$($proj)* .$field] [$($rest)*]) 1728 }; 1729 (@parse [$io:expr] [$($proj:tt)*] [[$flavor:ident: $index:expr] $($rest:tt)*]) => { 1730 $crate::io_write!(@parse [$io] [$($proj)* [$flavor: $index]] [$($rest)*]) 1731 }; 1732 ($io:expr, $($rest:tt)*) => { 1733 $crate::io_write!(@parse [$io] [] [$($rest)*]) 1734 }; 1735 } 1736 #[doc(inline)] 1737 pub use crate::io_write; 1738