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, build_assert, 9 device::{Bound, Device}, 10 error::code::*, 11 error::Result, 12 transmute::{AsBytes, FromBytes}, 13 types::ARef, 14 }; 15 16 /// Possible attributes associated with a DMA mapping. 17 /// 18 /// They can be combined with the operators `|`, `&`, and `!`. 19 /// 20 /// Values can be used from the [`attrs`] module. 21 /// 22 /// # Examples 23 /// 24 /// ``` 25 /// # use kernel::device::{Bound, Device}; 26 /// use kernel::dma::{attrs::*, CoherentAllocation}; 27 /// 28 /// # fn test(dev: &Device<Bound>) -> Result { 29 /// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN; 30 /// let c: CoherentAllocation<u64> = 31 /// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, attribs)?; 32 /// # Ok::<(), Error>(()) } 33 /// ``` 34 #[derive(Clone, Copy, PartialEq)] 35 #[repr(transparent)] 36 pub struct Attrs(u32); 37 38 impl Attrs { 39 /// Get the raw representation of this attribute. as_raw(self) -> crate::ffi::c_ulong40 pub(crate) fn as_raw(self) -> crate::ffi::c_ulong { 41 self.0 as _ 42 } 43 44 /// Check whether `flags` is contained in `self`. contains(self, flags: Attrs) -> bool45 pub fn contains(self, flags: Attrs) -> bool { 46 (self & flags) == flags 47 } 48 } 49 50 impl core::ops::BitOr for Attrs { 51 type Output = Self; bitor(self, rhs: Self) -> Self::Output52 fn bitor(self, rhs: Self) -> Self::Output { 53 Self(self.0 | rhs.0) 54 } 55 } 56 57 impl core::ops::BitAnd for Attrs { 58 type Output = Self; bitand(self, rhs: Self) -> Self::Output59 fn bitand(self, rhs: Self) -> Self::Output { 60 Self(self.0 & rhs.0) 61 } 62 } 63 64 impl core::ops::Not for Attrs { 65 type Output = Self; not(self) -> Self::Output66 fn not(self) -> Self::Output { 67 Self(!self.0) 68 } 69 } 70 71 /// DMA mapping attributes. 72 pub mod attrs { 73 use super::Attrs; 74 75 /// Specifies that reads and writes to the mapping may be weakly ordered, that is that reads 76 /// and writes may pass each other. 77 pub const DMA_ATTR_WEAK_ORDERING: Attrs = Attrs(bindings::DMA_ATTR_WEAK_ORDERING); 78 79 /// Specifies that writes to the mapping may be buffered to improve performance. 80 pub const DMA_ATTR_WRITE_COMBINE: Attrs = Attrs(bindings::DMA_ATTR_WRITE_COMBINE); 81 82 /// Lets the platform to avoid creating a kernel virtual mapping for the allocated buffer. 83 pub const DMA_ATTR_NO_KERNEL_MAPPING: Attrs = Attrs(bindings::DMA_ATTR_NO_KERNEL_MAPPING); 84 85 /// Allows platform code to skip synchronization of the CPU cache for the given buffer assuming 86 /// that it has been already transferred to 'device' domain. 87 pub const DMA_ATTR_SKIP_CPU_SYNC: Attrs = Attrs(bindings::DMA_ATTR_SKIP_CPU_SYNC); 88 89 /// Forces contiguous allocation of the buffer in physical memory. 90 pub const DMA_ATTR_FORCE_CONTIGUOUS: Attrs = Attrs(bindings::DMA_ATTR_FORCE_CONTIGUOUS); 91 92 /// This is a hint to the DMA-mapping subsystem that it's probably not worth the time to try 93 /// to allocate memory to in a way that gives better TLB efficiency. 94 pub const DMA_ATTR_ALLOC_SINGLE_PAGES: Attrs = Attrs(bindings::DMA_ATTR_ALLOC_SINGLE_PAGES); 95 96 /// This tells the DMA-mapping subsystem to suppress allocation failure reports (similarly to 97 /// `__GFP_NOWARN`). 98 pub const DMA_ATTR_NO_WARN: Attrs = Attrs(bindings::DMA_ATTR_NO_WARN); 99 100 /// Used to indicate that the buffer is fully accessible at an elevated privilege level (and 101 /// ideally inaccessible or at least read-only at lesser-privileged levels). 102 pub const DMA_ATTR_PRIVILEGED: Attrs = Attrs(bindings::DMA_ATTR_PRIVILEGED); 103 } 104 105 /// An abstraction of the `dma_alloc_coherent` API. 106 /// 107 /// This is an abstraction around the `dma_alloc_coherent` API which is used to allocate and map 108 /// large consistent DMA regions. 109 /// 110 /// A [`CoherentAllocation`] instance contains a pointer to the allocated region (in the 111 /// processor's virtual address space) and the device address which can be given to the device 112 /// as the DMA address base of the region. The region is released once [`CoherentAllocation`] 113 /// is dropped. 114 /// 115 /// # Invariants 116 /// 117 /// For the lifetime of an instance of [`CoherentAllocation`], the `cpu_addr` is a valid pointer 118 /// to an allocated region of consistent memory and `dma_handle` is the DMA address base of 119 /// the region. 120 // TODO 121 // 122 // DMA allocations potentially carry device resources (e.g.IOMMU mappings), hence for soundness 123 // reasons DMA allocation would need to be embedded in a `Devres` container, in order to ensure 124 // that device resources can never survive device unbind. 125 // 126 // However, it is neither desirable nor necessary to protect the allocated memory of the DMA 127 // allocation from surviving device unbind; it would require RCU read side critical sections to 128 // access the memory, which may require subsequent unnecessary copies. 129 // 130 // Hence, find a way to revoke the device resources of a `CoherentAllocation`, but not the 131 // entire `CoherentAllocation` including the allocated memory itself. 132 pub struct CoherentAllocation<T: AsBytes + FromBytes> { 133 dev: ARef<Device>, 134 dma_handle: bindings::dma_addr_t, 135 count: usize, 136 cpu_addr: *mut T, 137 dma_attrs: Attrs, 138 } 139 140 impl<T: AsBytes + FromBytes> CoherentAllocation<T> { 141 /// Allocates a region of `size_of::<T> * count` of consistent memory. 142 /// 143 /// # Examples 144 /// 145 /// ``` 146 /// # use kernel::device::{Bound, Device}; 147 /// use kernel::dma::{attrs::*, CoherentAllocation}; 148 /// 149 /// # fn test(dev: &Device<Bound>) -> Result { 150 /// let c: CoherentAllocation<u64> = 151 /// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?; 152 /// # Ok::<(), Error>(()) } 153 /// ``` alloc_attrs( dev: &Device<Bound>, count: usize, gfp_flags: kernel::alloc::Flags, dma_attrs: Attrs, ) -> Result<CoherentAllocation<T>>154 pub fn alloc_attrs( 155 dev: &Device<Bound>, 156 count: usize, 157 gfp_flags: kernel::alloc::Flags, 158 dma_attrs: Attrs, 159 ) -> Result<CoherentAllocation<T>> { 160 build_assert!( 161 core::mem::size_of::<T>() > 0, 162 "It doesn't make sense for the allocated type to be a ZST" 163 ); 164 165 let size = count 166 .checked_mul(core::mem::size_of::<T>()) 167 .ok_or(EOVERFLOW)?; 168 let mut dma_handle = 0; 169 // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`. 170 let ret = unsafe { 171 bindings::dma_alloc_attrs( 172 dev.as_raw(), 173 size, 174 &mut dma_handle, 175 gfp_flags.as_raw(), 176 dma_attrs.as_raw(), 177 ) 178 }; 179 if ret.is_null() { 180 return Err(ENOMEM); 181 } 182 // INVARIANT: We just successfully allocated a coherent region which is accessible for 183 // `count` elements, hence the cpu address is valid. We also hold a refcounted reference 184 // to the device. 185 Ok(Self { 186 dev: dev.into(), 187 dma_handle, 188 count, 189 cpu_addr: ret as *mut T, 190 dma_attrs, 191 }) 192 } 193 194 /// Performs the same functionality as [`CoherentAllocation::alloc_attrs`], except the 195 /// `dma_attrs` is 0 by default. alloc_coherent( dev: &Device<Bound>, count: usize, gfp_flags: kernel::alloc::Flags, ) -> Result<CoherentAllocation<T>>196 pub fn alloc_coherent( 197 dev: &Device<Bound>, 198 count: usize, 199 gfp_flags: kernel::alloc::Flags, 200 ) -> Result<CoherentAllocation<T>> { 201 CoherentAllocation::alloc_attrs(dev, count, gfp_flags, Attrs(0)) 202 } 203 204 /// Returns the base address to the allocated region in the CPU's virtual address space. start_ptr(&self) -> *const T205 pub fn start_ptr(&self) -> *const T { 206 self.cpu_addr 207 } 208 209 /// Returns the base address to the allocated region in the CPU's virtual address space as 210 /// a mutable pointer. start_ptr_mut(&mut self) -> *mut T211 pub fn start_ptr_mut(&mut self) -> *mut T { 212 self.cpu_addr 213 } 214 215 /// Returns a DMA handle which may given to the device as the DMA address base of 216 /// the region. dma_handle(&self) -> bindings::dma_addr_t217 pub fn dma_handle(&self) -> bindings::dma_addr_t { 218 self.dma_handle 219 } 220 221 /// Returns a pointer to an element from the region with bounds checking. `offset` is in 222 /// units of `T`, not the number of bytes. 223 /// 224 /// Public but hidden since it should only be used from [`dma_read`] and [`dma_write`] macros. 225 #[doc(hidden)] item_from_index(&self, offset: usize) -> Result<*mut T>226 pub fn item_from_index(&self, offset: usize) -> Result<*mut T> { 227 if offset >= self.count { 228 return Err(EINVAL); 229 } 230 // SAFETY: 231 // - The pointer is valid due to type invariant on `CoherentAllocation` 232 // and we've just checked that the range and index is within bounds. 233 // - `offset` can't overflow since it is smaller than `self.count` and we've checked 234 // that `self.count` won't overflow early in the constructor. 235 Ok(unsafe { self.cpu_addr.add(offset) }) 236 } 237 238 /// Reads the value of `field` and ensures that its type is [`FromBytes`]. 239 /// 240 /// # Safety 241 /// 242 /// This must be called from the [`dma_read`] macro which ensures that the `field` pointer is 243 /// validated beforehand. 244 /// 245 /// Public but hidden since it should only be used from [`dma_read`] macro. 246 #[doc(hidden)] field_read<F: FromBytes>(&self, field: *const F) -> F247 pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F { 248 // SAFETY: 249 // - By the safety requirements field is valid. 250 // - Using read_volatile() here is not sound as per the usual rules, the usage here is 251 // a special exception with the following notes in place. When dealing with a potential 252 // race from a hardware or code outside kernel (e.g. user-space program), we need that 253 // read on a valid memory is not UB. Currently read_volatile() is used for this, and the 254 // rationale behind is that it should generate the same code as READ_ONCE() which the 255 // kernel already relies on to avoid UB on data races. Note that the usage of 256 // read_volatile() is limited to this particular case, it cannot be used to prevent 257 // the UB caused by racing between two kernel functions nor do they provide atomicity. 258 unsafe { field.read_volatile() } 259 } 260 261 /// Writes a value to `field` and ensures that its type is [`AsBytes`]. 262 /// 263 /// # Safety 264 /// 265 /// This must be called from the [`dma_write`] macro which ensures that the `field` pointer is 266 /// validated beforehand. 267 /// 268 /// Public but hidden since it should only be used from [`dma_write`] macro. 269 #[doc(hidden)] field_write<F: AsBytes>(&self, field: *mut F, val: F)270 pub unsafe fn field_write<F: AsBytes>(&self, field: *mut F, val: F) { 271 // SAFETY: 272 // - By the safety requirements field is valid. 273 // - Using write_volatile() here is not sound as per the usual rules, the usage here is 274 // a special exception with the following notes in place. When dealing with a potential 275 // race from a hardware or code outside kernel (e.g. user-space program), we need that 276 // write on a valid memory is not UB. Currently write_volatile() is used for this, and the 277 // rationale behind is that it should generate the same code as WRITE_ONCE() which the 278 // kernel already relies on to avoid UB on data races. Note that the usage of 279 // write_volatile() is limited to this particular case, it cannot be used to prevent 280 // the UB caused by racing between two kernel functions nor do they provide atomicity. 281 unsafe { field.write_volatile(val) } 282 } 283 } 284 285 /// Note that the device configured to do DMA must be halted before this object is dropped. 286 impl<T: AsBytes + FromBytes> Drop for CoherentAllocation<T> { drop(&mut self)287 fn drop(&mut self) { 288 let size = self.count * core::mem::size_of::<T>(); 289 // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`. 290 // The cpu address, and the dma handle are valid due to the type invariants on 291 // `CoherentAllocation`. 292 unsafe { 293 bindings::dma_free_attrs( 294 self.dev.as_raw(), 295 size, 296 self.cpu_addr as _, 297 self.dma_handle, 298 self.dma_attrs.as_raw(), 299 ) 300 } 301 } 302 } 303 304 // SAFETY: It is safe to send a `CoherentAllocation` to another thread if `T` 305 // can be sent to another thread. 306 unsafe impl<T: AsBytes + FromBytes + Send> Send for CoherentAllocation<T> {} 307 308 /// Reads a field of an item from an allocated region of structs. 309 /// 310 /// # Examples 311 /// 312 /// ``` 313 /// use kernel::device::Device; 314 /// use kernel::dma::{attrs::*, CoherentAllocation}; 315 /// 316 /// struct MyStruct { field: u32, } 317 /// 318 /// // SAFETY: All bit patterns are acceptable values for `MyStruct`. 319 /// unsafe impl kernel::transmute::FromBytes for MyStruct{}; 320 /// // SAFETY: Instances of `MyStruct` have no uninitialized portions. 321 /// unsafe impl kernel::transmute::AsBytes for MyStruct{}; 322 /// 323 /// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result { 324 /// let whole = kernel::dma_read!(alloc[2]); 325 /// let field = kernel::dma_read!(alloc[1].field); 326 /// # Ok::<(), Error>(()) } 327 /// ``` 328 #[macro_export] 329 macro_rules! dma_read { 330 ($dma:expr, $idx: expr, $($field:tt)*) => {{ 331 let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?; 332 // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be 333 // dereferenced. The compiler also further validates the expression on whether `field` 334 // is a member of `item` when expanded by the macro. 335 unsafe { 336 let ptr_field = ::core::ptr::addr_of!((*item) $($field)*); 337 $crate::dma::CoherentAllocation::field_read(&$dma, ptr_field) 338 } 339 }}; 340 ($dma:ident [ $idx:expr ] $($field:tt)* ) => { 341 $crate::dma_read!($dma, $idx, $($field)*); 342 }; 343 ($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => { 344 $crate::dma_read!($($dma).*, $idx, $($field)*); 345 }; 346 } 347 348 /// Writes to a field of an item from an allocated region of structs. 349 /// 350 /// # Examples 351 /// 352 /// ``` 353 /// use kernel::device::Device; 354 /// use kernel::dma::{attrs::*, CoherentAllocation}; 355 /// 356 /// struct MyStruct { member: u32, } 357 /// 358 /// // SAFETY: All bit patterns are acceptable values for `MyStruct`. 359 /// unsafe impl kernel::transmute::FromBytes for MyStruct{}; 360 /// // SAFETY: Instances of `MyStruct` have no uninitialized portions. 361 /// unsafe impl kernel::transmute::AsBytes for MyStruct{}; 362 /// 363 /// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result { 364 /// kernel::dma_write!(alloc[2].member = 0xf); 365 /// kernel::dma_write!(alloc[1] = MyStruct { member: 0xf }); 366 /// # Ok::<(), Error>(()) } 367 /// ``` 368 #[macro_export] 369 macro_rules! dma_write { 370 ($dma:ident [ $idx:expr ] $($field:tt)*) => {{ 371 $crate::dma_write!($dma, $idx, $($field)*); 372 }}; 373 ($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => {{ 374 $crate::dma_write!($($dma).*, $idx, $($field)*); 375 }}; 376 ($dma:expr, $idx: expr, = $val:expr) => { 377 let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?; 378 // SAFETY: `item_from_index` ensures that `item` is always a valid item. 379 unsafe { $crate::dma::CoherentAllocation::field_write(&$dma, item, $val) } 380 }; 381 ($dma:expr, $idx: expr, $(.$field:ident)* = $val:expr) => { 382 let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?; 383 // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be 384 // dereferenced. The compiler also further validates the expression on whether `field` 385 // is a member of `item` when expanded by the macro. 386 unsafe { 387 let ptr_field = ::core::ptr::addr_of_mut!((*item) $(.$field)*); 388 $crate::dma::CoherentAllocation::field_write(&$dma, ptr_field, $val) 389 } 390 }; 391 } 392