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 /// 726 /// `offset` should be constant. 727 #[inline(always)] 728 fn read8(self, offset: usize) -> u8 729 where 730 usize: IoLoc<Self::Target, u8, IoType = u8>, 731 Self::Backend: IoCapable<u8>, 732 { 733 self.read(offset) 734 } 735 736 /// Infallible 16-bit read with compile-time bounds check. 737 /// 738 /// `offset` should be constant. 739 #[inline(always)] 740 fn read16(self, offset: usize) -> u16 741 where 742 usize: IoLoc<Self::Target, u16, IoType = u16>, 743 Self::Backend: IoCapable<u16>, 744 { 745 self.read(offset) 746 } 747 748 /// Infallible 32-bit read with compile-time bounds check. 749 /// 750 /// `offset` should be constant. 751 #[inline(always)] 752 fn read32(self, offset: usize) -> u32 753 where 754 usize: IoLoc<Self::Target, u32, IoType = u32>, 755 Self::Backend: IoCapable<u32>, 756 { 757 self.read(offset) 758 } 759 760 /// Infallible 64-bit read with compile-time bounds check. 761 /// 762 /// `offset` should be constant. 763 #[inline(always)] 764 fn read64(self, offset: usize) -> u64 765 where 766 usize: IoLoc<Self::Target, u64, IoType = u64>, 767 Self::Backend: IoCapable<u64>, 768 { 769 self.read(offset) 770 } 771 772 /// Infallible 8-bit write with compile-time bounds check. 773 /// 774 /// `offset` should be constant. 775 #[inline(always)] 776 fn write8(self, value: u8, offset: usize) 777 where 778 usize: IoLoc<Self::Target, u8, IoType = u8>, 779 Self::Backend: IoCapable<u8>, 780 { 781 self.write(offset, value) 782 } 783 784 /// Infallible 16-bit write with compile-time bounds check. 785 /// 786 /// `offset` should be constant. 787 #[inline(always)] 788 fn write16(self, value: u16, offset: usize) 789 where 790 usize: IoLoc<Self::Target, u16, IoType = u16>, 791 Self::Backend: IoCapable<u16>, 792 { 793 self.write(offset, value) 794 } 795 796 /// Infallible 32-bit write with compile-time bounds check. 797 /// 798 /// `offset` should be constant. 799 #[inline(always)] 800 fn write32(self, value: u32, offset: usize) 801 where 802 usize: IoLoc<Self::Target, u32, IoType = u32>, 803 Self::Backend: IoCapable<u32>, 804 { 805 self.write(offset, value) 806 } 807 808 /// Infallible 64-bit write with compile-time bounds check. 809 /// 810 /// `offset` should be constant. 811 #[inline(always)] 812 fn write64(self, value: u64, offset: usize) 813 where 814 usize: IoLoc<Self::Target, u64, IoType = u64>, 815 Self::Backend: IoCapable<u64>, 816 { 817 self.write(offset, value) 818 } 819 820 /// Generic fallible read with runtime bounds check. 821 /// 822 /// # Examples 823 /// 824 /// Read a primitive type from an I/O address: 825 /// 826 /// ```no_run 827 /// use kernel::io::{ 828 /// Io, 829 /// Mmio, 830 /// Region, 831 /// }; 832 /// 833 /// fn do_reads(io: Mmio<'_, Region>) -> Result { 834 /// // 32-bit read from address `0x10`. 835 /// let v: u32 = io.try_read(0x10)?; 836 /// 837 /// // 8-bit read from address `0xfff`. 838 /// let v: u8 = io.try_read(0xfff)?; 839 /// 840 /// Ok(()) 841 /// } 842 /// ``` 843 #[inline(always)] 844 fn try_read<T, L>(self, location: L) -> Result<T> 845 where 846 L: IoLoc<Self::Target, T>, 847 Self::Backend: IoCapable<L::IoType>, 848 { 849 let view = io_view::<Self, L::IoType>(self, location.offset())?; 850 Ok(Self::Backend::io_read(view).into()) 851 } 852 853 /// Generic fallible write with runtime bounds check. 854 /// 855 /// # Examples 856 /// 857 /// Write a primitive type to an I/O address: 858 /// 859 /// ```no_run 860 /// use kernel::io::{ 861 /// Io, 862 /// Mmio, 863 /// Region, 864 /// }; 865 /// 866 /// fn do_writes(io: Mmio<'_, Region>) -> Result { 867 /// // 32-bit write of value `1` at address `0x10`. 868 /// io.try_write(0x10, 1u32)?; 869 /// 870 /// // 8-bit write of value `0xff` at address `0xfff`. 871 /// io.try_write(0xfff, 0xffu8)?; 872 /// 873 /// Ok(()) 874 /// } 875 /// ``` 876 #[inline(always)] 877 fn try_write<T, L>(self, location: L, value: T) -> Result 878 where 879 L: IoLoc<Self::Target, T>, 880 Self::Backend: IoCapable<L::IoType>, 881 { 882 let view = io_view::<Self, L::IoType>(self, location.offset())?; 883 let io_value = value.into(); 884 Self::Backend::io_write(view, io_value); 885 Ok(()) 886 } 887 888 /// Generic fallible write of a fully-located register value. 889 /// 890 /// # Examples 891 /// 892 /// Tuples carrying a location and a value can be used with this method: 893 /// 894 /// ```no_run 895 /// use kernel::io::{ 896 /// register, 897 /// Io, 898 /// Mmio, 899 /// Region, 900 /// }; 901 /// 902 /// register! { 903 /// VERSION(u32) @ 0x100 { 904 /// 15:8 major; 905 /// 7:0 minor; 906 /// } 907 /// } 908 /// 909 /// impl VERSION { 910 /// fn new(major: u8, minor: u8) -> Self { 911 /// VERSION::zeroed().with_major(major).with_minor(minor) 912 /// } 913 /// } 914 /// 915 /// fn do_write_reg(io: Mmio<'_, Region>) -> Result { 916 /// 917 /// io.try_write_reg(VERSION::new(1, 0)) 918 /// } 919 /// ``` 920 #[inline(always)] 921 fn try_write_reg<T, L, V>(self, value: V) -> Result 922 where 923 L: IoLoc<Self::Target, T>, 924 V: LocatedRegister<Self::Target, Location = L, Value = T>, 925 Self::Backend: IoCapable<L::IoType>, 926 { 927 let (location, value) = value.into_io_op(); 928 929 self.try_write(location, value) 930 } 931 932 /// Generic fallible update with runtime bounds check. 933 /// 934 /// Note: this does not perform any synchronization. The caller is responsible for ensuring 935 /// exclusive access if required. 936 /// 937 /// # Examples 938 /// 939 /// Read the u32 value at address `0x10`, increment it, and store the updated value back: 940 /// 941 /// ```no_run 942 /// use kernel::io::{ 943 /// Io, 944 /// Mmio, 945 /// Region, 946 /// }; 947 /// 948 /// fn do_update(io: Mmio<'_, Region<0x1000>>) -> Result { 949 /// io.try_update(0x10, |v: u32| { 950 /// v + 1 951 /// }) 952 /// } 953 /// ``` 954 #[inline(always)] 955 fn try_update<T, L, F>(self, location: L, f: F) -> Result 956 where 957 L: IoLoc<Self::Target, T>, 958 Self::Backend: IoCapable<L::IoType>, 959 F: FnOnce(T) -> T, 960 { 961 let view = io_view::<Self, L::IoType>(self, location.offset())?; 962 963 let value: T = Self::Backend::io_read(view).into(); 964 let io_value = f(value).into(); 965 Self::Backend::io_write(view, io_value); 966 967 Ok(()) 968 } 969 970 /// Generic infallible read with compile-time bounds check. 971 /// 972 /// # Examples 973 /// 974 /// Read a primitive type from an I/O address: 975 /// 976 /// ```no_run 977 /// use kernel::io::{ 978 /// Io, 979 /// Mmio, 980 /// Region, 981 /// }; 982 /// 983 /// fn do_reads(io: Mmio<'_, Region<0x1000>>) { 984 /// // 32-bit read from address `0x10`. 985 /// let v: u32 = io.read(0x10); 986 /// 987 /// // 8-bit read from the top of the I/O space. 988 /// let v: u8 = io.read(0xfff); 989 /// } 990 /// ``` 991 #[inline(always)] 992 fn read<T, L>(self, location: L) -> T 993 where 994 L: IoLoc<Self::Target, T>, 995 Self::Backend: IoCapable<L::IoType>, 996 { 997 let view = io_view_assert::<Self, L::IoType>(self, location.offset()); 998 Self::Backend::io_read(view).into() 999 } 1000 1001 /// Generic infallible write with compile-time bounds check. 1002 /// 1003 /// # Examples 1004 /// 1005 /// Write a primitive type to an I/O address: 1006 /// 1007 /// ```no_run 1008 /// use kernel::io::{ 1009 /// Io, 1010 /// Mmio, 1011 /// Region, 1012 /// }; 1013 /// 1014 /// fn do_writes(io: Mmio<'_, Region<0x1000>>) { 1015 /// // 32-bit write of value `1` at address `0x10`. 1016 /// io.write(0x10, 1u32); 1017 /// 1018 /// // 8-bit write of value `0xff` at the top of the I/O space. 1019 /// io.write(0xfff, 0xffu8); 1020 /// } 1021 /// ``` 1022 #[inline(always)] 1023 fn write<T, L>(self, location: L, value: T) 1024 where 1025 L: IoLoc<Self::Target, T>, 1026 Self::Backend: IoCapable<L::IoType>, 1027 { 1028 let view = io_view_assert::<Self, L::IoType>(self, location.offset()); 1029 let io_value = value.into(); 1030 Self::Backend::io_write(view, io_value); 1031 } 1032 1033 /// Generic infallible write of a fully-located register value. 1034 /// 1035 /// # Examples 1036 /// 1037 /// Tuples carrying a location and a value can be used with this method: 1038 /// 1039 /// ```no_run 1040 /// use kernel::io::{ 1041 /// register, 1042 /// Io, 1043 /// Mmio, 1044 /// Region, 1045 /// }; 1046 /// 1047 /// register! { 1048 /// VERSION(u32) @ 0x100 { 1049 /// 15:8 major; 1050 /// 7:0 minor; 1051 /// } 1052 /// } 1053 /// 1054 /// impl VERSION { 1055 /// fn new(major: u8, minor: u8) -> Self { 1056 /// VERSION::zeroed().with_major(major).with_minor(minor) 1057 /// } 1058 /// } 1059 /// 1060 /// fn do_write_reg(io: Mmio<'_, Region<0x1000>>) { 1061 /// io.write_reg(VERSION::new(1, 0)); 1062 /// } 1063 /// ``` 1064 #[inline(always)] 1065 fn write_reg<T, L, V>(self, value: V) 1066 where 1067 L: IoLoc<Self::Target, T>, 1068 V: LocatedRegister<Self::Target, Location = L, Value = T>, 1069 Self::Backend: IoCapable<L::IoType>, 1070 { 1071 let (location, value) = value.into_io_op(); 1072 1073 self.write(location, value) 1074 } 1075 1076 /// Generic infallible update with compile-time bounds check. 1077 /// 1078 /// Note: this does not perform any synchronization. The caller is responsible for ensuring 1079 /// exclusive access if required. 1080 /// 1081 /// # Examples 1082 /// 1083 /// Read the u32 value at address `0x10`, increment it, and store the updated value back: 1084 /// 1085 /// ```no_run 1086 /// use kernel::io::{ 1087 /// Io, 1088 /// Mmio, 1089 /// Region, 1090 /// }; 1091 /// 1092 /// fn do_update(io: Mmio<'_, Region<0x1000>>) { 1093 /// io.update(0x10, |v: u32| { 1094 /// v + 1 1095 /// }) 1096 /// } 1097 /// ``` 1098 #[inline(always)] 1099 fn update<T, L, F>(self, location: L, f: F) 1100 where 1101 L: IoLoc<Self::Target, T>, 1102 Self::Backend: IoCapable<L::IoType>, 1103 F: FnOnce(T) -> T, 1104 { 1105 let view = io_view_assert::<Self, L::IoType>(self, location.offset()); 1106 let value: T = Self::Backend::io_read(view).into(); 1107 let io_value = f(value).into(); 1108 Self::Backend::io_write(view, io_value); 1109 } 1110 } 1111 1112 // Blanket implementation ensures that provided methods cannot be arbitrarily overridden by 1113 // implementers, which is relied upon for correctness and soundness. 1114 impl<'a, T: IoBase<'a>> Io<'a> for T {} 1115 1116 /// A view of memory-mapped I/O region. 1117 /// 1118 /// # Invariant 1119 /// 1120 /// `ptr` points to a valid and aligned memory-mapped I/O region for the duration lifetime `'a`. 1121 pub struct Mmio<'a, T: ?Sized> { 1122 ptr: *mut T, 1123 phantom: PhantomData<&'a ()>, 1124 } 1125 1126 impl<T: ?Sized> Copy for Mmio<'_, T> {} 1127 impl<T: ?Sized> Clone for Mmio<'_, T> { 1128 #[inline] 1129 fn clone(&self) -> Self { 1130 *self 1131 } 1132 } 1133 1134 impl<'a, T: ?Sized> Mmio<'a, T> { 1135 /// Create a `Mmio`, providing the accessors to the MMIO mapping. 1136 /// 1137 /// # Safety 1138 /// 1139 /// `raw` represents a valid and aligned memory-mapped I/O region while `'a` is alive. 1140 #[inline] 1141 pub unsafe fn from_raw(raw: MmioRaw<T>) -> Self { 1142 // INVARIANT: Per safety requirement. 1143 Self { 1144 ptr: raw.ptr, 1145 phantom: PhantomData, 1146 } 1147 } 1148 } 1149 1150 // SAFETY: `Mmio<'_, T>` is conceptually `&T` but in I/O memory. 1151 unsafe impl<T: ?Sized + Sync> Send for Mmio<'_, T> {} 1152 1153 // SAFETY: `Mmio<'_, T>` is conceptually `&T` but in I/O memory. 1154 unsafe impl<T: ?Sized + Sync> Sync for Mmio<'_, T> {} 1155 1156 impl<'a, T: ?Sized + KnownSize> IoBase<'a> for Mmio<'a, T> { 1157 type Backend = MmioBackend; 1158 type Target = T; 1159 1160 #[inline] 1161 fn as_view(self) -> Mmio<'a, T> { 1162 self 1163 } 1164 } 1165 1166 /// I/O Backend for memory-mapped I/O. 1167 pub struct MmioBackend; 1168 1169 impl IoBackend for MmioBackend { 1170 type View<'a, T: ?Sized + KnownSize> = Mmio<'a, T>; 1171 1172 #[inline] 1173 fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T { 1174 view.ptr 1175 } 1176 1177 #[inline] 1178 unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>( 1179 _view: Self::View<'a, T>, 1180 ptr: *mut U, 1181 ) -> Self::View<'a, U> { 1182 // INVARIANT: Per safety requirement, `ptr` is projection from `view`, so it is also a valid 1183 // memory-mapped I/O region. 1184 Mmio { 1185 ptr, 1186 phantom: PhantomData, 1187 } 1188 } 1189 } 1190 1191 /// Implements [`IoCapable`] on `$backend` for `$ty` using `$read_fn` and `$write_fn`. 1192 macro_rules! impl_mmio_io_capable { 1193 ($backend: ident, $ty:ty, $read_fn:ident, $write_fn:ident) => { 1194 impl IoCapable<$ty> for $backend { 1195 #[inline] 1196 fn io_read(view: <$backend as IoBackend>::View<'_, $ty>) -> $ty { 1197 // SAFETY: `$backend::as_ptr(view)` is a valid pointer for MMIO operations for both 1198 // `MmioBackend` and `RelaxedMmioBackend`. 1199 unsafe { bindings::$read_fn($backend::as_ptr(view).cast_const().cast()) } 1200 } 1201 1202 #[inline] 1203 fn io_write(view: <$backend as IoBackend>::View<'_, $ty>, value: $ty) { 1204 // SAFETY: `$backend::as_ptr(view)` is a valid pointer for MMIO operations for both 1205 // `MmioBackend` and `RelaxedMmioBackend`. 1206 unsafe { bindings::$write_fn(value, $backend::as_ptr(view).cast()) } 1207 } 1208 } 1209 }; 1210 } 1211 1212 // MMIO regions support 8, 16, and 32-bit accesses. 1213 impl_mmio_io_capable!(MmioBackend, u8, readb, writeb); 1214 impl_mmio_io_capable!(MmioBackend, u16, readw, writew); 1215 impl_mmio_io_capable!(MmioBackend, u32, readl, writel); 1216 // MMIO regions on 64-bit systems also support 64-bit accesses. 1217 #[cfg(CONFIG_64BIT)] 1218 impl_mmio_io_capable!(MmioBackend, u64, readq, writeq); 1219 1220 impl IoCopyable for MmioBackend { 1221 #[inline] 1222 unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { 1223 // SAFETY: 1224 // - `view.ptr` is valid MMIO memory for `view.size()` bytes. 1225 // - `buffer` is valid for write for `view.size()` bytes. 1226 unsafe { 1227 bindings::memcpy_fromio(buffer.cast(), view.ptr.cast(), view.size()); 1228 } 1229 } 1230 1231 #[inline] 1232 unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { 1233 // SAFETY: 1234 // - `view.ptr` is valid MMIO memory for `view.size()` bytes. 1235 // - `buffer` is valid for read for `view.size()` bytes. 1236 unsafe { 1237 bindings::memcpy_toio(view.ptr.cast(), buffer.cast(), view.size()); 1238 } 1239 } 1240 } 1241 1242 /// [`Mmio`] but using relaxed accessors. 1243 /// 1244 /// This type provides an implementation of [`Io`] that uses relaxed I/O MMIO operands instead of 1245 /// the regular ones. 1246 /// 1247 /// See [`Mmio::relaxed`] for a usage example. 1248 pub struct RelaxedMmio<'a, T: ?Sized>(Mmio<'a, T>); 1249 1250 impl<T: ?Sized> Copy for RelaxedMmio<'_, T> {} 1251 impl<T: ?Sized> Clone for RelaxedMmio<'_, T> { 1252 #[inline] 1253 fn clone(&self) -> Self { 1254 *self 1255 } 1256 } 1257 1258 /// I/O Backend for memory-mapped I/O, with relaxed access semantics. 1259 pub struct RelaxedMmioBackend; 1260 1261 impl IoBackend for RelaxedMmioBackend { 1262 type View<'a, T: ?Sized + KnownSize> = RelaxedMmio<'a, T>; 1263 1264 #[inline] 1265 fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T { 1266 MmioBackend::as_ptr(view.0) 1267 } 1268 1269 #[inline] 1270 unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>( 1271 view: Self::View<'a, T>, 1272 ptr: *mut U, 1273 ) -> Self::View<'a, U> { 1274 // SAFETY: Per safety requirement. 1275 RelaxedMmio(unsafe { MmioBackend::project_view(view.0, ptr) }) 1276 } 1277 } 1278 1279 impl<'a, T: ?Sized + KnownSize> IoBase<'a> for RelaxedMmio<'a, T> { 1280 type Backend = RelaxedMmioBackend; 1281 type Target = T; 1282 1283 #[inline] 1284 fn as_view(self) -> RelaxedMmio<'a, T> { 1285 self 1286 } 1287 } 1288 1289 impl<'a, T: ?Sized> Mmio<'a, T> { 1290 /// Returns a [`RelaxedMmio`] that performs relaxed I/O operations. 1291 /// 1292 /// Relaxed accessors do not provide ordering guarantees with respect to DMA or memory accesses 1293 /// and can be used when such ordering is not required. 1294 /// 1295 /// # Examples 1296 /// 1297 /// ```no_run 1298 /// use kernel::io::{ 1299 /// Io, 1300 /// Mmio, 1301 /// Region, 1302 /// RelaxedMmio, 1303 /// }; 1304 /// 1305 /// fn do_io(io: Mmio<'_, Region<0x100>>) { 1306 /// // The access is performed using `readl_relaxed` instead of `readl`. 1307 /// let v = io.relaxed().read32(0x10); 1308 /// } 1309 /// 1310 /// ``` 1311 #[inline] 1312 pub fn relaxed(self) -> RelaxedMmio<'a, T> { 1313 RelaxedMmio(self) 1314 } 1315 } 1316 1317 // MMIO regions support 8, 16, and 32-bit accesses. 1318 impl_mmio_io_capable!(RelaxedMmioBackend, u8, readb_relaxed, writeb_relaxed); 1319 impl_mmio_io_capable!(RelaxedMmioBackend, u16, readw_relaxed, writew_relaxed); 1320 impl_mmio_io_capable!(RelaxedMmioBackend, u32, readl_relaxed, writel_relaxed); 1321 // MMIO regions on 64-bit systems also support 64-bit accesses. 1322 #[cfg(CONFIG_64BIT)] 1323 impl_mmio_io_capable!(RelaxedMmioBackend, u64, readq_relaxed, writeq_relaxed); 1324 1325 /// I/O Backend for system memory. 1326 pub struct SysMemBackend; 1327 1328 impl IoBackend for SysMemBackend { 1329 type View<'a, T: ?Sized + KnownSize> = SysMem<'a, T>; 1330 1331 #[inline] 1332 fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T { 1333 view.ptr 1334 } 1335 1336 #[inline] 1337 unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>( 1338 _view: Self::View<'a, T>, 1339 ptr: *mut U, 1340 ) -> Self::View<'a, U> { 1341 // INVARIANT: Per safety requirement, `ptr` is projection from `view`, so it is also a valid 1342 // kernel accessible memory region. 1343 SysMem { 1344 ptr, 1345 phantom: PhantomData, 1346 } 1347 } 1348 } 1349 1350 /// Implements [`IoCapable`] on `SysMemBackend` for `$ty` using `read_volatile` and 1351 /// `write_volatile`. 1352 macro_rules! impl_sysmem_io_capable { 1353 ($ty:ty) => { 1354 impl IoCapable<$ty> for SysMemBackend { 1355 #[inline] 1356 fn io_read(view: SysMem<'_, $ty>) -> $ty { 1357 // SAFETY: 1358 // - Per type invariant, `ptr` is valid and aligned. 1359 // - Using read_volatile() here so that race with hardware is well-defined. 1360 // - Using read_volatile() here is not sound if it races with other CPU per Rust 1361 // rules, but this is allowed per LKMM. 1362 // - The macro is only used on primitives so all bit patterns are valid. 1363 unsafe { view.ptr.read_volatile() } 1364 } 1365 1366 #[inline] 1367 fn io_write(view: SysMem<'_, $ty>, value: $ty) { 1368 // SAFETY: 1369 // - Per type invariant, `ptr` is valid and aligned. 1370 // - Using write_volatile() here so that race with hardware is well-defined. 1371 // - Using write_volatile() here is not sound if it races with other CPU per Rust 1372 // rules, but this is allowed per LKMM. 1373 unsafe { view.ptr.write_volatile(value) } 1374 } 1375 } 1376 }; 1377 } 1378 1379 impl_sysmem_io_capable!(u8); 1380 impl_sysmem_io_capable!(u16); 1381 impl_sysmem_io_capable!(u32); 1382 #[cfg(CONFIG_64BIT)] 1383 impl_sysmem_io_capable!(u64); 1384 1385 impl IoCopyable for SysMemBackend { 1386 #[inline] 1387 unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { 1388 // Use `bindings::memcpy` instead of `copy_nonoverlapping` for volatile. 1389 // SAFETY: 1390 // - `view.ptr` is in CPU address space and valid for read. 1391 // - `buffer` is valid for write for `view.size()` bytes which is equal to `view.ptr.len()`. 1392 unsafe { bindings::memcpy(buffer.cast(), view.ptr.cast(), view.ptr.len()) }; 1393 } 1394 1395 #[inline] 1396 unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { 1397 // Use `bindings::memcpy` instead of `copy_nonoverlapping` for volatile. 1398 // SAFETY: 1399 // - `view.ptr` is in CPU address space and valid for write. 1400 // - `buffer` is valid for read for `view.size()` bytes which is equal to `view.ptr.len()`. 1401 unsafe { bindings::memcpy(view.ptr.cast(), buffer.cast(), view.ptr.len()) }; 1402 } 1403 1404 #[inline] 1405 fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { 1406 // SAFETY: 1407 // - Per type invariant, `ptr` is valid and aligned. 1408 // - Using read_volatile() here so that race with hardware is well-defined. 1409 // - Using read_volatile() here is not sound if it races with other CPU per Rust 1410 // rules, but this is allowed per LKMM. 1411 // - `T: FromBytes` so all bit patterns are valid. 1412 unsafe { view.ptr.read_volatile() } 1413 } 1414 1415 #[inline] 1416 fn copy_write<T: IntoBytes>(view: Self::View<'_, T>, value: T) { 1417 // SAFETY: 1418 // - Per type invariant, `ptr` is valid and aligned. 1419 // - Using write_volatile() here so that race with hardware is well-defined. 1420 // - Using write_volatile() here is not sound if it races with other CPU per Rust 1421 // rules, but this is allowed per LKMM. 1422 unsafe { view.ptr.write_volatile(value) } 1423 } 1424 } 1425 1426 /// A view of a system memory region. 1427 /// 1428 /// Provides `Io` trait implementation for kernel virtual address ranges, 1429 /// using volatile read/write to safely access shared memory that may be 1430 /// concurrently accessed by external hardware. 1431 /// 1432 /// # Invariants 1433 /// 1434 /// `self.ptr.addr() .. self.ptr.addr() + KnownSize::size(self.ptr)` is valid and aligned kernel 1435 /// accessible memory region for the lifetime `'a`. 1436 pub struct SysMem<'a, T: ?Sized> { 1437 ptr: *mut T, 1438 phantom: PhantomData<&'a ()>, 1439 } 1440 1441 impl<T: ?Sized> Copy for SysMem<'_, T> {} 1442 impl<T: ?Sized> Clone for SysMem<'_, T> { 1443 #[inline] 1444 fn clone(&self) -> Self { 1445 *self 1446 } 1447 } 1448 1449 // SAFETY: `SysMem<'_, T>` is conceptually `&T`. 1450 unsafe impl<T: ?Sized + Sync> Send for SysMem<'_, T> {} 1451 1452 // SAFETY: `SysMem<'_, T>` is conceptually `&T`. 1453 unsafe impl<T: ?Sized + Sync> Sync for SysMem<'_, T> {} 1454 1455 impl<'a, T: ?Sized> SysMem<'a, T> { 1456 /// Create a `SysMem` from a raw pointer. 1457 /// 1458 /// # Safety 1459 /// 1460 /// `ptr.addr() .. ptr.addr() + KnownSize::size(ptr)` must be valid and aligned kernel 1461 /// accessible memory region for the lifetime `'a`. 1462 #[inline] 1463 pub unsafe fn new(ptr: *mut T) -> Self { 1464 // INVARIANT: Per safety requirement. 1465 Self { 1466 ptr, 1467 phantom: PhantomData, 1468 } 1469 } 1470 1471 /// Obtain the raw pointer to the memory. 1472 #[inline] 1473 pub fn as_ptr(self) -> *mut T { 1474 self.ptr 1475 } 1476 } 1477 1478 impl<'a, T: ?Sized + KnownSize> IoBase<'a> for SysMem<'a, T> { 1479 type Backend = SysMemBackend; 1480 type Target = T; 1481 1482 #[inline] 1483 fn as_view(self) -> <Self::Backend as IoBackend>::View<'a, Self::Target> { 1484 self 1485 } 1486 } 1487 1488 /// I/O Backend for [`IoSysMap`]. 1489 pub struct IoSysMapBackend; 1490 1491 /// Either [`Mmio`] or [`SysMem`]. 1492 /// 1493 /// This can be used when a piece of logic may wish to handle both MMIO or system memory but does 1494 /// not want or cannot be generic over I/O backends. This serves a similar purpose to 1495 /// [`include/linux/iosys-map.h`] in C. 1496 /// 1497 /// This type can be used like any other types that implements [`Io`]; this also include 1498 /// [`io_project!`], [`io_read!`], [`io_write!`]. 1499 /// 1500 /// [`include/linux/iosys-map.h`]: srctree/include/linux/iosys-map.h 1501 pub enum IoSysMap<'a, T: ?Sized> { 1502 /// The view is I/O memory. 1503 Io(Mmio<'a, T>), 1504 /// The view is system memory. 1505 Sys(SysMem<'a, T>), 1506 } 1507 1508 impl<T: ?Sized> Copy for IoSysMap<'_, T> {} 1509 impl<T: ?Sized> Clone for IoSysMap<'_, T> { 1510 #[inline] 1511 fn clone(&self) -> Self { 1512 *self 1513 } 1514 } 1515 1516 impl<'a, T: ?Sized> From<Mmio<'a, T>> for IoSysMap<'a, T> { 1517 #[inline] 1518 fn from(value: Mmio<'a, T>) -> Self { 1519 IoSysMap::Io(value) 1520 } 1521 } 1522 1523 impl<'a, T: ?Sized> From<SysMem<'a, T>> for IoSysMap<'a, T> { 1524 #[inline] 1525 fn from(value: SysMem<'a, T>) -> Self { 1526 IoSysMap::Sys(value) 1527 } 1528 } 1529 1530 impl IoBackend for IoSysMapBackend { 1531 type View<'a, T: ?Sized + KnownSize> = IoSysMap<'a, T>; 1532 1533 #[inline] 1534 fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T { 1535 match view { 1536 IoSysMap::Io(l) => MmioBackend::as_ptr(l), 1537 IoSysMap::Sys(r) => SysMemBackend::as_ptr(r), 1538 } 1539 } 1540 1541 #[inline] 1542 unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>( 1543 view: Self::View<'a, T>, 1544 ptr: *mut U, 1545 ) -> Self::View<'a, U> { 1546 match view { 1547 // SAFETY: Per safety requirement. 1548 IoSysMap::Io(l) => IoSysMap::Io(unsafe { MmioBackend::project_view(l, ptr) }), 1549 // SAFETY: Per safety requirement. 1550 IoSysMap::Sys(r) => IoSysMap::Sys(unsafe { SysMemBackend::project_view(r, ptr) }), 1551 } 1552 } 1553 } 1554 1555 impl<T> IoCapable<T> for IoSysMapBackend 1556 where 1557 MmioBackend: IoCapable<T>, 1558 SysMemBackend: IoCapable<T>, 1559 { 1560 #[inline] 1561 fn io_read(view: Self::View<'_, T>) -> T { 1562 match view { 1563 IoSysMap::Io(l) => MmioBackend::io_read(l), 1564 IoSysMap::Sys(r) => SysMemBackend::io_read(r), 1565 } 1566 } 1567 1568 #[inline] 1569 fn io_write<'a>(view: Self::View<'a, T>, value: T) { 1570 match view { 1571 IoSysMap::Io(l) => MmioBackend::io_write(l, value), 1572 IoSysMap::Sys(r) => SysMemBackend::io_write(r, value), 1573 } 1574 } 1575 } 1576 1577 impl IoCopyable for IoSysMapBackend { 1578 #[inline] 1579 unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { 1580 match view { 1581 // SAFETY: Per safety requirement. 1582 IoSysMap::Io(l) => unsafe { MmioBackend::copy_from_io(l, buffer) }, 1583 // SAFETY: Per safety requirement. 1584 IoSysMap::Sys(r) => unsafe { SysMemBackend::copy_from_io(r, buffer) }, 1585 } 1586 } 1587 1588 #[inline] 1589 unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { 1590 match view { 1591 // SAFETY: Per safety requirement. 1592 IoSysMap::Io(l) => unsafe { MmioBackend::copy_to_io(l, buffer) }, 1593 // SAFETY: Per safety requirement. 1594 IoSysMap::Sys(r) => unsafe { SysMemBackend::copy_to_io(r, buffer) }, 1595 } 1596 } 1597 1598 #[inline] 1599 fn copy_read<T: FromBytes>(view: Self::View<'_, T>) -> T { 1600 match view { 1601 IoSysMap::Io(l) => MmioBackend::copy_read(l), 1602 IoSysMap::Sys(r) => SysMemBackend::copy_read(r), 1603 } 1604 } 1605 1606 #[inline] 1607 fn copy_write<T: IntoBytes>(view: Self::View<'_, T>, value: T) { 1608 match view { 1609 IoSysMap::Io(l) => MmioBackend::copy_write(l, value), 1610 IoSysMap::Sys(r) => SysMemBackend::copy_write(r, value), 1611 } 1612 } 1613 } 1614 1615 impl<'a, T: ?Sized + KnownSize> IoBase<'a> for IoSysMap<'a, T> { 1616 type Backend = IoSysMapBackend; 1617 type Target = T; 1618 1619 #[inline] 1620 fn as_view(self) -> IoSysMap<'a, T> { 1621 self 1622 } 1623 } 1624 1625 // This helper turns associated functions to methods so it can be invoked in macro. 1626 // Used by `io_project!()` only. 1627 #[doc(hidden)] 1628 #[derive(Clone, Copy)] 1629 pub struct ProjectHelper<T>(pub T); 1630 1631 impl<'a, T> ProjectHelper<T> 1632 where 1633 T: Io<'a, Backend: IoBackend<View<'a, T::Target> = T>>, 1634 { 1635 // These helper methods must not have symbols present in the binary to avoid confusion. 1636 #[inline(always)] 1637 pub fn as_ptr(self) -> *mut T::Target { 1638 T::Backend::as_ptr(self.0) 1639 } 1640 1641 /// # Safety 1642 /// 1643 /// Same as `IoBackend::project_view` 1644 #[inline(always)] 1645 pub unsafe fn project_view<U: ?Sized + KnownSize>( 1646 self, 1647 ptr: *mut U, 1648 ) -> <T::Backend as IoBackend>::View<'a, U> { 1649 // SAFETY: Per safety requirement. 1650 unsafe { T::Backend::project_view::<T::Target, _>(self.0, ptr) } 1651 } 1652 } 1653 1654 /// Project an I/O type to a subview of it. 1655 /// 1656 /// The syntax is of form `io_project!(io, proj)` where `io` is an expression to a type that 1657 /// implements [`Io`] and `proj` is a [projection specification](kernel::ptr::project!). 1658 /// 1659 /// # Examples 1660 /// 1661 /// ``` 1662 /// use kernel::io::{ 1663 /// io_project, 1664 /// Mmio, 1665 /// }; 1666 /// #[repr(C)] 1667 /// struct MyStruct { field: u32, } 1668 /// 1669 /// # fn test(mmio: Mmio<'_, [MyStruct]>) -> Result { 1670 /// // let mmio: Mmio<[MyStruct]>; 1671 /// let field: Mmio<'_, u32> = io_project!(mmio, [try: 1].field); 1672 /// let whole: Mmio<'_, MyStruct> = io_project!(mmio, [try: 2]); 1673 /// let nested: Mmio<'_, u32> = io_project!(whole, .field); 1674 /// # Ok::<(), Error>(()) } 1675 /// ``` 1676 #[macro_export] 1677 #[doc(hidden)] 1678 macro_rules! io_project { 1679 ($io:expr, $($proj:tt)*) => {{ 1680 #[allow(unused)] 1681 use $crate::io::IoBase as _; 1682 let view = $crate::io::ProjectHelper($io.as_view()); 1683 let ptr = $crate::ptr::project!( 1684 mut view.as_ptr(), $($proj)* 1685 ); 1686 #[allow(unused_unsafe)] 1687 // SAFETY: `ptr` is a projection. 1688 unsafe { view.project_view(ptr) } 1689 }}; 1690 } 1691 #[doc(inline)] 1692 pub use crate::io_project; 1693 1694 /// Read from I/O memory. 1695 /// 1696 /// The syntax is of form `io_read!(io, proj)` where `io` is an expression to a type that 1697 /// implements [`Io`] and `proj` is a [projection specification](kernel::ptr::project!). 1698 /// 1699 /// # Examples 1700 /// 1701 /// ``` 1702 /// #[repr(C)] 1703 /// struct MyStruct { field: u32, } 1704 /// 1705 /// # fn test(mmio: kernel::io::Mmio<'_, [MyStruct]>) -> Result { 1706 /// // let mmio: Mmio<'_, [MyStruct]>; 1707 /// let field: u32 = kernel::io::io_read!(mmio, [try: 2].field); 1708 /// # Ok::<(), Error>(()) } 1709 /// ``` 1710 #[macro_export] 1711 #[doc(hidden)] 1712 macro_rules! io_read { 1713 ($io:expr, $($proj:tt)*) => { 1714 $crate::io::Io::read_val($crate::io_project!($io, $($proj)*)) 1715 }; 1716 } 1717 #[doc(inline)] 1718 pub use crate::io_read; 1719 1720 /// Writes to I/O memory. 1721 /// 1722 /// The syntax is of form `io_write!(io, proj, val)` where `io` is an expression to a type that 1723 /// implements [`Io`] and `proj` is a [projection specification](kernel::ptr::project!), 1724 /// and `val` is the value to be written to the projected location. 1725 /// 1726 /// # Examples 1727 /// 1728 /// ``` 1729 /// #[repr(C)] 1730 /// struct MyStruct { field: u32, } 1731 /// 1732 /// # fn test(mmio: kernel::io::Mmio<'_, [MyStruct]>) -> Result { 1733 /// // let mmio: Mmio<'_, [MyStruct]>; 1734 /// kernel::io::io_write!(mmio, [try: 2].field, 10); 1735 /// # Ok::<(), Error>(()) } 1736 /// ``` 1737 #[macro_export] 1738 #[doc(hidden)] 1739 macro_rules! io_write { 1740 (@parse [$io:expr] [$($proj:tt)*] [, $val:expr]) => { 1741 $crate::io::Io::write_val($crate::io_project!($io, $($proj)*), $val) 1742 }; 1743 (@parse [$io:expr] [$($proj:tt)*] [.$field:tt $($rest:tt)*]) => { 1744 $crate::io_write!(@parse [$io] [$($proj)* .$field] [$($rest)*]) 1745 }; 1746 (@parse [$io:expr] [$($proj:tt)*] [[$flavor:ident: $index:expr] $($rest:tt)*]) => { 1747 $crate::io_write!(@parse [$io] [$($proj)* [$flavor: $index]] [$($rest)*]) 1748 }; 1749 ($io:expr, $($rest:tt)*) => { 1750 $crate::io_write!(@parse [$io] [] [$($rest)*]) 1751 }; 1752 } 1753 #[doc(inline)] 1754 pub use crate::io_write; 1755