1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Direct memory access (DMA). 4 //! 5 //! C header: [`include/linux/dma-mapping.h`](srctree/include/linux/dma-mapping.h) 6 7 use crate::{ 8 bindings, 9 debugfs, 10 device::{ 11 self, 12 Bound, 13 Core, // 14 }, 15 error::to_result, 16 fs::file, 17 io::{ 18 IoBackend, 19 IoBase, 20 IoCapable, 21 IoCopyable, 22 SysMem, 23 SysMemBackend, // 24 }, 25 prelude::*, 26 ptr::KnownSize, 27 sync::aref::ARef, 28 transmute::{ 29 AsBytes, 30 FromBytes, // 31 }, 32 uaccess::UserSliceWriter, // 33 }; 34 use core::{ 35 ops::{ 36 Deref, 37 DerefMut, // 38 }, 39 ptr::NonNull, // 40 }; 41 42 /// DMA address type. 43 /// 44 /// Represents a bus address used for Direct Memory Access (DMA) operations. 45 /// 46 /// This is an alias of the kernel's `dma_addr_t`, which may be `u32` or `u64` depending on 47 /// `CONFIG_ARCH_DMA_ADDR_T_64BIT`. 48 /// 49 /// Note that this may be `u64` even on 32-bit architectures. 50 pub type DmaAddress = bindings::dma_addr_t; 51 52 /// Trait to be implemented by DMA capable bus devices. 53 /// 54 /// The [`dma::Device`](Device) trait should be implemented by bus specific device representations, 55 /// where the underlying bus is DMA capable, such as: 56 #[cfg_attr(CONFIG_PCI, doc = "* [`pci::Device`](kernel::pci::Device)")] 57 /// * [`platform::Device`](::kernel::platform::Device) 58 pub trait Device<'a>: AsRef<device::Device<Core<'a>>> { 59 /// Set up the device's DMA streaming addressing capabilities. 60 /// 61 /// This method is usually called once from `probe()` as soon as the device capabilities are 62 /// known. 63 /// 64 /// # Safety 65 /// 66 /// This method must not be called concurrently with any DMA allocation or mapping primitives, 67 /// such as [`Coherent::zeroed`]. 68 unsafe fn dma_set_mask(&self, mask: DmaMask) -> Result { 69 // SAFETY: 70 // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. 71 // - The safety requirement of this function guarantees that there are no concurrent calls 72 // to DMA allocation and mapping primitives using this mask. 73 to_result(unsafe { bindings::dma_set_mask(self.as_ref().as_raw(), mask.value()) }) 74 } 75 76 /// Set up the device's DMA coherent addressing capabilities. 77 /// 78 /// This method is usually called once from `probe()` as soon as the device capabilities are 79 /// known. 80 /// 81 /// # Safety 82 /// 83 /// This method must not be called concurrently with any DMA allocation or mapping primitives, 84 /// such as [`Coherent::zeroed`]. 85 unsafe fn dma_set_coherent_mask(&self, mask: DmaMask) -> Result { 86 // SAFETY: 87 // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. 88 // - The safety requirement of this function guarantees that there are no concurrent calls 89 // to DMA allocation and mapping primitives using this mask. 90 to_result(unsafe { bindings::dma_set_coherent_mask(self.as_ref().as_raw(), mask.value()) }) 91 } 92 93 /// Set up the device's DMA addressing capabilities. 94 /// 95 /// This is a combination of [`Device::dma_set_mask`] and [`Device::dma_set_coherent_mask`]. 96 /// 97 /// This method is usually called once from `probe()` as soon as the device capabilities are 98 /// known. 99 /// 100 /// # Safety 101 /// 102 /// This method must not be called concurrently with any DMA allocation or mapping primitives, 103 /// such as [`Coherent::zeroed`]. 104 unsafe fn dma_set_mask_and_coherent(&self, mask: DmaMask) -> Result { 105 // SAFETY: 106 // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. 107 // - The safety requirement of this function guarantees that there are no concurrent calls 108 // to DMA allocation and mapping primitives using this mask. 109 to_result(unsafe { 110 bindings::dma_set_mask_and_coherent(self.as_ref().as_raw(), mask.value()) 111 }) 112 } 113 114 /// Set the maximum size of a single DMA segment the device may request. 115 /// 116 /// This method is usually called once from `probe()` as soon as the device capabilities are 117 /// known. 118 /// 119 /// # Safety 120 /// 121 /// This method must not be called concurrently with any DMA allocation or mapping primitives, 122 /// such as [`Coherent::zeroed`]. 123 unsafe fn dma_set_max_seg_size(&self, size: u32) { 124 // SAFETY: 125 // - By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid. 126 // - The safety requirement of this function guarantees that there are no concurrent calls 127 // to DMA allocation and mapping primitives using this parameter. 128 unsafe { bindings::dma_set_max_seg_size(self.as_ref().as_raw(), size) } 129 } 130 } 131 132 /// A DMA mask that holds a bitmask with the lowest `n` bits set. 133 /// 134 /// Use [`DmaMask::new`] or [`DmaMask::try_new`] to construct a value. Values 135 /// are guaranteed to never exceed the bit width of `u64`. 136 /// 137 /// This is the Rust equivalent of the C macro `DMA_BIT_MASK()`. 138 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 139 pub struct DmaMask(u64); 140 141 impl DmaMask { 142 /// Constructs a `DmaMask` with the lowest `n` bits set to `1`. 143 /// 144 /// For `n <= 64`, sets exactly the lowest `n` bits. 145 /// For `n > 64`, results in a build error. 146 /// 147 /// # Examples 148 /// 149 /// ``` 150 /// use kernel::dma::DmaMask; 151 /// 152 /// let mask0 = DmaMask::new::<0>(); 153 /// assert_eq!(mask0.value(), 0); 154 /// 155 /// let mask1 = DmaMask::new::<1>(); 156 /// assert_eq!(mask1.value(), 0b1); 157 /// 158 /// let mask64 = DmaMask::new::<64>(); 159 /// assert_eq!(mask64.value(), u64::MAX); 160 /// 161 /// // Build failure. 162 /// // let mask_overflow = DmaMask::new::<100>(); 163 /// ``` 164 #[inline] 165 pub const fn new<const N: u32>() -> Self { 166 let Ok(mask) = Self::try_new(N) else { 167 build_error!("Invalid DMA Mask."); 168 }; 169 170 mask 171 } 172 173 /// Constructs a `DmaMask` with the lowest `n` bits set to `1`. 174 /// 175 /// For `n <= 64`, sets exactly the lowest `n` bits. 176 /// For `n > 64`, returns [`EINVAL`]. 177 /// 178 /// # Examples 179 /// 180 /// ``` 181 /// use kernel::dma::DmaMask; 182 /// 183 /// let mask0 = DmaMask::try_new(0)?; 184 /// assert_eq!(mask0.value(), 0); 185 /// 186 /// let mask1 = DmaMask::try_new(1)?; 187 /// assert_eq!(mask1.value(), 0b1); 188 /// 189 /// let mask64 = DmaMask::try_new(64)?; 190 /// assert_eq!(mask64.value(), u64::MAX); 191 /// 192 /// let mask_overflow = DmaMask::try_new(100); 193 /// assert!(mask_overflow.is_err()); 194 /// # Ok::<(), Error>(()) 195 /// ``` 196 #[inline] 197 pub const fn try_new(n: u32) -> Result<Self> { 198 Ok(Self(match n { 199 0 => 0, 200 1..=64 => u64::MAX >> (64 - n), 201 _ => return Err(EINVAL), 202 })) 203 } 204 205 /// Returns the underlying `u64` bitmask value. 206 #[inline] 207 pub const fn value(&self) -> u64 { 208 self.0 209 } 210 } 211 212 /// Possible attributes associated with a DMA mapping. 213 /// 214 /// They can be combined with the operators `|`, `&`, and `!`. 215 /// 216 /// Values can be used from the [`attrs`] module. 217 /// 218 /// # Examples 219 /// 220 /// ``` 221 /// # use kernel::device::{Bound, Device}; 222 /// use kernel::dma::{attrs::*, Coherent}; 223 /// 224 /// # fn test(dev: &Device<Bound>) -> Result { 225 /// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN; 226 /// let c: Coherent<[u64]> = 227 /// Coherent::zeroed_slice_with_attrs(dev, 4, GFP_KERNEL, attribs)?; 228 /// # Ok::<(), Error>(()) } 229 /// ``` 230 #[derive(Clone, Copy, PartialEq)] 231 #[repr(transparent)] 232 pub struct Attrs(u32); 233 234 impl Attrs { 235 /// Get the raw representation of this attribute. 236 pub(crate) fn as_raw(self) -> crate::ffi::c_ulong { 237 self.0 as crate::ffi::c_ulong 238 } 239 240 /// Check whether `flags` is contained in `self`. 241 pub fn contains(self, flags: Attrs) -> bool { 242 (self & flags) == flags 243 } 244 } 245 246 impl core::ops::BitOr for Attrs { 247 type Output = Self; 248 fn bitor(self, rhs: Self) -> Self::Output { 249 Self(self.0 | rhs.0) 250 } 251 } 252 253 impl core::ops::BitAnd for Attrs { 254 type Output = Self; 255 fn bitand(self, rhs: Self) -> Self::Output { 256 Self(self.0 & rhs.0) 257 } 258 } 259 260 impl core::ops::Not for Attrs { 261 type Output = Self; 262 fn not(self) -> Self::Output { 263 Self(!self.0) 264 } 265 } 266 267 /// DMA mapping attributes. 268 pub mod attrs { 269 use super::Attrs; 270 271 /// Specifies that reads and writes to the mapping may be weakly ordered, that is that reads 272 /// and writes may pass each other. 273 pub const DMA_ATTR_WEAK_ORDERING: Attrs = Attrs(bindings::DMA_ATTR_WEAK_ORDERING); 274 275 /// Specifies that writes to the mapping may be buffered to improve performance. 276 pub const DMA_ATTR_WRITE_COMBINE: Attrs = Attrs(bindings::DMA_ATTR_WRITE_COMBINE); 277 278 /// Allows platform code to skip synchronization of the CPU cache for the given buffer assuming 279 /// that it has been already transferred to 'device' domain. 280 pub const DMA_ATTR_SKIP_CPU_SYNC: Attrs = Attrs(bindings::DMA_ATTR_SKIP_CPU_SYNC); 281 282 /// Forces contiguous allocation of the buffer in physical memory. 283 pub const DMA_ATTR_FORCE_CONTIGUOUS: Attrs = Attrs(bindings::DMA_ATTR_FORCE_CONTIGUOUS); 284 285 /// Hints DMA-mapping subsystem that it's probably not worth the time to try 286 /// to allocate memory to in a way that gives better TLB efficiency. 287 pub const DMA_ATTR_ALLOC_SINGLE_PAGES: Attrs = Attrs(bindings::DMA_ATTR_ALLOC_SINGLE_PAGES); 288 289 /// This tells the DMA-mapping subsystem to suppress allocation failure reports (similarly to 290 /// `__GFP_NOWARN`). 291 pub const DMA_ATTR_NO_WARN: Attrs = Attrs(bindings::DMA_ATTR_NO_WARN); 292 293 /// Indicates that the buffer is fully accessible at an elevated privilege level (and 294 /// ideally inaccessible or at least read-only at lesser-privileged levels). 295 pub const DMA_ATTR_PRIVILEGED: Attrs = Attrs(bindings::DMA_ATTR_PRIVILEGED); 296 297 /// Indicates that the buffer is MMIO memory. 298 pub const DMA_ATTR_MMIO: Attrs = Attrs(bindings::DMA_ATTR_MMIO); 299 } 300 301 /// DMA data direction. 302 /// 303 /// Corresponds to the C [`enum dma_data_direction`]. 304 /// 305 /// [`enum dma_data_direction`]: srctree/include/linux/dma-direction.h 306 #[derive(Copy, Clone, PartialEq, Eq, Debug)] 307 #[repr(u32)] 308 pub enum DataDirection { 309 /// The DMA mapping is for bidirectional data transfer. 310 /// 311 /// This is used when the buffer can be both read from and written to by the device. 312 /// The cache for the corresponding memory region is both flushed and invalidated. 313 Bidirectional = Self::const_cast(bindings::dma_data_direction_DMA_BIDIRECTIONAL), 314 315 /// The DMA mapping is for data transfer from memory to the device (write). 316 /// 317 /// The CPU has prepared data in the buffer, and the device will read it. 318 /// The cache for the corresponding memory region is flushed before device access. 319 ToDevice = Self::const_cast(bindings::dma_data_direction_DMA_TO_DEVICE), 320 321 /// The DMA mapping is for data transfer from the device to memory (read). 322 /// 323 /// The device will write data into the buffer for the CPU to read. 324 /// The cache for the corresponding memory region is invalidated before CPU access. 325 FromDevice = Self::const_cast(bindings::dma_data_direction_DMA_FROM_DEVICE), 326 327 /// The DMA mapping is not for data transfer. 328 /// 329 /// This is primarily for debugging purposes. With this direction, the DMA mapping API 330 /// will not perform any cache coherency operations. 331 None = Self::const_cast(bindings::dma_data_direction_DMA_NONE), 332 } 333 334 impl DataDirection { 335 /// Casts the bindgen-generated enum type to a `u32` at compile time. 336 /// 337 /// This function will cause a compile-time error if the underlying value of the 338 /// C enum is out of bounds for `u32`. 339 const fn const_cast(val: bindings::dma_data_direction) -> u32 { 340 // CAST: The C standard allows compilers to choose different integer types for enums. 341 // To safely check the value, we cast it to a wide signed integer type (`i128`) 342 // which can hold any standard C integer enum type without truncation. 343 let wide_val = val as i128; 344 345 // Check if the value is outside the valid range for the target type `u32`. 346 // CAST: `u32::MAX` is cast to `i128` to match the type of `wide_val` for the comparison. 347 if wide_val < 0 || wide_val > u32::MAX as i128 { 348 // Trigger a compile-time error in a const context. 349 build_error!("C enum value is out of bounds for the target type `u32`."); 350 } 351 352 // CAST: This cast is valid because the check above guarantees that `wide_val` 353 // is within the representable range of `u32`. 354 wide_val as u32 355 } 356 } 357 358 impl From<DataDirection> for bindings::dma_data_direction { 359 /// Returns the raw representation of [`enum dma_data_direction`]. 360 fn from(direction: DataDirection) -> Self { 361 // CAST: `direction as u32` gets the underlying representation of our `#[repr(u32)]` enum. 362 // The subsequent cast to `Self` (the bindgen type) assumes the C enum is compatible 363 // with the enum variants of `DataDirection`, which is a valid assumption given our 364 // compile-time checks. 365 direction as u32 as Self 366 } 367 } 368 369 /// CPU-owned DMA allocation that can be converted into a device-shared [`Coherent`] object. 370 /// 371 /// Unlike [`Coherent`], a [`CoherentBox`] is guaranteed to be fully owned by the CPU -- its DMA 372 /// address is not exposed and it cannot be accessed by a device. This means it can safely be used 373 /// like a normal boxed allocation (e.g. direct reads, writes, and mutable slices are all safe). 374 /// 375 /// A typical use is to allocate a [`CoherentBox`], populate it with normal CPU access, and then 376 /// convert it into a [`Coherent`] object to share it with the device. 377 /// 378 /// # Examples 379 /// 380 /// `CoherentBox<T>`: 381 /// 382 /// ``` 383 /// # use kernel::device::{ 384 /// # Bound, 385 /// # Device, 386 /// # }; 387 /// use kernel::dma::{attrs::*, 388 /// Coherent, 389 /// CoherentBox, 390 /// }; 391 /// 392 /// # fn test(dev: &Device<Bound>) -> Result { 393 /// let mut dmem: CoherentBox<u64> = CoherentBox::zeroed(dev, GFP_KERNEL)?; 394 /// *dmem = 42; 395 /// let dmem: Coherent<u64> = dmem.into(); 396 /// # Ok::<(), Error>(()) } 397 /// ``` 398 /// 399 /// `CoherentBox<[T]>`: 400 /// 401 /// 402 /// ``` 403 /// # use kernel::device::{ 404 /// # Bound, 405 /// # Device, 406 /// # }; 407 /// use kernel::dma::{attrs::*, 408 /// Coherent, 409 /// CoherentBox, 410 /// }; 411 /// 412 /// # fn test(dev: &Device<Bound>) -> Result { 413 /// let mut dmem: CoherentBox<[u64]> = CoherentBox::zeroed_slice(dev, 4, GFP_KERNEL)?; 414 /// dmem.fill(42); 415 /// let dmem: Coherent<[u64]> = dmem.into(); 416 /// # Ok::<(), Error>(()) } 417 /// ``` 418 pub struct CoherentBox<T: KnownSize + ?Sized>(Coherent<T>); 419 420 impl<T: AsBytes + FromBytes> CoherentBox<[T]> { 421 /// [`CoherentBox`] variant of [`Coherent::zeroed_slice_with_attrs`]. 422 #[inline] 423 pub fn zeroed_slice_with_attrs( 424 dev: &device::Device<Bound>, 425 count: usize, 426 gfp_flags: kernel::alloc::Flags, 427 dma_attrs: Attrs, 428 ) -> Result<Self> { 429 Coherent::zeroed_slice_with_attrs(dev, count, gfp_flags, dma_attrs).map(Self) 430 } 431 432 /// Same as [CoherentBox::zeroed_slice_with_attrs], but with `dma::Attrs(0)`. 433 #[inline] 434 pub fn zeroed_slice( 435 dev: &device::Device<Bound>, 436 count: usize, 437 gfp_flags: kernel::alloc::Flags, 438 ) -> Result<Self> { 439 Self::zeroed_slice_with_attrs(dev, count, gfp_flags, Attrs(0)) 440 } 441 442 /// Initializes the element at `i` using the given initializer. 443 /// 444 /// Returns `EINVAL` if `i` is out of bounds. 445 pub fn init_at<E>(&mut self, i: usize, init: impl Init<T, E>) -> Result 446 where 447 Error: From<E>, 448 { 449 if i >= self.0.len() { 450 return Err(EINVAL); 451 } 452 453 let ptr = &raw mut self[i]; 454 455 // SAFETY: 456 // - `ptr` is valid, properly aligned, and within this allocation. 457 // - `T: AsBytes + FromBytes` guarantees all bit patterns are valid, so partial writes on 458 // error cannot leave the element in an invalid state. 459 // - The DMA address has not been exposed yet, so there is no concurrent device access. 460 unsafe { init.__init(ptr)? }; 461 462 Ok(()) 463 } 464 465 /// Allocates a region of coherent memory of the same size as `data` and initializes it with a 466 /// copy of its contents. 467 /// 468 /// This is the [`CoherentBox`] variant of [`Coherent::from_slice_with_attrs`]. 469 /// 470 /// # Examples 471 /// 472 /// ``` 473 /// use core::ops::Deref; 474 /// 475 /// # use kernel::device::{Bound, Device}; 476 /// use kernel::dma::{ 477 /// attrs::*, 478 /// CoherentBox 479 /// }; 480 /// 481 /// # fn test(dev: &Device<Bound>) -> Result { 482 /// let data = [0u8, 1u8, 2u8, 3u8]; 483 /// let c: CoherentBox<[u8]> = 484 /// CoherentBox::from_slice_with_attrs(dev, &data, GFP_KERNEL, DMA_ATTR_NO_WARN)?; 485 /// 486 /// assert_eq!(c.deref(), &data); 487 /// # Ok::<(), Error>(()) } 488 /// ``` 489 pub fn from_slice_with_attrs( 490 dev: &device::Device<Bound>, 491 data: &[T], 492 gfp_flags: kernel::alloc::Flags, 493 dma_attrs: Attrs, 494 ) -> Result<Self> 495 where 496 T: Copy, 497 { 498 let mut slice = Self(Coherent::<T>::alloc_slice_with_attrs( 499 dev, 500 data.len(), 501 gfp_flags, 502 dma_attrs, 503 )?); 504 505 // PANIC: `slice` was created with length `data.len()`. 506 slice.copy_from_slice(data); 507 508 Ok(slice) 509 } 510 511 /// Performs the same functionality as [`CoherentBox::from_slice_with_attrs`], except the 512 /// `dma_attrs` is 0 by default. 513 #[inline] 514 pub fn from_slice( 515 dev: &device::Device<Bound>, 516 data: &[T], 517 gfp_flags: kernel::alloc::Flags, 518 ) -> Result<Self> 519 where 520 T: Copy, 521 { 522 Self::from_slice_with_attrs(dev, data, gfp_flags, Attrs(0)) 523 } 524 } 525 526 impl<T: AsBytes + FromBytes> CoherentBox<T> { 527 /// Same as [`CoherentBox::zeroed_slice_with_attrs`], but for a single element. 528 #[inline] 529 pub fn zeroed_with_attrs( 530 dev: &device::Device<Bound>, 531 gfp_flags: kernel::alloc::Flags, 532 dma_attrs: Attrs, 533 ) -> Result<Self> { 534 Coherent::zeroed_with_attrs(dev, gfp_flags, dma_attrs).map(Self) 535 } 536 537 /// Same as [`CoherentBox::zeroed_slice`], but for a single element. 538 #[inline] 539 pub fn zeroed(dev: &device::Device<Bound>, gfp_flags: kernel::alloc::Flags) -> Result<Self> { 540 Self::zeroed_with_attrs(dev, gfp_flags, Attrs(0)) 541 } 542 } 543 544 impl<T: KnownSize + ?Sized> Deref for CoherentBox<T> { 545 type Target = T; 546 547 #[inline] 548 fn deref(&self) -> &Self::Target { 549 // SAFETY: 550 // - We have not exposed the DMA address yet, so there can't be any concurrent access by a 551 // device. 552 // - We have exclusive access to `self.0`. 553 unsafe { self.0.as_ref() } 554 } 555 } 556 557 impl<T: AsBytes + FromBytes + KnownSize + ?Sized> DerefMut for CoherentBox<T> { 558 #[inline] 559 fn deref_mut(&mut self) -> &mut Self::Target { 560 // SAFETY: 561 // - We have not exposed the DMA address yet, so there can't be any concurrent access by a 562 // device. 563 // - We have exclusive access to `self.0`. 564 unsafe { self.0.as_mut() } 565 } 566 } 567 568 impl<T: AsBytes + FromBytes + KnownSize + ?Sized> From<CoherentBox<T>> for Coherent<T> { 569 #[inline] 570 fn from(value: CoherentBox<T>) -> Self { 571 value.0 572 } 573 } 574 575 /// An abstraction of the `dma_alloc_coherent` API. 576 /// 577 /// This is an abstraction around the `dma_alloc_coherent` API which is used to allocate and map 578 /// large coherent DMA regions. 579 /// 580 /// A [`Coherent`] instance contains a pointer to the allocated region (in the 581 /// processor's virtual address space) and the device address which can be given to the device 582 /// as the DMA address base of the region. The region is released once [`Coherent`] 583 /// is dropped. 584 /// 585 /// # Invariants 586 /// 587 /// - For the lifetime of an instance of [`Coherent`], the `cpu_addr` is a valid pointer 588 /// to an allocated region of coherent memory and `dma_handle` is the DMA address base of the 589 /// region. 590 /// - The size in bytes of the allocation is equal to size information via pointer. 591 // TODO 592 // 593 // DMA allocations potentially carry device resources (e.g.IOMMU mappings), hence for soundness 594 // reasons DMA allocation would need to be embedded in a `Devres` container, in order to ensure 595 // that device resources can never survive device unbind. 596 // 597 // However, it is neither desirable nor necessary to protect the allocated memory of the DMA 598 // allocation from surviving device unbind; it would require RCU read side critical sections to 599 // access the memory, which may require subsequent unnecessary copies. 600 // 601 // Hence, find a way to revoke the device resources of a `Coherent`, but not the 602 // entire `Coherent` including the allocated memory itself. 603 pub struct Coherent<T: KnownSize + ?Sized> { 604 dev: ARef<device::Device>, 605 dma_handle: DmaAddress, 606 cpu_addr: NonNull<T>, 607 dma_attrs: Attrs, 608 } 609 610 impl<T: KnownSize + ?Sized> Coherent<T> { 611 /// Returns the size in bytes of this allocation. 612 #[inline] 613 pub fn size(&self) -> usize { 614 T::size(self.cpu_addr.as_ptr()) 615 } 616 617 /// Returns the raw pointer to the allocated region in the CPU's virtual address space. 618 #[inline] 619 pub fn as_ptr(&self) -> *const T { 620 self.cpu_addr.as_ptr() 621 } 622 623 /// Returns the raw pointer to the allocated region in the CPU's virtual address space as 624 /// a mutable pointer. 625 #[inline] 626 pub fn as_mut_ptr(&self) -> *mut T { 627 self.cpu_addr.as_ptr() 628 } 629 630 /// Returns a DMA handle which may be given to the device as the DMA address base of 631 /// the region. 632 #[inline] 633 pub fn dma_handle(&self) -> DmaAddress { 634 self.dma_handle 635 } 636 637 /// Returns a reference to the data in the region. 638 /// 639 /// # Safety 640 /// 641 /// * Callers must ensure that the device does not read/write to/from memory while the returned 642 /// slice is live. 643 /// * Callers must ensure that this call does not race with a write to the same region while 644 /// the returned slice is live. 645 #[inline] 646 pub unsafe fn as_ref(&self) -> &T { 647 // SAFETY: per safety requirement. 648 unsafe { &*self.as_ptr() } 649 } 650 651 /// Returns a mutable reference to the data in the region. 652 /// 653 /// # Safety 654 /// 655 /// * Callers must ensure that the device does not read/write to/from memory while the returned 656 /// slice is live. 657 /// * Callers must ensure that this call does not race with a read or write to the same region 658 /// while the returned slice is live. 659 #[expect(clippy::mut_from_ref, reason = "unsafe to use API")] 660 #[inline] 661 pub unsafe fn as_mut(&self) -> &mut T { 662 // SAFETY: per safety requirement. 663 unsafe { &mut *self.as_mut_ptr() } 664 } 665 } 666 667 impl<T: AsBytes + FromBytes> Coherent<T> { 668 /// Allocates a region of `T` of coherent memory. 669 fn alloc_with_attrs( 670 dev: &device::Device<Bound>, 671 gfp_flags: kernel::alloc::Flags, 672 dma_attrs: Attrs, 673 ) -> Result<Self> { 674 const { 675 assert!( 676 core::mem::size_of::<T>() > 0, 677 "It doesn't make sense for the allocated type to be a ZST" 678 ); 679 } 680 681 let mut dma_handle = 0; 682 // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`. 683 let addr = unsafe { 684 bindings::dma_alloc_attrs( 685 dev.as_raw(), 686 core::mem::size_of::<T>(), 687 &mut dma_handle, 688 gfp_flags.as_raw(), 689 dma_attrs.as_raw(), 690 ) 691 }; 692 let cpu_addr = NonNull::new(addr.cast()).ok_or(ENOMEM)?; 693 // INVARIANT: 694 // - We just successfully allocated a coherent region which is adequately sized for `T`, 695 // hence the cpu address is valid. 696 // - We also hold a refcounted reference to the device. 697 Ok(Self { 698 dev: dev.into(), 699 dma_handle, 700 cpu_addr, 701 dma_attrs, 702 }) 703 } 704 705 /// Allocates a region of type `T` of coherent memory. 706 /// 707 /// # Examples 708 /// 709 /// ``` 710 /// # use kernel::device::{ 711 /// # Bound, 712 /// # Device, 713 /// # }; 714 /// use kernel::dma::{ 715 /// attrs::*, 716 /// Coherent, 717 /// }; 718 /// 719 /// # fn test(dev: &Device<Bound>) -> Result { 720 /// let c: Coherent<[u64; 4]> = 721 /// Coherent::zeroed_with_attrs(dev, GFP_KERNEL, DMA_ATTR_NO_WARN)?; 722 /// # Ok::<(), Error>(()) } 723 /// ``` 724 #[inline] 725 pub fn zeroed_with_attrs( 726 dev: &device::Device<Bound>, 727 gfp_flags: kernel::alloc::Flags, 728 dma_attrs: Attrs, 729 ) -> Result<Self> { 730 Self::alloc_with_attrs(dev, gfp_flags | __GFP_ZERO, dma_attrs) 731 } 732 733 /// Performs the same functionality as [`Coherent::zeroed_with_attrs`], except the 734 /// `dma_attrs` is 0 by default. 735 #[inline] 736 pub fn zeroed(dev: &device::Device<Bound>, gfp_flags: kernel::alloc::Flags) -> Result<Self> { 737 Self::zeroed_with_attrs(dev, gfp_flags, Attrs(0)) 738 } 739 740 /// Same as [`Coherent::zeroed_with_attrs`], but instead of a zero-initialization the memory is 741 /// initialized with `init`. 742 pub fn init_with_attrs<E>( 743 dev: &device::Device<Bound>, 744 gfp_flags: kernel::alloc::Flags, 745 dma_attrs: Attrs, 746 init: impl Init<T, E>, 747 ) -> Result<Self> 748 where 749 Error: From<E>, 750 { 751 let dmem = Self::alloc_with_attrs(dev, gfp_flags, dma_attrs)?; 752 let ptr = dmem.as_mut_ptr(); 753 754 // SAFETY: 755 // - `ptr` is valid, properly aligned, and points to exclusively owned memory. 756 // - If `__init` fails, `self` is dropped, which safely frees the underlying `Coherent`'s 757 // DMA memory. `T: AsBytes + FromBytes` ensures there are no complex `Drop` requirements 758 // we are bypassing. 759 unsafe { init.__init(ptr)? }; 760 761 Ok(dmem) 762 } 763 764 /// Same as [`Coherent::zeroed`], but instead of a zero-initialization the memory is initialized 765 /// with `init`. 766 #[inline] 767 pub fn init<E>( 768 dev: &device::Device<Bound>, 769 gfp_flags: kernel::alloc::Flags, 770 init: impl Init<T, E>, 771 ) -> Result<Self> 772 where 773 Error: From<E>, 774 { 775 Self::init_with_attrs(dev, gfp_flags, Attrs(0), init) 776 } 777 778 /// Allocates a region of `[T; len]` of coherent memory. 779 fn alloc_slice_with_attrs( 780 dev: &device::Device<Bound>, 781 len: usize, 782 gfp_flags: kernel::alloc::Flags, 783 dma_attrs: Attrs, 784 ) -> Result<Coherent<[T]>> { 785 const { 786 assert!( 787 core::mem::size_of::<T>() > 0, 788 "It doesn't make sense for the allocated type to be a ZST" 789 ); 790 } 791 792 // `dma_alloc_attrs` cannot handle zero-length allocation, bail early. 793 if len == 0 { 794 Err(EINVAL)?; 795 } 796 797 let size = core::mem::size_of::<T>().checked_mul(len).ok_or(ENOMEM)?; 798 let mut dma_handle = 0; 799 // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`. 800 let addr = unsafe { 801 bindings::dma_alloc_attrs( 802 dev.as_raw(), 803 size, 804 &mut dma_handle, 805 gfp_flags.as_raw(), 806 dma_attrs.as_raw(), 807 ) 808 }; 809 let cpu_addr = NonNull::slice_from_raw_parts(NonNull::new(addr.cast()).ok_or(ENOMEM)?, len); 810 // INVARIANT: 811 // - We just successfully allocated a coherent region which is adequately sized for 812 // `[T; len]`, hence the cpu address is valid. 813 // - We also hold a refcounted reference to the device. 814 Ok(Coherent { 815 dev: dev.into(), 816 dma_handle, 817 cpu_addr, 818 dma_attrs, 819 }) 820 } 821 822 /// Allocates a zeroed region of type `T` of coherent memory. 823 /// 824 /// Unlike `Coherent::<[T; N]>::zeroed_with_attrs`, `Coherent::<T>::zeroed_slices` support 825 /// a runtime length. 826 /// 827 /// # Examples 828 /// 829 /// ``` 830 /// # use kernel::device::{ 831 /// # Bound, 832 /// # Device, 833 /// # }; 834 /// use kernel::dma::{ 835 /// attrs::*, 836 /// Coherent, 837 /// }; 838 /// 839 /// # fn test(dev: &Device<Bound>) -> Result { 840 /// let c: Coherent<[u64]> = 841 /// Coherent::zeroed_slice_with_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?; 842 /// # Ok::<(), Error>(()) } 843 /// ``` 844 #[inline] 845 pub fn zeroed_slice_with_attrs( 846 dev: &device::Device<Bound>, 847 len: usize, 848 gfp_flags: kernel::alloc::Flags, 849 dma_attrs: Attrs, 850 ) -> Result<Coherent<[T]>> { 851 Coherent::alloc_slice_with_attrs(dev, len, gfp_flags | __GFP_ZERO, dma_attrs) 852 } 853 854 /// Performs the same functionality as [`Coherent::zeroed_slice_with_attrs`], except the 855 /// `dma_attrs` is 0 by default. 856 #[inline] 857 pub fn zeroed_slice( 858 dev: &device::Device<Bound>, 859 len: usize, 860 gfp_flags: kernel::alloc::Flags, 861 ) -> Result<Coherent<[T]>> { 862 Self::zeroed_slice_with_attrs(dev, len, gfp_flags, Attrs(0)) 863 } 864 865 /// Allocates a region of coherent memory of the same size as `data` and initializes it with a 866 /// copy of its contents. 867 /// 868 /// # Examples 869 /// 870 /// ``` 871 /// # use kernel::device::{Bound, Device}; 872 /// use kernel::dma::{ 873 /// attrs::*, 874 /// Coherent 875 /// }; 876 /// 877 /// # fn test(dev: &Device<Bound>) -> Result { 878 /// let data = [0u8, 1u8, 2u8, 3u8]; 879 /// // `c` has the same content as `data`. 880 /// let c: Coherent<[u8]> = 881 /// Coherent::from_slice_with_attrs(dev, &data, GFP_KERNEL, DMA_ATTR_NO_WARN)?; 882 /// 883 /// # Ok::<(), Error>(()) } 884 /// ``` 885 #[inline] 886 pub fn from_slice_with_attrs( 887 dev: &device::Device<Bound>, 888 data: &[T], 889 gfp_flags: kernel::alloc::Flags, 890 dma_attrs: Attrs, 891 ) -> Result<Coherent<[T]>> 892 where 893 T: Copy, 894 { 895 CoherentBox::from_slice_with_attrs(dev, data, gfp_flags, dma_attrs).map(Into::into) 896 } 897 898 /// Performs the same functionality as [`Coherent::from_slice_with_attrs`], except the 899 /// `dma_attrs` is 0 by default. 900 #[inline] 901 pub fn from_slice( 902 dev: &device::Device<Bound>, 903 data: &[T], 904 gfp_flags: kernel::alloc::Flags, 905 ) -> Result<Coherent<[T]>> 906 where 907 T: Copy, 908 { 909 Self::from_slice_with_attrs(dev, data, gfp_flags, Attrs(0)) 910 } 911 } 912 913 impl<T> Coherent<[T]> { 914 /// Returns the number of elements `T` in this allocation. 915 /// 916 /// Note that this is not the size of the allocation in bytes, which is provided by 917 /// [`Self::size`]. 918 #[inline] 919 #[expect(clippy::len_without_is_empty, reason = "Coherent slice is never empty")] 920 pub fn len(&self) -> usize { 921 self.cpu_addr.len() 922 } 923 } 924 925 /// Note that the device configured to do DMA must be halted before this object is dropped. 926 impl<T: KnownSize + ?Sized> Drop for Coherent<T> { 927 fn drop(&mut self) { 928 let size = T::size(self.cpu_addr.as_ptr()); 929 // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`. 930 // The cpu address, and the dma handle are valid due to the type invariants on 931 // `Coherent`. 932 unsafe { 933 bindings::dma_free_attrs( 934 self.dev.as_raw(), 935 size, 936 self.cpu_addr.as_ptr().cast(), 937 self.dma_handle, 938 self.dma_attrs.as_raw(), 939 ) 940 } 941 } 942 } 943 944 // SAFETY: It is safe to send a `Coherent` to another thread if `T` 945 // can be sent to another thread. 946 unsafe impl<T: KnownSize + Send + ?Sized> Send for Coherent<T> {} 947 948 // SAFETY: Sharing `&Coherent` across threads is safe if `T` is `Sync`, because all 949 // methods that access the buffer contents (`field_read`, `field_write`, `as_slice`, 950 // `as_slice_mut`) are `unsafe`, and callers are responsible for ensuring no data races occur. 951 // The safe methods only return metadata or raw pointers whose use requires `unsafe`. 952 unsafe impl<T: KnownSize + ?Sized + AsBytes + FromBytes + Sync> Sync for Coherent<T> {} 953 954 impl<T: KnownSize + AsBytes + ?Sized> debugfs::BinaryWriter for Coherent<T> { 955 fn write_to_slice( 956 &self, 957 writer: &mut UserSliceWriter, 958 offset: &mut file::Offset, 959 ) -> Result<usize> { 960 if offset.is_negative() { 961 return Err(EINVAL); 962 } 963 964 // If the offset is too large for a usize (e.g. on 32-bit platforms), 965 // then consider that as past EOF and just return 0 bytes. 966 let Ok(offset_val) = usize::try_from(*offset) else { 967 return Ok(0); 968 }; 969 970 let count = self.size().saturating_sub(offset_val).min(writer.len()); 971 972 writer.write_dma(self, offset_val, count)?; 973 974 *offset += count as i64; 975 Ok(count) 976 } 977 } 978 979 /// An opaque DMA allocation without a kernel virtual mapping. 980 /// 981 /// Unlike [`Coherent`], a `CoherentHandle` does not provide CPU access to the allocated memory. 982 /// The allocation is always performed with `DMA_ATTR_NO_KERNEL_MAPPING`, meaning no kernel 983 /// virtual mapping is created for the buffer. The value returned by the C API as the CPU 984 /// address is an opaque handle used only to free the allocation. 985 /// 986 /// This is useful for buffers that are only ever accessed by hardware. 987 /// 988 /// # Invariants 989 /// 990 /// - `cpu_handle` holds the opaque handle returned by `dma_alloc_attrs` with 991 /// `DMA_ATTR_NO_KERNEL_MAPPING` set, and is only valid for passing back to `dma_free_attrs`. 992 /// - `dma_handle` is the corresponding bus address for device DMA. 993 /// - `size` is the allocation size in bytes as passed to `dma_alloc_attrs`. 994 /// - `dma_attrs` contains the attributes used for the allocation, always including 995 /// `DMA_ATTR_NO_KERNEL_MAPPING`. 996 pub struct CoherentHandle { 997 dev: ARef<device::Device>, 998 dma_handle: DmaAddress, 999 cpu_handle: NonNull<c_void>, 1000 size: usize, 1001 dma_attrs: Attrs, 1002 } 1003 1004 impl CoherentHandle { 1005 /// Allocates `size` bytes of coherent DMA memory without creating a kernel virtual mapping. 1006 /// 1007 /// Additional DMA attributes may be passed via `dma_attrs`; `DMA_ATTR_NO_KERNEL_MAPPING` is 1008 /// always set implicitly. 1009 /// 1010 /// Returns `EINVAL` if `size` is zero, `ENOMEM` if the allocation fails. 1011 pub fn alloc_with_attrs( 1012 dev: &device::Device<Bound>, 1013 size: usize, 1014 gfp_flags: kernel::alloc::Flags, 1015 dma_attrs: Attrs, 1016 ) -> Result<Self> { 1017 if size == 0 { 1018 return Err(EINVAL); 1019 } 1020 1021 let dma_attrs = dma_attrs | Attrs(bindings::DMA_ATTR_NO_KERNEL_MAPPING); 1022 let mut dma_handle = 0; 1023 // SAFETY: `dev.as_raw()` is valid by the type invariant on `device::Device`. 1024 let cpu_handle = unsafe { 1025 bindings::dma_alloc_attrs( 1026 dev.as_raw(), 1027 size, 1028 &mut dma_handle, 1029 gfp_flags.as_raw(), 1030 dma_attrs.as_raw(), 1031 ) 1032 }; 1033 1034 let cpu_handle = NonNull::new(cpu_handle).ok_or(ENOMEM)?; 1035 1036 // INVARIANT: `cpu_handle` is the opaque handle from a successful `dma_alloc_attrs` call 1037 // with `DMA_ATTR_NO_KERNEL_MAPPING`, `dma_handle` is the corresponding DMA address, 1038 // and we hold a refcounted reference to the device. 1039 Ok(Self { 1040 dev: dev.into(), 1041 dma_handle, 1042 cpu_handle, 1043 size, 1044 dma_attrs, 1045 }) 1046 } 1047 1048 /// Allocates `size` bytes of coherent DMA memory without creating a kernel virtual mapping. 1049 #[inline] 1050 pub fn alloc( 1051 dev: &device::Device<Bound>, 1052 size: usize, 1053 gfp_flags: kernel::alloc::Flags, 1054 ) -> Result<Self> { 1055 Self::alloc_with_attrs(dev, size, gfp_flags, Attrs(0)) 1056 } 1057 1058 /// Returns the DMA handle for this allocation. 1059 /// 1060 /// This address can be programmed into device hardware for DMA access. 1061 #[inline] 1062 pub fn dma_handle(&self) -> DmaAddress { 1063 self.dma_handle 1064 } 1065 1066 /// Returns the size in bytes of this allocation. 1067 #[inline] 1068 pub fn size(&self) -> usize { 1069 self.size 1070 } 1071 } 1072 1073 impl Drop for CoherentHandle { 1074 fn drop(&mut self) { 1075 // SAFETY: All values are valid by the type invariants on `CoherentHandle`. 1076 // `cpu_handle` is the opaque handle from `dma_alloc_attrs` and is passed back unchanged. 1077 unsafe { 1078 bindings::dma_free_attrs( 1079 self.dev.as_raw(), 1080 self.size, 1081 self.cpu_handle.as_ptr(), 1082 self.dma_handle, 1083 self.dma_attrs.as_raw(), 1084 ) 1085 } 1086 } 1087 } 1088 1089 // SAFETY: `CoherentHandle` only holds a device reference, a DMA handle, an opaque CPU handle, 1090 // and a size. None of these are tied to a specific thread. 1091 unsafe impl Send for CoherentHandle {} 1092 1093 // SAFETY: `CoherentHandle` provides no CPU access to the underlying allocation. The only 1094 // operations on `&CoherentHandle` are reading the DMA handle and size, both of which are 1095 // plain `Copy` values. 1096 unsafe impl Sync for CoherentHandle {} 1097 1098 /// View type for `Coherent`. 1099 /// 1100 /// This is same as [`SysMem`] but with additional information that allows handing out a DMA handle. 1101 pub struct CoherentView<'a, T: ?Sized> { 1102 cpu_addr: SysMem<'a, T>, 1103 dma_handle: DmaAddress, 1104 } 1105 1106 impl<T: ?Sized> Copy for CoherentView<'_, T> {} 1107 impl<T: ?Sized> Clone for CoherentView<'_, T> { 1108 #[inline] 1109 fn clone(&self) -> Self { 1110 *self 1111 } 1112 } 1113 1114 impl<'a, T: ?Sized> CoherentView<'a, T> { 1115 /// Erase the DMA handle information and obtain a [`SysMem`] view of the same memory region. 1116 #[inline] 1117 pub fn as_sys_mem(self) -> SysMem<'a, T> { 1118 self.cpu_addr 1119 } 1120 1121 /// Returns a DMA handle which may be given to the device as the DMA address base of the region. 1122 #[inline] 1123 pub fn dma_handle(self) -> DmaAddress { 1124 self.dma_handle 1125 } 1126 1127 /// Returns a reference to the data in the region. 1128 /// 1129 /// # Safety 1130 /// 1131 /// * Callers must ensure that the device does not read/write to/from memory while the returned 1132 /// reference is live. 1133 /// * Callers must ensure that this call does not race with a write (including call to `as_mut`) 1134 /// to the same region while the returned reference is live. 1135 #[inline] 1136 pub unsafe fn as_ref(self) -> &'a T { 1137 // SAFETY: pointer is aligned and valid per type invariant. Aliasing rule is satisfied per 1138 // safety requirement. 1139 unsafe { &*self.cpu_addr.as_ptr() } 1140 } 1141 1142 /// Returns a mutable reference to the data in the region. 1143 /// 1144 /// # Safety 1145 /// 1146 /// * Callers must ensure that the device does not read/write to/from memory while the returned 1147 /// reference is live. 1148 /// * Callers must ensure that this call does not race with a read (including call to `as_ref`) 1149 /// or write (including call to `as_mut`) to the same region while the returned reference is 1150 /// live. 1151 #[inline] 1152 pub unsafe fn as_mut(self) -> &'a mut T { 1153 // SAFETY: pointer is aligned and valid per type invariant. Aliasing rule is satisfied per 1154 // safety requirement. 1155 unsafe { &mut *self.cpu_addr.as_ptr() } 1156 } 1157 } 1158 1159 /// `IoBackend` implementation for `Coherent`. 1160 pub struct CoherentIoBackend; 1161 1162 impl IoBackend for CoherentIoBackend { 1163 type View<'a, T: ?Sized + KnownSize> = CoherentView<'a, T>; 1164 1165 #[inline] 1166 fn as_ptr<'a, T: ?Sized + KnownSize>(view: Self::View<'a, T>) -> *mut T { 1167 SysMemBackend::as_ptr(view.cpu_addr) 1168 } 1169 1170 #[inline] 1171 unsafe fn project_view<'a, T: ?Sized + KnownSize, U: ?Sized + KnownSize>( 1172 view: Self::View<'a, T>, 1173 ptr: *mut U, 1174 ) -> Self::View<'a, U> { 1175 let offset = ptr.addr() - view.cpu_addr.as_ptr().addr(); 1176 // CAST: The offset DMA address can never overflow. 1177 let dma_handle = view.dma_handle + offset as DmaAddress; 1178 CoherentView { 1179 dma_handle, 1180 // SAFETY: Per safety requirement. 1181 cpu_addr: unsafe { SysMemBackend::project_view(view.cpu_addr, ptr) }, 1182 } 1183 } 1184 } 1185 1186 impl<T> IoCapable<T> for CoherentIoBackend 1187 where 1188 SysMemBackend: IoCapable<T>, 1189 { 1190 #[inline] 1191 fn io_read<'a>(view: Self::View<'a, T>) -> T { 1192 SysMemBackend::io_read(view.cpu_addr) 1193 } 1194 1195 #[inline] 1196 fn io_write<'a>(view: Self::View<'a, T>, value: T) { 1197 SysMemBackend::io_write(view.cpu_addr, value) 1198 } 1199 } 1200 1201 impl IoCopyable for CoherentIoBackend { 1202 #[inline] 1203 unsafe fn copy_from_io(view: Self::View<'_, [u8]>, buffer: *mut u8) { 1204 // SAFETY: Per safety requirement. 1205 unsafe { SysMemBackend::copy_from_io(view.cpu_addr, buffer) } 1206 } 1207 1208 #[inline] 1209 unsafe fn copy_to_io(view: Self::View<'_, [u8]>, buffer: *const u8) { 1210 // SAFETY: Per safety requirement. 1211 unsafe { SysMemBackend::copy_to_io(view.cpu_addr, buffer) } 1212 } 1213 1214 #[inline] 1215 fn copy_read<T: zerocopy::FromBytes>(view: Self::View<'_, T>) -> T { 1216 SysMemBackend::copy_read(view.cpu_addr) 1217 } 1218 1219 #[inline] 1220 fn copy_write<T: zerocopy::IntoBytes>(view: Self::View<'_, T>, value: T) { 1221 SysMemBackend::copy_write(view.cpu_addr, value) 1222 } 1223 } 1224 1225 impl<'a, T: ?Sized + KnownSize> IoBase<'a> for CoherentView<'a, T> { 1226 type Backend = CoherentIoBackend; 1227 type Target = T; 1228 1229 #[inline] 1230 fn as_view(self) -> CoherentView<'a, Self::Target> { 1231 self 1232 } 1233 } 1234 1235 impl<'a, T: ?Sized + KnownSize> IoBase<'a> for &'a Coherent<T> { 1236 type Backend = CoherentIoBackend; 1237 type Target = T; 1238 1239 #[inline] 1240 fn as_view(self) -> CoherentView<'a, Self::Target> { 1241 CoherentView { 1242 // SAFETY: `cpu_addr` is valid and aligned kernel accessible memory. 1243 cpu_addr: unsafe { SysMem::new(self.cpu_addr.as_ptr()) }, 1244 dma_handle: self.dma_handle, 1245 } 1246 } 1247 } 1248