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