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