* [PATCH v15 00/11] rust: add dma coherent allocator abstraction
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 01/11] rust: error: Add EOVERFLOW Abdiel Janulgue
` (13 more replies)
0 siblings, 14 replies; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
This series adds the rust bindings for the dma coherent allocator which
is needed for nova-core[0].
For v15, document safety comments on the exception of usage on
read_volatile and write_volatile as suggested by Boqun Feng.
This is tested on a Nvidia GA104 GPU device using PoC code which parses
and loads the GSP firmware via DMA.
Changes since v14:
- Add safety comments on the exception of usage on read_volatile
and write_volatile (Boqun Feng, Benno Lossin, Andreas Hindborg).
- Link to v14: https://lore.kernel.org/lkml/20250311174930.2348813-1-abdiel.janulgue@gmail.com/
Changes since v13:
- Remove Devres wrapper, document correct solution for proper resource
deallocation as TODO, add patches from Danilo to properly add DMA
addressing capabilities for the device which requires a new trait
that defines the DMA specific methods of devices. (Danilo)
Changes since v12:
- Move out the contentious functions: as_slice, as_slice_mut, and write
for later discussion as a separate patch. Make write unsafe as well.
Remove skip_drop, use volatile r/w for field_read and field_write
(Alice Ryhl, et al.).
- Documentation improvements, use markdown for intra-doc links
(Miguel Ojeda).
- Move dma addressing capabilities to a separate patch within device.rs
(Andreas Hindborg).
- Add a simple driver to excercise the basics of the api (Danilo).
Changes since v11:
- Ensure robust handling for potential pointer arithmetic overflows
in bounds checking (Petr Tesařík).
- Add dma mask helpers (Daniel Almeida).
- Clarification in the safety aspects of the as_slice/as_slice_mut API,
Use ManuallyDrop trait as a replacement for into_parts(),
Add dma_read!/dma_write! helper macros (Alice Ryhl).
Changes since v10:
- rename read() to as_slice() (Boqun Feng)
- Do a bitwise copy of ARef<Device> in into_parts() when returning the
device reference (Alice Ryhl).
Changes since v9:
- Use ARef<Device> in the constructor arguments, docs clarification avoid
manually dropping the refcount for the device in into_parts(), use
add() instead of wrapping_add() in the pointer arithmetic for performance
(Alice Ryhl).
Changes since v8:
- Add MAINTAINERS entry
- Fix build issues due to switch from core::ffi to crate:ffi in bindgen.
- Ensure the wrapped attribute is non-pub in struct Attrs, declare it
#[repr(transparent)] as well (Daniel Sedlak)
Changes since v7:
- Remove cpu_buf() and cpu_buf_mut() as exporting a r/w interface via
a slice is undefined behaviour due to slice's requirement that the
underlying pointer should not be modified (Alice Ryhl, Robin Murphy).
- Reintroduce r/w helpers instead which includes proper safety
invariants (Daniel Almeida).
Changes since v6:
- Include the dma_attrs in the constructor, use alloc::Flags as inpiration
Changes since v5:
- Remove unnecessary lifetime annotation when returning the CPU buffer.
Changes since v4:
- Documentation and example fixes, use Markdown formatting (Miguel Ojeda).
- Discard read()/write() helpers to remove bound on Copy and fix overhead
(Daniel Almeida).
- Improve error-handling in the constructor block (Andreas Hindborg).
Changes since v3:
- Reject ZST types by checking the type size in the constructor in
addition to requiring FromBytes/AsBytes traits for the type (Alice Ryhl).
Changes since v2:
- Fixed missing header for generating the bindings.
Changes since v1:
- Fix missing info in commit log where EOVERFLOW is used.
- Restrict the dma coherent allocator to numeric types for now for valid
behaviour (Daniel Almeida).
- Build slice dynamically.
[0] https://lore.kernel.org/lkml/20250131220432.17717-1-dakr@kernel.org/
Abdiel Janulgue (5):
rust: error: Add EOVERFLOW
rust: add dma coherent allocator abstraction.
samples: rust: add Rust dma test sample driver
MAINTAINERS: add entry for Rust dma mapping helpers device driver API
rust: dma: add as_slice/write functions for CoherentAllocation
Danilo Krummrich (6):
rust: dma: implement `dma::Device` trait
rust: dma: add dma addressing capabilities
rust: pci: implement the `dma::Device` trait
rust: platform: implement the `dma::Device` trait
rust: dma: use `dma::Device` in `CoherentAllocation`
rust: samples: dma: set DMA mask
MAINTAINERS | 13 +
rust/bindings/bindings_helper.h | 1 +
rust/helpers/dma.c | 8 +
rust/helpers/helpers.c | 1 +
rust/kernel/dma.rs | 521 ++++++++++++++++++++++++++++++++
rust/kernel/error.rs | 1 +
rust/kernel/lib.rs | 1 +
rust/kernel/pci.rs | 2 +
rust/kernel/platform.rs | 2 +
samples/rust/Kconfig | 11 +
samples/rust/Makefile | 1 +
samples/rust/rust_dma.rs | 104 +++++++
12 files changed, 666 insertions(+)
create mode 100644 rust/helpers/dma.c
create mode 100644 rust/kernel/dma.rs
create mode 100644 samples/rust/rust_dma.rs
base-commit: cf25bc61f8aecad9b0c45fe32697e35ea4b13378
--
2.43.0
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v15 01/11] rust: error: Add EOVERFLOW
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 02/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (12 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
Trivial addition for missing EOVERFLOW error. This is used by a
subsequent patch that might require returning EOVERFLOW as a result
of `checked_mul`.
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
---
rust/kernel/error.rs | 1 +
1 file changed, 1 insertion(+)
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index 376f6a6ae5e3..30014d507ed3 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -64,6 +64,7 @@ macro_rules! declare_err {
declare_err!(EPIPE, "Broken pipe.");
declare_err!(EDOM, "Math argument out of domain of func.");
declare_err!(ERANGE, "Math result not representable.");
+ declare_err!(EOVERFLOW, "Value too large for defined data type.");
declare_err!(ERESTARTSYS, "Restart the system call.");
declare_err!(ERESTARTNOINTR, "System call was interrupted by a signal and will be restarted.");
declare_err!(ERESTARTNOHAND, "Restart if no handler.");
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v15 02/11] rust: add dma coherent allocator abstraction.
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 01/11] rust: error: Add EOVERFLOW Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-18 13:07 ` Andreas Hindborg
2025-03-17 18:52 ` [PATCH v15 03/11] samples: rust: add Rust dma test sample driver Abdiel Janulgue
` (11 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
Add a simple dma coherent allocator rust abstraction. Based on
Andreas Hindborg's dma abstractions from the rnvme driver, which
was also based on earlier work by Wedson Almeida Filho.
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
---
rust/bindings/bindings_helper.h | 1 +
rust/kernel/dma.rs | 387 ++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 1 +
3 files changed, 389 insertions(+)
create mode 100644 rust/kernel/dma.rs
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index ae39fc18a8bf..ccb988340df6 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -12,6 +12,7 @@
#include <linux/blkdev.h>
#include <linux/cred.h>
#include <linux/device/faux.h>
+#include <linux/dma-mapping.h>
#include <linux/errname.h>
#include <linux/ethtool.h>
#include <linux/file.h>
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
new file mode 100644
index 000000000000..9d00f9c49f47
--- /dev/null
+++ b/rust/kernel/dma.rs
@@ -0,0 +1,387 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Direct memory access (DMA).
+//!
+//! C header: [`include/linux/dma-mapping.h`](srctree/include/linux/dma-mapping.h)
+
+use crate::{
+ bindings, build_assert,
+ device::Device,
+ error::code::*,
+ error::Result,
+ transmute::{AsBytes, FromBytes},
+ types::ARef,
+};
+
+/// Possible attributes associated with a DMA mapping.
+///
+/// They can be combined with the operators `|`, `&`, and `!`.
+///
+/// Values can be used from the [`attrs`] module.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::device::Device;
+/// use kernel::dma::{attrs::*, CoherentAllocation};
+///
+/// # fn test(dev: &Device) -> Result {
+/// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN;
+/// let c: CoherentAllocation<u64> =
+/// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, attribs)?;
+/// # Ok::<(), Error>(()) }
+/// ```
+#[derive(Clone, Copy, PartialEq)]
+#[repr(transparent)]
+pub struct Attrs(u32);
+
+impl Attrs {
+ /// Get the raw representation of this attribute.
+ pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
+ self.0 as _
+ }
+
+ /// Check whether `flags` is contained in `self`.
+ pub fn contains(self, flags: Attrs) -> bool {
+ (self & flags) == flags
+ }
+}
+
+impl core::ops::BitOr for Attrs {
+ type Output = Self;
+ fn bitor(self, rhs: Self) -> Self::Output {
+ Self(self.0 | rhs.0)
+ }
+}
+
+impl core::ops::BitAnd for Attrs {
+ type Output = Self;
+ fn bitand(self, rhs: Self) -> Self::Output {
+ Self(self.0 & rhs.0)
+ }
+}
+
+impl core::ops::Not for Attrs {
+ type Output = Self;
+ fn not(self) -> Self::Output {
+ Self(!self.0)
+ }
+}
+
+/// DMA mapping attributes.
+pub mod attrs {
+ use super::Attrs;
+
+ /// Specifies that reads and writes to the mapping may be weakly ordered, that is that reads
+ /// and writes may pass each other.
+ pub const DMA_ATTR_WEAK_ORDERING: Attrs = Attrs(bindings::DMA_ATTR_WEAK_ORDERING);
+
+ /// Specifies that writes to the mapping may be buffered to improve performance.
+ pub const DMA_ATTR_WRITE_COMBINE: Attrs = Attrs(bindings::DMA_ATTR_WRITE_COMBINE);
+
+ /// Lets the platform to avoid creating a kernel virtual mapping for the allocated buffer.
+ pub const DMA_ATTR_NO_KERNEL_MAPPING: Attrs = Attrs(bindings::DMA_ATTR_NO_KERNEL_MAPPING);
+
+ /// Allows platform code to skip synchronization of the CPU cache for the given buffer assuming
+ /// that it has been already transferred to 'device' domain.
+ pub const DMA_ATTR_SKIP_CPU_SYNC: Attrs = Attrs(bindings::DMA_ATTR_SKIP_CPU_SYNC);
+
+ /// Forces contiguous allocation of the buffer in physical memory.
+ pub const DMA_ATTR_FORCE_CONTIGUOUS: Attrs = Attrs(bindings::DMA_ATTR_FORCE_CONTIGUOUS);
+
+ /// This is a hint to the DMA-mapping subsystem that it's probably not worth the time to try
+ /// to allocate memory to in a way that gives better TLB efficiency.
+ pub const DMA_ATTR_ALLOC_SINGLE_PAGES: Attrs = Attrs(bindings::DMA_ATTR_ALLOC_SINGLE_PAGES);
+
+ /// This tells the DMA-mapping subsystem to suppress allocation failure reports (similarly to
+ /// __GFP_NOWARN).
+ pub const DMA_ATTR_NO_WARN: Attrs = Attrs(bindings::DMA_ATTR_NO_WARN);
+
+ /// Used to indicate that the buffer is fully accessible at an elevated privilege level (and
+ /// ideally inaccessible or at least read-only at lesser-privileged levels).
+ pub const DMA_ATTR_PRIVILEGED: Attrs = Attrs(bindings::DMA_ATTR_PRIVILEGED);
+}
+
+/// An abstraction of the `dma_alloc_coherent` API.
+///
+/// This is an abstraction around the `dma_alloc_coherent` API which is used to allocate and map
+/// large consistent DMA regions.
+///
+/// A [`CoherentAllocation`] instance contains a pointer to the allocated region (in the
+/// processor's virtual address space) and the device address which can be given to the device
+/// as the DMA address base of the region. The region is released once [`CoherentAllocation`]
+/// is dropped.
+///
+/// # Invariants
+///
+/// For the lifetime of an instance of [`CoherentAllocation`], the `cpu_addr` is a valid pointer
+/// to an allocated region of consistent memory and `dma_handle` is the DMA address base of
+/// the region.
+// TODO
+//
+// DMA allocations potentially carry device resources (e.g.IOMMU mappings), hence for soundness
+// reasons DMA allocation would need to be embedded in a `Devres` container, in order to ensure
+// that device resources can never survive device unbind.
+//
+// However, it is neither desirable nor necessary to protect the allocated memory of the DMA
+// allocation from surviving device unbind; it would require RCU read side critical sections to
+// access the memory, which may require subsequent unnecessary copies.
+//
+// Hence, find a way to revoke the device resources of a `CoherentAllocation`, but not the
+// entire `CoherentAllocation` including the allocated memory itself.
+pub struct CoherentAllocation<T: AsBytes + FromBytes> {
+ dev: ARef<Device>,
+ dma_handle: bindings::dma_addr_t,
+ count: usize,
+ cpu_addr: *mut T,
+ dma_attrs: Attrs,
+}
+
+impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
+ /// Allocates a region of `size_of::<T> * count` of consistent memory.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use kernel::device::Device;
+ /// use kernel::dma::{attrs::*, CoherentAllocation};
+ ///
+ /// # fn test(dev: &Device) -> Result {
+ /// let c: CoherentAllocation<u64> =
+ /// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
+ /// # Ok::<(), Error>(()) }
+ /// ```
+ pub fn alloc_attrs(
+ dev: &Device,
+ count: usize,
+ gfp_flags: kernel::alloc::Flags,
+ dma_attrs: Attrs,
+ ) -> Result<CoherentAllocation<T>> {
+ build_assert!(
+ core::mem::size_of::<T>() > 0,
+ "It doesn't make sense for the allocated type to be a ZST"
+ );
+
+ let size = count
+ .checked_mul(core::mem::size_of::<T>())
+ .ok_or(EOVERFLOW)?;
+ let mut dma_handle = 0;
+ // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
+ let ret = unsafe {
+ bindings::dma_alloc_attrs(
+ dev.as_raw(),
+ size,
+ &mut dma_handle,
+ gfp_flags.as_raw(),
+ dma_attrs.as_raw(),
+ )
+ };
+ if ret.is_null() {
+ return Err(ENOMEM);
+ }
+ // INVARIANT: We just successfully allocated a coherent region which is accessible for
+ // `count` elements, hence the cpu address is valid. We also hold a refcounted reference
+ // to the device.
+ Ok(Self {
+ dev: dev.into(),
+ dma_handle,
+ count,
+ cpu_addr: ret as *mut T,
+ dma_attrs,
+ })
+ }
+
+ /// Performs the same functionality as [`CoherentAllocation::alloc_attrs`], except the
+ /// `dma_attrs` is 0 by default.
+ pub fn alloc_coherent(
+ dev: &Device,
+ count: usize,
+ gfp_flags: kernel::alloc::Flags,
+ ) -> Result<CoherentAllocation<T>> {
+ CoherentAllocation::alloc_attrs(dev, count, gfp_flags, Attrs(0))
+ }
+
+ /// Returns the base address to the allocated region in the CPU's virtual address space.
+ pub fn start_ptr(&self) -> *const T {
+ self.cpu_addr
+ }
+
+ /// Returns the base address to the allocated region in the CPU's virtual address space as
+ /// a mutable pointer.
+ pub fn start_ptr_mut(&mut self) -> *mut T {
+ self.cpu_addr
+ }
+
+ /// Returns a DMA handle which may given to the device as the DMA address base of
+ /// the region.
+ pub fn dma_handle(&self) -> bindings::dma_addr_t {
+ self.dma_handle
+ }
+
+ /// Returns a pointer to an element from the region with bounds checking. `offset` is in
+ /// units of `T`, not the number of bytes.
+ ///
+ /// Public but hidden since it should only be used from [`dma_read`] and [`dma_write`] macros.
+ #[doc(hidden)]
+ pub fn item_from_index(&self, offset: usize) -> Result<*mut T> {
+ if offset >= self.count {
+ return Err(EINVAL);
+ }
+ // SAFETY:
+ // - The pointer is valid due to type invariant on `CoherentAllocation`
+ // and we've just checked that the range and index is within bounds.
+ // - `offset` can't overflow since it is smaller than `self.count` and we've checked
+ // that `self.count` won't overflow early in the constructor.
+ Ok(unsafe { self.cpu_addr.add(offset) })
+ }
+
+ /// Reads the value of `field` and ensures that its type is [`FromBytes`].
+ ///
+ /// # Safety
+ ///
+ /// This must be called from the [`dma_read`] macro which ensures that the `field` pointer is
+ /// validated beforehand.
+ ///
+ /// Public but hidden since it should only be used from [`dma_read`] macro.
+ #[doc(hidden)]
+ pub unsafe fn field_read<F: FromBytes>(&self, field: *const F) -> F {
+ // SAFETY:
+ // - By the safety requirements field is valid.
+ // - Using read_volatile() here is not sound as per the usual rules, the usage here is
+ // a special exception with the following notes in place. When dealing with a potential
+ // race from a hardware or code outside kernel (e.g. user-space program), we need that
+ // read on a valid memory is not UB. Currently read_volatile() is used for this, and the
+ // rationale behind is that it should generate the same code as READ_ONCE() which the
+ // kernel already relies on to avoid UB on data races. Note that the usage of
+ // read_volatile() is limited to this particular case, it cannot be used to prevent
+ // the UB caused by racing between two kernel functions nor do they provide atomicity.
+ unsafe { field.read_volatile() }
+ }
+
+ /// Writes a value to `field` and ensures that its type is [`AsBytes`].
+ ///
+ /// # Safety
+ ///
+ /// This must be called from the [`dma_write`] macro which ensures that the `field` pointer is
+ /// validated beforehand.
+ ///
+ /// Public but hidden since it should only be used from [`dma_write`] macro.
+ #[doc(hidden)]
+ pub unsafe fn field_write<F: AsBytes>(&self, field: *mut F, val: F) {
+ // SAFETY:
+ // - By the safety requirements field is valid.
+ // - Using write_volatile() here is not sound as per the usual rules, the usage here is
+ // a special exception with the following notes in place. When dealing with a potential
+ // race from a hardware or code outside kernel (e.g. user-space program), we need that
+ // write on a valid memory is not UB. Currently write_volatile() is used for this, and the
+ // rationale behind is that it should generate the same code as WRITE_ONCE() which the
+ // kernel already relies on to avoid UB on data races. Note that the usage of
+ // write_volatile() is limited to this particular case, it cannot be used to prevent
+ // the UB caused by racing between two kernel functions nor do they provide atomicity.
+ unsafe { field.write_volatile(val) }
+ }
+}
+
+/// Note that the device configured to do DMA must be halted before this object is dropped.
+impl<T: AsBytes + FromBytes> Drop for CoherentAllocation<T> {
+ fn drop(&mut self) {
+ let size = self.count * core::mem::size_of::<T>();
+ // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
+ // The cpu address, and the dma handle are valid due to the type invariants on
+ // `CoherentAllocation`.
+ unsafe {
+ bindings::dma_free_attrs(
+ self.dev.as_raw(),
+ size,
+ self.cpu_addr as _,
+ self.dma_handle,
+ self.dma_attrs.as_raw(),
+ )
+ }
+ }
+}
+
+/// Reads a field of an item from an allocated region of structs.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::device::Device;
+/// use kernel::dma::{attrs::*, CoherentAllocation};
+///
+/// struct MyStruct { field: u32, }
+///
+/// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
+/// unsafe impl kernel::transmute::FromBytes for MyStruct{};
+/// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
+/// unsafe impl kernel::transmute::AsBytes for MyStruct{};
+///
+/// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result {
+/// let whole = kernel::dma_read!(alloc[2]);
+/// let field = kernel::dma_read!(alloc[1].field);
+/// # Ok::<(), Error>(()) }
+/// ```
+#[macro_export]
+macro_rules! dma_read {
+ ($dma:expr, $idx: expr, $($field:tt)*) => {{
+ let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
+ // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be
+ // dereferenced. The compiler also further validates the expression on whether `field`
+ // is a member of `item` when expanded by the macro.
+ unsafe {
+ let ptr_field = ::core::ptr::addr_of!((*item) $($field)*);
+ $crate::dma::CoherentAllocation::field_read(&$dma, ptr_field)
+ }
+ }};
+ ($dma:ident [ $idx:expr ] $($field:tt)* ) => {
+ $crate::dma_read!($dma, $idx, $($field)*);
+ };
+ ($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => {
+ $crate::dma_read!($($dma).*, $idx, $($field)*);
+ };
+}
+
+/// Writes to a field of an item from an allocated region of structs.
+///
+/// # Examples
+///
+/// ```
+/// use kernel::device::Device;
+/// use kernel::dma::{attrs::*, CoherentAllocation};
+///
+/// struct MyStruct { member: u32, }
+///
+/// // SAFETY: All bit patterns are acceptable values for `MyStruct`.
+/// unsafe impl kernel::transmute::FromBytes for MyStruct{};
+/// // SAFETY: Instances of `MyStruct` have no uninitialized portions.
+/// unsafe impl kernel::transmute::AsBytes for MyStruct{};
+///
+/// # fn test(alloc: &kernel::dma::CoherentAllocation<MyStruct>) -> Result {
+/// kernel::dma_write!(alloc[2].member = 0xf);
+/// kernel::dma_write!(alloc[1] = MyStruct { member: 0xf });
+/// # Ok::<(), Error>(()) }
+/// ```
+#[macro_export]
+macro_rules! dma_write {
+ ($dma:ident [ $idx:expr ] $($field:tt)*) => {{
+ $crate::dma_write!($dma, $idx, $($field)*);
+ }};
+ ($($dma:ident).* [ $idx:expr ] $($field:tt)* ) => {{
+ $crate::dma_write!($($dma).*, $idx, $($field)*);
+ }};
+ ($dma:expr, $idx: expr, = $val:expr) => {
+ let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
+ // SAFETY: `item_from_index` ensures that `item` is always a valid item.
+ unsafe { $crate::dma::CoherentAllocation::field_write(&$dma, item, $val) }
+ };
+ ($dma:expr, $idx: expr, $(.$field:ident)* = $val:expr) => {
+ let item = $crate::dma::CoherentAllocation::item_from_index(&$dma, $idx)?;
+ // SAFETY: `item_from_index` ensures that `item` is always a valid pointer and can be
+ // dereferenced. The compiler also further validates the expression on whether `field`
+ // is a member of `item` when expanded by the macro.
+ unsafe {
+ let ptr_field = ::core::ptr::addr_of_mut!((*item) $(.$field)*);
+ $crate::dma::CoherentAllocation::field_write(&$dma, ptr_field, $val)
+ }
+ };
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index c92497c7c655..001374a96d66 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -44,6 +44,7 @@
pub mod device;
pub mod device_id;
pub mod devres;
+pub mod dma;
pub mod driver;
pub mod error;
pub mod faux;
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v15 03/11] samples: rust: add Rust dma test sample driver
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 01/11] rust: error: Add EOVERFLOW Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 02/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-18 13:06 ` Danilo Krummrich
2025-03-17 18:52 ` [PATCH v15 04/11] MAINTAINERS: add entry for Rust dma mapping helpers device driver API Abdiel Janulgue
` (10 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
Add a simple driver to excercise the basics of the Rust DMA
coherent allocator bindings.
Suggested-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
---
samples/rust/Kconfig | 11 +++++
samples/rust/Makefile | 1 +
samples/rust/rust_dma.rs | 97 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 109 insertions(+)
create mode 100644 samples/rust/rust_dma.rs
diff --git a/samples/rust/Kconfig b/samples/rust/Kconfig
index 3b6eae84b297..e2d14aa6beec 100644
--- a/samples/rust/Kconfig
+++ b/samples/rust/Kconfig
@@ -78,4 +78,15 @@ config SAMPLE_RUST_HOSTPROGS
If unsure, say N.
+config SAMPLE_RUST_DRIVER_DMA
+ tristate "DMA Test Driver"
+ depends on PCI
+ help
+ This option builds the Rust dma test driver sample.
+
+ To compile this as a module, choose M here:
+ the module will be called dma.
+
+ If unsure, say N.
+
endif # SAMPLES_RUST
diff --git a/samples/rust/Makefile b/samples/rust/Makefile
index 0dbc6d90f1ef..1a9aff6e8d6a 100644
--- a/samples/rust/Makefile
+++ b/samples/rust/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_SAMPLE_RUST_PRINT) += rust_print.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_PCI) += rust_driver_pci.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_PLATFORM) += rust_driver_platform.o
obj-$(CONFIG_SAMPLE_RUST_DRIVER_FAUX) += rust_driver_faux.o
+obj-$(CONFIG_SAMPLE_RUST_DRIVER_DMA) += rust_dma.o
rust_print-y := rust_print_main.o rust_print_events.o
diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs
new file mode 100644
index 000000000000..1740140faba6
--- /dev/null
+++ b/samples/rust/rust_dma.rs
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Rust DMA api test (based on QEMU's `pci-testdev`).
+//!
+//! To make this driver probe, QEMU must be run with `-device pci-testdev`.
+
+use kernel::{bindings, dma::CoherentAllocation, pci, prelude::*};
+
+struct DmaSampleDriver {
+ pdev: pci::Device,
+ ca: CoherentAllocation<MyStruct>,
+}
+
+const TEST_VALUES: [(u32, u32); 5] = [
+ (0xa, 0xb),
+ (0xc, 0xd),
+ (0xe, 0xf),
+ (0xab, 0xba),
+ (0xcd, 0xef),
+];
+
+struct MyStruct {
+ h: u32,
+ b: u32,
+}
+
+impl MyStruct {
+ fn new(h: u32, b: u32) -> Self {
+ Self { h, b }
+ }
+}
+// SAFETY: All bit patterns are acceptable values for `MyStruct`.
+unsafe impl kernel::transmute::AsBytes for MyStruct {}
+// SAFETY: Instances of `MyStruct` have no uninitialized portions.
+unsafe impl kernel::transmute::FromBytes for MyStruct {}
+
+kernel::pci_device_table!(
+ PCI_TABLE,
+ MODULE_PCI_TABLE,
+ <DmaSampleDriver as pci::Driver>::IdInfo,
+ [(
+ pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, 0x5),
+ ()
+ )]
+);
+
+impl pci::Driver for DmaSampleDriver {
+ type IdInfo = ();
+ const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
+
+ fn probe(pdev: &mut pci::Device, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
+ dev_info!(pdev.as_ref(), "Probe DMA test driver.\n");
+
+ let ca: CoherentAllocation<MyStruct> =
+ CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?;
+
+ || -> Result {
+ for (i, value) in TEST_VALUES.into_iter().enumerate() {
+ kernel::dma_write!(ca[i] = MyStruct::new(value.0, value.1));
+ }
+
+ Ok(())
+ }()?;
+
+ let drvdata = KBox::new(
+ Self {
+ pdev: pdev.clone(),
+ ca,
+ },
+ GFP_KERNEL,
+ )?;
+
+ Ok(drvdata.into())
+ }
+}
+
+impl Drop for DmaSampleDriver {
+ fn drop(&mut self) {
+ dev_info!(self.pdev.as_ref(), "Unload DMA test driver.\n");
+
+ let _ = || -> Result {
+ for (i, value) in TEST_VALUES.into_iter().enumerate() {
+ assert_eq!(kernel::dma_read!(self.ca[i].h), value.0);
+ assert_eq!(kernel::dma_read!(self.ca[i].b), value.1);
+ }
+ Ok(())
+ }();
+ }
+}
+
+kernel::module_pci_driver! {
+ type: DmaSampleDriver,
+ name: "rust_dma",
+ author: "Abdiel Janulgue",
+ description: "Rust DMA test",
+ license: "GPL v2",
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v15 04/11] MAINTAINERS: add entry for Rust dma mapping helpers device driver API
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (2 preceding siblings ...)
2025-03-17 18:52 ` [PATCH v15 03/11] samples: rust: add Rust dma test sample driver Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 05/11] rust: dma: implement `dma::Device` trait Abdiel Janulgue
` (9 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
Add an entry for the Rust dma mapping helpers abstractions.
Nacked-by: Christoph Hellwig <hch@lst.de>
Acked-by: Danilo Krummrich <dakr@kernel.org>
Acked-by: Andreas Hindborg <a.hindborg@kernel.org>
Acked-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
---
MAINTAINERS | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 72b88f1638a2..4c0786336826 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6902,6 +6902,19 @@ F: include/linux/dma-mapping.h
F: include/linux/swiotlb.h
F: kernel/dma/
+DMA MAPPING HELPERS DEVICE DRIVER API [RUST]
+M: Abdiel Janulgue <abdiel.janulgue@gmail.com>
+M: Danilo Krummrich <dakr@kernel.org>
+R: Daniel Almeida <daniel.almeida@collabora.com>
+R: Robin Murphy <robin.murphy@arm.com>
+R: Andreas Hindborg <a.hindborg@kernel.org>
+L: rust-for-linux@vger.kernel.org
+S: Supported
+W: https://rust-for-linux.com
+T: git https://github.com/Rust-for-Linux/linux.git alloc-next
+F: rust/kernel/dma.rs
+F: samples/rust/rust_dma.rs
+
DMA-BUF HEAPS FRAMEWORK
M: Sumit Semwal <sumit.semwal@linaro.org>
R: Benjamin Gaignard <benjamin.gaignard@collabora.com>
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v15 05/11] rust: dma: implement `dma::Device` trait
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (3 preceding siblings ...)
2025-03-17 18:52 ` [PATCH v15 04/11] MAINTAINERS: add entry for Rust dma mapping helpers device driver API Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 06/11] rust: dma: add dma addressing capabilities Abdiel Janulgue
` (8 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
From: Danilo Krummrich <dakr@kernel.org>
Add a trait that defines the DMA specific methods of devices.
The `dma::Device` trait should be implemented by (bus) device
representations, where the underlying bus potentially supports DMA, such
as `pci::Device` or `platform::Device`.
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
---
rust/kernel/dma.rs | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index 9d00f9c49f47..834d00c1347e 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -6,13 +6,20 @@
use crate::{
bindings, build_assert,
- device::Device,
+ device,
error::code::*,
error::Result,
transmute::{AsBytes, FromBytes},
types::ARef,
};
+/// Trait to be implemented by bus specific devices.
+///
+/// The [`Device`] trait should be implemented by bus specific device representations, where the
+/// underlying bus has potential support for DMA, such as [`crate::pci::Device`] or
+/// [crate::platform::Device].
+pub trait Device: AsRef<device::Device> {}
+
/// Possible attributes associated with a DMA mapping.
///
/// They can be combined with the operators `|`, `&`, and `!`.
@@ -130,7 +137,7 @@ pub mod attrs {
// Hence, find a way to revoke the device resources of a `CoherentAllocation`, but not the
// entire `CoherentAllocation` including the allocated memory itself.
pub struct CoherentAllocation<T: AsBytes + FromBytes> {
- dev: ARef<Device>,
+ dev: ARef<device::Device>,
dma_handle: bindings::dma_addr_t,
count: usize,
cpu_addr: *mut T,
@@ -152,7 +159,7 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
/// # Ok::<(), Error>(()) }
/// ```
pub fn alloc_attrs(
- dev: &Device,
+ dev: &device::Device,
count: usize,
gfp_flags: kernel::alloc::Flags,
dma_attrs: Attrs,
@@ -194,7 +201,7 @@ pub fn alloc_attrs(
/// Performs the same functionality as [`CoherentAllocation::alloc_attrs`], except the
/// `dma_attrs` is 0 by default.
pub fn alloc_coherent(
- dev: &Device,
+ dev: &device::Device,
count: usize,
gfp_flags: kernel::alloc::Flags,
) -> Result<CoherentAllocation<T>> {
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v15 06/11] rust: dma: add dma addressing capabilities
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (4 preceding siblings ...)
2025-03-17 18:52 ` [PATCH v15 05/11] rust: dma: implement `dma::Device` trait Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 07/11] rust: pci: implement the `dma::Device` trait Abdiel Janulgue
` (7 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
From: Danilo Krummrich <dakr@kernel.org>
Implement `dma_set_mask()` and `dma_set_mask_and_coherent()` in the
`dma::Device` trait.
Those methods are used to inform the kernel about the device's DMA
addressing capabilities.
Co-developed-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
---
rust/helpers/dma.c | 8 ++++++++
rust/helpers/helpers.c | 1 +
rust/kernel/dma.rs | 46 +++++++++++++++++++++++++++++++++++++++---
3 files changed, 52 insertions(+), 3 deletions(-)
create mode 100644 rust/helpers/dma.c
diff --git a/rust/helpers/dma.c b/rust/helpers/dma.c
new file mode 100644
index 000000000000..8eb482386f93
--- /dev/null
+++ b/rust/helpers/dma.c
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/dma-mapping.h>
+
+int rust_helper_dma_set_mask_and_coherent(struct device *dev, u64 mask)
+{
+ return dma_set_mask_and_coherent(dev, mask);
+}
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 0640b7e115be..8f3808c8b7fe 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -13,6 +13,7 @@
#include "build_bug.c"
#include "cred.c"
#include "device.c"
+#include "dma.c"
#include "err.c"
#include "fs.c"
#include "io.c"
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index 834d00c1347e..fc66f1764c31 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -5,10 +5,10 @@
//! C header: [`include/linux/dma-mapping.h`](srctree/include/linux/dma-mapping.h)
use crate::{
- bindings, build_assert,
- device,
+ bindings, build_assert, device,
error::code::*,
error::Result,
+ prelude::*,
transmute::{AsBytes, FromBytes},
types::ARef,
};
@@ -18,7 +18,35 @@
/// The [`Device`] trait should be implemented by bus specific device representations, where the
/// underlying bus has potential support for DMA, such as [`crate::pci::Device`] or
/// [crate::platform::Device].
-pub trait Device: AsRef<device::Device> {}
+pub trait Device: AsRef<device::Device> {
+ /// Inform the kernel about the device's DMA addressing capabilities.
+ ///
+ /// Set both the DMA mask and the coherent DMA mask to the same value.
+ ///
+ /// Note that we don't check the return value from the C `dma_set_coherent_mask` as the DMA API
+ /// guarantees that the coherent DMA mask can be set to the same or smaller than the streaming
+ /// DMA mask.
+ fn dma_set_mask_and_coherent(&mut self, mask: u64) -> Result {
+ // SAFETY: By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
+ let ret = unsafe { bindings::dma_set_mask_and_coherent(self.as_ref().as_raw(), mask) };
+ if ret != 0 {
+ Err(Error::from_errno(ret))
+ } else {
+ Ok(())
+ }
+ }
+
+ /// Same as [`Self::dma_set_mask_and_coherent`], but set the mask only for streaming mappings.
+ fn dma_set_mask(&mut self, mask: u64) -> Result {
+ // SAFETY: By the type invariant of `device::Device`, `self.as_ref().as_raw()` is valid.
+ let ret = unsafe { bindings::dma_set_mask(self.as_ref().as_raw(), mask) };
+ if ret != 0 {
+ Err(Error::from_errno(ret))
+ } else {
+ Ok(())
+ }
+ }
+}
/// Possible attributes associated with a DMA mapping.
///
@@ -392,3 +420,15 @@ macro_rules! dma_write {
}
};
}
+
+/// Helper function to set the bit mask for DMA addressing.
+pub const fn dma_bit_mask(n: usize) -> u64 {
+ if n > 64 {
+ return 0;
+ }
+ if n == 64 {
+ !0
+ } else {
+ (1 << (n)) - 1
+ }
+}
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v15 07/11] rust: pci: implement the `dma::Device` trait
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (5 preceding siblings ...)
2025-03-17 18:52 ` [PATCH v15 06/11] rust: dma: add dma addressing capabilities Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 08/11] rust: platform: " Abdiel Janulgue
` (6 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
From: Danilo Krummrich <dakr@kernel.org>
The PCI bus is potentially capable of performing DMA, hence implement
the `dma:Device` trait for `pci::Device`.
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
---
rust/kernel/pci.rs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index f7b2743828ae..5839aa5d4098 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -432,3 +432,5 @@ fn as_ref(&self) -> &device::Device {
&self.0
}
}
+
+impl crate::dma::Device for Device {}
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v15 08/11] rust: platform: implement the `dma::Device` trait
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (6 preceding siblings ...)
2025-03-17 18:52 ` [PATCH v15 07/11] rust: pci: implement the `dma::Device` trait Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 09/11] rust: dma: use `dma::Device` in `CoherentAllocation` Abdiel Janulgue
` (5 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
From: Danilo Krummrich <dakr@kernel.org>
The platform bus is potentially capable of performing DMA, hence implement
the `dma:Device` trait for `platform::Device`.
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
---
rust/kernel/platform.rs | 2 ++
1 file changed, 2 insertions(+)
diff --git a/rust/kernel/platform.rs b/rust/kernel/platform.rs
index 1297f5292ba9..a7bf3525313e 100644
--- a/rust/kernel/platform.rs
+++ b/rust/kernel/platform.rs
@@ -198,3 +198,5 @@ fn as_ref(&self) -> &device::Device {
&self.0
}
}
+
+impl crate::dma::Device for Device {}
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v15 09/11] rust: dma: use `dma::Device` in `CoherentAllocation`
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (7 preceding siblings ...)
2025-03-17 18:52 ` [PATCH v15 08/11] rust: platform: " Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-06-03 12:18 ` Andreas Hindborg
2025-03-17 18:52 ` [PATCH v15 10/11] rust: samples: dma: set DMA mask Abdiel Janulgue
` (4 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
From: Danilo Krummrich <dakr@kernel.org>
Require a `&dyn dma::Device` in `CoherentAllocation`, such that DMA
memory can only be allocated with devices on potentially DMA capable
busses.
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
---
rust/kernel/dma.rs | 16 ++++++++--------
samples/rust/rust_dma.rs | 2 +-
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index fc66f1764c31..6d7aff6b360a 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -57,10 +57,9 @@ fn dma_set_mask(&mut self, mask: u64) -> Result {
/// # Examples
///
/// ```
-/// use kernel::device::Device;
-/// use kernel::dma::{attrs::*, CoherentAllocation};
+/// use kernel::dma::{attrs::*, Device, CoherentAllocation};
///
-/// # fn test(dev: &Device) -> Result {
+/// # fn test(dev: &dyn Device) -> Result {
/// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN;
/// let c: CoherentAllocation<u64> =
/// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, attribs)?;
@@ -178,16 +177,15 @@ impl<T: AsBytes + FromBytes> CoherentAllocation<T> {
/// # Examples
///
/// ```
- /// use kernel::device::Device;
- /// use kernel::dma::{attrs::*, CoherentAllocation};
+ /// use kernel::dma::{attrs::*, Device, CoherentAllocation};
///
- /// # fn test(dev: &Device) -> Result {
+ /// # fn test(dev: &dyn Device) -> Result {
/// let c: CoherentAllocation<u64> =
/// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, DMA_ATTR_NO_WARN)?;
/// # Ok::<(), Error>(()) }
/// ```
pub fn alloc_attrs(
- dev: &device::Device,
+ dev: &dyn Device,
count: usize,
gfp_flags: kernel::alloc::Flags,
dma_attrs: Attrs,
@@ -197,6 +195,8 @@ pub fn alloc_attrs(
"It doesn't make sense for the allocated type to be a ZST"
);
+ let dev = dev.as_ref();
+
let size = count
.checked_mul(core::mem::size_of::<T>())
.ok_or(EOVERFLOW)?;
@@ -229,7 +229,7 @@ pub fn alloc_attrs(
/// Performs the same functionality as [`CoherentAllocation::alloc_attrs`], except the
/// `dma_attrs` is 0 by default.
pub fn alloc_coherent(
- dev: &device::Device,
+ dev: &dyn Device,
count: usize,
gfp_flags: kernel::alloc::Flags,
) -> Result<CoherentAllocation<T>> {
diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs
index 1740140faba6..4c7ebf66647a 100644
--- a/samples/rust/rust_dma.rs
+++ b/samples/rust/rust_dma.rs
@@ -52,7 +52,7 @@ fn probe(pdev: &mut pci::Device, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>
dev_info!(pdev.as_ref(), "Probe DMA test driver.\n");
let ca: CoherentAllocation<MyStruct> =
- CoherentAllocation::alloc_coherent(pdev.as_ref(), TEST_VALUES.len(), GFP_KERNEL)?;
+ CoherentAllocation::alloc_coherent(pdev, TEST_VALUES.len(), GFP_KERNEL)?;
|| -> Result {
for (i, value) in TEST_VALUES.into_iter().enumerate() {
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v15 10/11] rust: samples: dma: set DMA mask
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (8 preceding siblings ...)
2025-03-17 18:52 ` [PATCH v15 09/11] rust: dma: use `dma::Device` in `CoherentAllocation` Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 11/11] rust: dma: add as_slice/write functions for CoherentAllocation Abdiel Janulgue
` (3 subsequent siblings)
13 siblings, 0 replies; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
From: Danilo Krummrich <dakr@kernel.org>
Set a DMA mask for the `pci::Device` in the Rust DMA sample driver.
Signed-off-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
---
samples/rust/rust_dma.rs | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs
index 4c7ebf66647a..39b6050aa3b6 100644
--- a/samples/rust/rust_dma.rs
+++ b/samples/rust/rust_dma.rs
@@ -4,7 +4,12 @@
//!
//! To make this driver probe, QEMU must be run with `-device pci-testdev`.
-use kernel::{bindings, dma::CoherentAllocation, pci, prelude::*};
+use kernel::{
+ bindings,
+ dma::{CoherentAllocation, Device},
+ pci,
+ prelude::*,
+};
struct DmaSampleDriver {
pdev: pci::Device,
@@ -51,6 +56,8 @@ impl pci::Driver for DmaSampleDriver {
fn probe(pdev: &mut pci::Device, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
dev_info!(pdev.as_ref(), "Probe DMA test driver.\n");
+ pdev.dma_set_mask_and_coherent(kernel::dma::dma_bit_mask(64))?;
+
let ca: CoherentAllocation<MyStruct> =
CoherentAllocation::alloc_coherent(pdev, TEST_VALUES.len(), GFP_KERNEL)?;
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [PATCH v15 11/11] rust: dma: add as_slice/write functions for CoherentAllocation
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (9 preceding siblings ...)
2025-03-17 18:52 ` [PATCH v15 10/11] rust: samples: dma: set DMA mask Abdiel Janulgue
@ 2025-03-17 18:52 ` Abdiel Janulgue
2025-03-18 14:09 ` Andreas Hindborg
2025-03-18 11:11 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Danilo Krummrich
` (2 subsequent siblings)
13 siblings, 1 reply; 23+ messages in thread
From: Abdiel Janulgue @ 2025-03-17 18:52 UTC (permalink / raw)
To: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl
Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS,
Abdiel Janulgue
Add unsafe accessors for the region for reading or writing large
blocks of data.
Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
---
rust/kernel/dma.rs | 87 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index 6d7aff6b360a..027ef75a461a 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -253,6 +253,93 @@ pub fn dma_handle(&self) -> bindings::dma_addr_t {
self.dma_handle
}
+ /// Returns the data from the region starting from `offset` as a slice.
+ /// `offset` and `count` are in units of `T`, not the number of bytes.
+ ///
+ /// Due to the safety requirements of slice, the caller should consider that the region could
+ /// be modified by the device at anytime. For ringbuffer type of r/w access or use-cases where
+ /// the pointer to the live data is needed, `start_ptr()` or `start_ptr_mut()` could be
+ /// used instead.
+ ///
+ /// # Safety
+ ///
+ /// * Callers must ensure that no hardware operations that involve the buffer are currently
+ /// taking place while the returned slice is live.
+ /// * Callers must ensure that this call does not race with a write to the same region while
+ /// while the returned slice is live.
+ pub unsafe fn as_slice(&self, offset: usize, count: usize) -> Result<&[T]> {
+ let end = offset.checked_add(count).ok_or(EOVERFLOW)?;
+ if end >= self.count {
+ return Err(EINVAL);
+ }
+ // SAFETY:
+ // - The pointer is valid due to type invariant on `CoherentAllocation`,
+ // we've just checked that the range and index is within bounds. The immutability of the
+ // of data is also guaranteed by the safety requirements of the function.
+ // - `offset` can't overflow since it is smaller than `self.count` and we've checked
+ // that `self.count` won't overflow early in the constructor.
+ Ok(unsafe { core::slice::from_raw_parts(self.cpu_addr.add(offset), count) })
+ }
+
+ /// Performs the same functionality as [`CoherentAllocation::as_slice`], except that a mutable
+ /// slice is returned.
+ ///
+ /// # Safety
+ ///
+ /// * Callers must ensure that no hardware operations that involve the buffer are currently
+ /// taking place while the returned slice is live.
+ /// * Callers must ensure that this call does not race with a read or write to the same region
+ /// while the returned slice is live.
+ pub unsafe fn as_slice_mut(&self, offset: usize, count: usize) -> Result<&mut [T]> {
+ let end = offset.checked_add(count).ok_or(EOVERFLOW)?;
+ if end >= self.count {
+ return Err(EINVAL);
+ }
+ // SAFETY:
+ // - The pointer is valid due to type invariant on `CoherentAllocation`,
+ // we've just checked that the range and index is within bounds. The immutability of the
+ // of data is also guaranteed by the safety requirements of the function.
+ // - `offset` can't overflow since it is smaller than `self.count` and we've checked
+ // that `self.count` won't overflow early in the constructor.
+ Ok(unsafe { core::slice::from_raw_parts_mut(self.cpu_addr.add(offset), count) })
+ }
+
+ /// Writes data to the region starting from `offset`. `offset` is in units of `T`, not the
+ /// number of bytes.
+ ///
+ /// # Safety
+ ///
+ /// * Callers must ensure that no hardware operations that involve the buffer overlaps with
+ /// this write.
+ /// * Callers must ensure that this call does not race with a read or write to the same region
+ /// that overlaps with this write.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # fn test(alloc: &mut kernel::dma::CoherentAllocation<u8>) -> Result {
+ /// let somedata: [u8; 4] = [0xf; 4];
+ /// let buf: &[u8] = &somedata;
+ /// // SAFETY: No hw operation on the device and no other r/w access to the region at this point.
+ /// unsafe { alloc.write(buf, 0)?; }
+ /// # Ok::<(), Error>(()) }
+ /// ```
+ pub unsafe fn write(&self, src: &[T], offset: usize) -> Result {
+ let end = offset.checked_add(src.len()).ok_or(EOVERFLOW)?;
+ if end >= self.count {
+ return Err(EINVAL);
+ }
+ // SAFETY:
+ // - The pointer is valid due to type invariant on `CoherentAllocation`
+ // and we've just checked that the range and index is within bounds.
+ // - `offset` can't overflow since it is smaller than `self.count` and we've checked
+ // that `self.count` won't overflow early in the constructor.
+ unsafe {
+ core::ptr::copy_nonoverlapping(src.as_ptr(), self.cpu_addr.add(offset), src.len())
+ };
+ Ok(())
+ }
+
/// Returns a pointer to an element from the region with bounds checking. `offset` is in
/// units of `T`, not the number of bytes.
///
--
2.43.0
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v15 00/11] rust: add dma coherent allocator abstraction
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (10 preceding siblings ...)
2025-03-17 18:52 ` [PATCH v15 11/11] rust: dma: add as_slice/write functions for CoherentAllocation Abdiel Janulgue
@ 2025-03-18 11:11 ` Danilo Krummrich
2025-03-18 14:11 ` Andreas Hindborg
2025-03-20 23:22 ` Miguel Ojeda
13 siblings, 0 replies; 23+ messages in thread
From: Danilo Krummrich @ 2025-03-18 11:11 UTC (permalink / raw)
To: Abdiel Janulgue
Cc: rust-for-linux, daniel.almeida, robin.murphy, aliceryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS
On Mon, Mar 17, 2025 at 08:52:07PM +0200, Abdiel Janulgue wrote:
> Abdiel Janulgue (5):
> rust: error: Add EOVERFLOW
> rust: add dma coherent allocator abstraction.
> samples: rust: add Rust dma test sample driver
> MAINTAINERS: add entry for Rust dma mapping helpers device driver API
For those four,
Acked-by: Danilo Krummrich <dakr@kernel.org>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v15 03/11] samples: rust: add Rust dma test sample driver
2025-03-17 18:52 ` [PATCH v15 03/11] samples: rust: add Rust dma test sample driver Abdiel Janulgue
@ 2025-03-18 13:06 ` Danilo Krummrich
0 siblings, 0 replies; 23+ messages in thread
From: Danilo Krummrich @ 2025-03-18 13:06 UTC (permalink / raw)
To: Miguel Ojeda
Cc: rust-for-linux, daniel.almeida, robin.murphy, aliceryhl,
Abdiel Janulgue, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS
Hi Miguel,
On Mon, Mar 17, 2025 at 08:52:10PM +0200, Abdiel Janulgue wrote:
> Add a simple driver to excercise the basics of the Rust DMA
> coherent allocator bindings.
>
> Suggested-by: Danilo Krummrich <dakr@kernel.org>
> Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
> ---
> samples/rust/Kconfig | 11 +++++
> samples/rust/Makefile | 1 +
> samples/rust/rust_dma.rs | 97 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 109 insertions(+)
> create mode 100644 samples/rust/rust_dma.rs
This patch has a conflict with the driver-core tree, which you should also hit
in linux-next.
The below diff should fix it.
- Danilo
diff --git a/samples/rust/rust_dma.rs b/samples/rust/rust_dma.rs
index 1740140faba6..44e0e6aa5658 100644
--- a/samples/rust/rust_dma.rs
+++ b/samples/rust/rust_dma.rs
@@ -4,10 +4,10 @@
//!
//! To make this driver probe, QEMU must be run with `-device pci-testdev`.
-use kernel::{bindings, dma::CoherentAllocation, pci, prelude::*};
+use kernel::{bindings, device::Core, dma::CoherentAllocation, pci, prelude::*, types::ARef};
struct DmaSampleDriver {
- pdev: pci::Device,
+ pdev: ARef<pci::Device>,
ca: CoherentAllocation<MyStruct>,
}
@@ -48,7 +48,7 @@ impl pci::Driver for DmaSampleDriver {
type IdInfo = ();
const ID_TABLE: pci::IdTable<Self::IdInfo> = &PCI_TABLE;
- fn probe(pdev: &mut pci::Device, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
+ fn probe(pdev: &pci::Device<Core>, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>> {
dev_info!(pdev.as_ref(), "Probe DMA test driver.\n");
let ca: CoherentAllocation<MyStruct> =
@@ -64,7 +64,7 @@ fn probe(pdev: &mut pci::Device, _info: &Self::IdInfo) -> Result<Pin<KBox<Self>>
let drvdata = KBox::new(
Self {
- pdev: pdev.clone(),
+ pdev: pdev.into(),
ca,
},
GFP_KERNEL,
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v15 02/11] rust: add dma coherent allocator abstraction.
2025-03-17 18:52 ` [PATCH v15 02/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
@ 2025-03-18 13:07 ` Andreas Hindborg
2025-03-18 15:37 ` Alice Ryhl
` (2 more replies)
0 siblings, 3 replies; 23+ messages in thread
From: Andreas Hindborg @ 2025-03-18 13:07 UTC (permalink / raw)
To: Abdiel Janulgue
Cc: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Trevor Gross, Valentin Obst,
linux-kernel, Christoph Hellwig, Marek Szyprowski, airlied, iommu
"Abdiel Janulgue" <abdiel.janulgue@gmail.com> writes:
[...]
> +/// Possible attributes associated with a DMA mapping.
> +///
> +/// They can be combined with the operators `|`, `&`, and `!`.
> +///
> +/// Values can be used from the [`attrs`] module.
> +///
> +/// # Examples
> +///
> +/// ```
> +/// use kernel::device::Device;
> +/// use kernel::dma::{attrs::*, CoherentAllocation};
> +///
> +/// # fn test(dev: &Device) -> Result {
> +/// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN;
> +/// let c: CoherentAllocation<u64> =
> +/// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, attribs)?;
> +/// # Ok::<(), Error>(()) }
> +/// ```
> +#[derive(Clone, Copy, PartialEq)]
> +#[repr(transparent)]
> +pub struct Attrs(u32);
> +
> +impl Attrs {
> + /// Get the raw representation of this attribute.
> + pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
> + self.0 as _
> + }
OT: I wonder why we do not have `usize: From<u32>`? It seems like this
should be fine, even on 32 bit systems?
> +
> + /// Check whether `flags` is contained in `self`.
> + pub fn contains(self, flags: Attrs) -> bool {
> + (self & flags) == flags
> + }
> +}
> +
> +impl core::ops::BitOr for Attrs {
> + type Output = Self;
> + fn bitor(self, rhs: Self) -> Self::Output {
> + Self(self.0 | rhs.0)
> + }
> +}
> +
> +impl core::ops::BitAnd for Attrs {
> + type Output = Self;
> + fn bitand(self, rhs: Self) -> Self::Output {
> + Self(self.0 & rhs.0)
> + }
> +}
> +
> +impl core::ops::Not for Attrs {
> + type Output = Self;
> + fn not(self) -> Self::Output {
> + Self(!self.0)
> + }
> +}
> +
> +/// DMA mapping attributes.
> +pub mod attrs {
> + use super::Attrs;
> +
> + /// Specifies that reads and writes to the mapping may be weakly ordered, that is that reads
> + /// and writes may pass each other.
> + pub const DMA_ATTR_WEAK_ORDERING: Attrs = Attrs(bindings::DMA_ATTR_WEAK_ORDERING);
> +
> + /// Specifies that writes to the mapping may be buffered to improve performance.
> + pub const DMA_ATTR_WRITE_COMBINE: Attrs = Attrs(bindings::DMA_ATTR_WRITE_COMBINE);
> +
> + /// Lets the platform to avoid creating a kernel virtual mapping for the allocated buffer.
> + pub const DMA_ATTR_NO_KERNEL_MAPPING: Attrs = Attrs(bindings::DMA_ATTR_NO_KERNEL_MAPPING);
> +
> + /// Allows platform code to skip synchronization of the CPU cache for the given buffer assuming
> + /// that it has been already transferred to 'device' domain.
> + pub const DMA_ATTR_SKIP_CPU_SYNC: Attrs = Attrs(bindings::DMA_ATTR_SKIP_CPU_SYNC);
> +
> + /// Forces contiguous allocation of the buffer in physical memory.
> + pub const DMA_ATTR_FORCE_CONTIGUOUS: Attrs = Attrs(bindings::DMA_ATTR_FORCE_CONTIGUOUS);
> +
> + /// This is a hint to the DMA-mapping subsystem that it's probably not worth the time to try
> + /// to allocate memory to in a way that gives better TLB efficiency.
The wording of in the other doc comments is different than this one and
the two next ones. Consider aligning them:
Hints the DMA-mapping subsystem that ...
> + pub const DMA_ATTR_ALLOC_SINGLE_PAGES: Attrs = Attrs(bindings::DMA_ATTR_ALLOC_SINGLE_PAGES);
> +
> + /// This tells the DMA-mapping subsystem to suppress allocation failure reports (similarly to
> + /// __GFP_NOWARN).
Tells the DMA-mapping subsystem ...
> + pub const DMA_ATTR_NO_WARN: Attrs = Attrs(bindings::DMA_ATTR_NO_WARN);
> +
> + /// Used to indicate that the buffer is fully accessible at an elevated privilege level (and
> + /// ideally inaccessible or at least read-only at lesser-privileged levels).
Indicates that the buffer ...
> + pub const DMA_ATTR_PRIVILEGED: Attrs = Attrs(bindings::DMA_ATTR_PRIVILEGED);
> +}
> +
> +/// An abstraction of the `dma_alloc_coherent` API.
> +///
> +/// This is an abstraction around the `dma_alloc_coherent` API which is used to allocate and map
> +/// large consistent DMA regions.
I think it would be nice to have a description of what a coherent DMA
region is here. From Documentation/core-api/dma-api.rst:
Consistent memory is memory for which a write by either the device or
the processor can immediately be read by the processor or device
without having to worry about caching effects. (You may however need
to make sure to flush the processor's write buffers before telling
devices to read that memory.)
I think consistent and coherent are used interchangeably in the kernel.
If so, can we settle on just one of the terms in the rust code?
> +///
> +/// A [`CoherentAllocation`] instance contains a pointer to the allocated region (in the
> +/// processor's virtual address space) and the device address which can be given to the device
> +/// as the DMA address base of the region. The region is released once [`CoherentAllocation`]
> +/// is dropped.
> +///
> +/// # Invariants
> +///
> +/// For the lifetime of an instance of [`CoherentAllocation`], the `cpu_addr` is a valid pointer
> +/// to an allocated region of consistent memory and `dma_handle` is the DMA address base of
> +/// the region.
> +// TODO
> +//
> +// DMA allocations potentially carry device resources (e.g.IOMMU mappings), hence for soundness
> +// reasons DMA allocation would need to be embedded in a `Devres` container, in order to ensure
> +// that device resources can never survive device unbind.
> +//
> +// However, it is neither desirable nor necessary to protect the allocated memory of the DMA
> +// allocation from surviving device unbind; it would require RCU read side critical sections to
> +// access the memory, which may require subsequent unnecessary copies.
> +//
> +// Hence, find a way to revoke the device resources of a `CoherentAllocation`, but not the
> +// entire `CoherentAllocation` including the allocated memory itself.
Looking forward to seeing this solution.
Best regards,
Andreas Hindborg
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v15 11/11] rust: dma: add as_slice/write functions for CoherentAllocation
2025-03-17 18:52 ` [PATCH v15 11/11] rust: dma: add as_slice/write functions for CoherentAllocation Abdiel Janulgue
@ 2025-03-18 14:09 ` Andreas Hindborg
0 siblings, 0 replies; 23+ messages in thread
From: Andreas Hindborg @ 2025-03-18 14:09 UTC (permalink / raw)
To: Abdiel Janulgue
Cc: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Trevor Gross, Valentin Obst,
linux-kernel, Christoph Hellwig, Marek Szyprowski, airlied, iommu
"Abdiel Janulgue" <abdiel.janulgue@gmail.com> writes:
> Add unsafe accessors for the region for reading or writing large
> blocks of data.
>
> Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Best regards,
Andreas Hindborg
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v15 00/11] rust: add dma coherent allocator abstraction
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (11 preceding siblings ...)
2025-03-18 11:11 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Danilo Krummrich
@ 2025-03-18 14:11 ` Andreas Hindborg
2025-03-20 23:22 ` Miguel Ojeda
13 siblings, 0 replies; 23+ messages in thread
From: Andreas Hindborg @ 2025-03-18 14:11 UTC (permalink / raw)
To: Abdiel Janulgue
Cc: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Trevor Gross, Valentin Obst,
linux-kernel, Christoph Hellwig, Marek Szyprowski, airlied, iommu
Hi Abdiel,
"Abdiel Janulgue" <abdiel.janulgue@gmail.com> writes:
> This series adds the rust bindings for the dma coherent allocator which
> is needed for nova-core[0].
>
> For v15, document safety comments on the exception of usage on
> read_volatile and write_volatile as suggested by Boqun Feng.
>
> This is tested on a Nvidia GA104 GPU device using PoC code which parses
> and loads the GSP firmware via DMA.
>
I messed up and replied to v14 of the series for patch 3, 6 (x2) and 9.
Comments still apply to v15.
Best regards,
Andreas Hindborg
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v15 02/11] rust: add dma coherent allocator abstraction.
2025-03-18 13:07 ` Andreas Hindborg
@ 2025-03-18 15:37 ` Alice Ryhl
2025-03-20 23:54 ` Miguel Ojeda
2025-03-22 22:58 ` Daniel Almeida
2 siblings, 0 replies; 23+ messages in thread
From: Alice Ryhl @ 2025-03-18 15:37 UTC (permalink / raw)
To: Andreas Hindborg
Cc: Abdiel Janulgue, rust-for-linux, daniel.almeida, dakr,
robin.murphy, Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Trevor Gross, Valentin Obst,
linux-kernel, Christoph Hellwig, Marek Szyprowski, airlied, iommu
On Tue, Mar 18, 2025 at 02:07:40PM +0100, Andreas Hindborg wrote:
> "Abdiel Janulgue" <abdiel.janulgue@gmail.com> writes:
>
> [...]
>
> > +/// Possible attributes associated with a DMA mapping.
> > +///
> > +/// They can be combined with the operators `|`, `&`, and `!`.
> > +///
> > +/// Values can be used from the [`attrs`] module.
> > +///
> > +/// # Examples
> > +///
> > +/// ```
> > +/// use kernel::device::Device;
> > +/// use kernel::dma::{attrs::*, CoherentAllocation};
> > +///
> > +/// # fn test(dev: &Device) -> Result {
> > +/// let attribs = DMA_ATTR_FORCE_CONTIGUOUS | DMA_ATTR_NO_WARN;
> > +/// let c: CoherentAllocation<u64> =
> > +/// CoherentAllocation::alloc_attrs(dev, 4, GFP_KERNEL, attribs)?;
> > +/// # Ok::<(), Error>(()) }
> > +/// ```
> > +#[derive(Clone, Copy, PartialEq)]
> > +#[repr(transparent)]
> > +pub struct Attrs(u32);
> > +
> > +impl Attrs {
> > + /// Get the raw representation of this attribute.
> > + pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
> > + self.0 as _
> > + }
>
> OT: I wonder why we do not have `usize: From<u32>`? It seems like this
> should be fine, even on 32 bit systems?
usize only implements From<unn> when it would work on all concievable
platforms, so it's missing for u32 due to 16-bit platforms.
Alice
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v15 00/11] rust: add dma coherent allocator abstraction
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
` (12 preceding siblings ...)
2025-03-18 14:11 ` Andreas Hindborg
@ 2025-03-20 23:22 ` Miguel Ojeda
13 siblings, 0 replies; 23+ messages in thread
From: Miguel Ojeda @ 2025-03-20 23:22 UTC (permalink / raw)
To: Abdiel Janulgue
Cc: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Valentin Obst, open list, Christoph Hellwig,
Marek Szyprowski, airlied, open list:DMA MAPPING HELPERS
On Mon, Mar 17, 2025 at 7:54 PM Abdiel Janulgue
<abdiel.janulgue@gmail.com> wrote:
>
> This series adds the rust bindings for the dma coherent allocator which
> is needed for nova-core[0].
>
> For v15, document safety comments on the exception of usage on
> read_volatile and write_volatile as suggested by Boqun Feng.
>
> This is tested on a Nvidia GA104 GPU device using PoC code which parses
> and loads the GSP firmware via DMA.
Applied (up to the `MAINTAINERS` patch, as discussed) to `rust-next`
-- thanks everyone!
[ Removed period. - Miguel ]
[ Renamed Kconfig symbol and moved it up. Migrated to the new
`authors` key in `module!`. Fixed module name in description
and typo in commit message. - Miguel ]
Cheers,
Miguel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v15 02/11] rust: add dma coherent allocator abstraction.
2025-03-18 13:07 ` Andreas Hindborg
2025-03-18 15:37 ` Alice Ryhl
@ 2025-03-20 23:54 ` Miguel Ojeda
2025-03-21 6:56 ` Andreas Hindborg
2025-03-22 22:58 ` Daniel Almeida
2 siblings, 1 reply; 23+ messages in thread
From: Miguel Ojeda @ 2025-03-20 23:54 UTC (permalink / raw)
To: Andreas Hindborg
Cc: Abdiel Janulgue, rust-for-linux, daniel.almeida, dakr,
robin.murphy, aliceryhl, Miguel Ojeda, Alex Gaynor, Boqun Feng,
Gary Guo, Björn Roy Baron, Benno Lossin, Trevor Gross,
Valentin Obst, linux-kernel, Christoph Hellwig, Marek Szyprowski,
airlied, iommu
On Tue, Mar 18, 2025 at 2:13 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>
> The wording of in the other doc comments is different than this one and
> the two next ones. Consider aligning them:
>
> Hints the DMA-mapping subsystem that ...
>
> Tells the DMA-mapping subsystem ...
>
> Indicates that the buffer ...
These come from the C side and are copy-pasted, so I suspect that was
the reason -- they may want to have them in sync, so I didn't touch
them.
> I think it would be nice to have a description of what a coherent DMA
> region is here. From Documentation/core-api/dma-api.rst:
>
> Consistent memory is memory for which a write by either the device or
> the processor can immediately be read by the processor or device
> without having to worry about caching effects. (You may however need
> to make sure to flush the processor's write buffers before telling
> devices to read that memory.)
>
> I think consistent and coherent are used interchangeably in the kernel.
> If so, can we settle on just one of the terms in the rust code?
Abdiel has the diff ready for this, so he may send the patch (or you),
but for the moment I decided to minimize changes -- up to the
maintainers/reviewers now :)
> > +// DMA allocations potentially carry device resources (e.g.IOMMU mappings), hence for soundness
Nit: I think this should have a space after e.g. or a comma -- I
didn't touch it, and it is a TODO anyway, but before I forget I
mention it here.
Thanks!
Cheers,
Miguel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v15 02/11] rust: add dma coherent allocator abstraction.
2025-03-20 23:54 ` Miguel Ojeda
@ 2025-03-21 6:56 ` Andreas Hindborg
0 siblings, 0 replies; 23+ messages in thread
From: Andreas Hindborg @ 2025-03-21 6:56 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Abdiel Janulgue, rust-for-linux, daniel.almeida, dakr,
robin.murphy, aliceryhl, Miguel Ojeda, Alex Gaynor, Boqun Feng,
Gary Guo, =?utf-8?Q?Bj=C3=B6rn?= Roy Baron, Benno Lossin,
Trevor Gross, Valentin Obst, linux-kernel, Christoph Hellwig,
Marek Szyprowski, airlied, iommu
"Miguel Ojeda" <miguel.ojeda.sandonis@gmail.com> writes:
> On Tue, Mar 18, 2025 at 2:13 PM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>>
>> The wording of in the other doc comments is different than this one and
>> the two next ones. Consider aligning them:
>>
>> Hints the DMA-mapping subsystem that ...
>>
>> Tells the DMA-mapping subsystem ...
>>
>> Indicates that the buffer ...
>
> These come from the C side and are copy-pasted, so I suspect that was
> the reason -- they may want to have them in sync, so I didn't touch
> them.
Since this particular doc discussion is about wording and not semantics,
I won't object too much. However, writing the docs for Rust is a very
good chance to get _better_ docs and in general I would encourage taking
advantage of that.
Best regards,
Andreas Hindborg
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v15 02/11] rust: add dma coherent allocator abstraction.
2025-03-18 13:07 ` Andreas Hindborg
2025-03-18 15:37 ` Alice Ryhl
2025-03-20 23:54 ` Miguel Ojeda
@ 2025-03-22 22:58 ` Daniel Almeida
2 siblings, 0 replies; 23+ messages in thread
From: Daniel Almeida @ 2025-03-22 22:58 UTC (permalink / raw)
To: Andreas Hindborg
Cc: Abdiel Janulgue, rust-for-linux, dakr, robin.murphy, aliceryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Trevor Gross, Valentin Obst,
linux-kernel, Christoph Hellwig, Marek Szyprowski, airlied, iommu
Hi Andreas,
>
> I think consistent and coherent are used interchangeably in the kernel.
> If so, can we settle on just one of the terms in the rust code?
>
I’d say let’s keep the `coherent` nomenclature. It immediately shows that dma_alloc_coherent() is being used.
— Daniel
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v15 09/11] rust: dma: use `dma::Device` in `CoherentAllocation`
2025-03-17 18:52 ` [PATCH v15 09/11] rust: dma: use `dma::Device` in `CoherentAllocation` Abdiel Janulgue
@ 2025-06-03 12:18 ` Andreas Hindborg
0 siblings, 0 replies; 23+ messages in thread
From: Andreas Hindborg @ 2025-06-03 12:18 UTC (permalink / raw)
To: Abdiel Janulgue
Cc: rust-for-linux, daniel.almeida, dakr, robin.murphy, aliceryhl,
Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Trevor Gross, Valentin Obst,
linux-kernel, Christoph Hellwig, Marek Szyprowski, airlied, iommu
Hi Abdiel,
"Abdiel Janulgue" <abdiel.janulgue@gmail.com> writes:
> From: Danilo Krummrich <dakr@kernel.org>
>
> Require a `&dyn dma::Device` in `CoherentAllocation`, such that DMA
> memory can only be allocated with devices on potentially DMA capable
> busses.
>
> Signed-off-by: Danilo Krummrich <dakr@kernel.org>
> Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
Did you see my comment on v14 [1]?
Best regards,
Andreas Hindborg
[1] https://lore.kernel.org/lkml/87y0x2igjz.fsf@kernel.org/
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2025-06-03 12:18 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <rTVBNBYxl4bn6nnkXBjTN8d-dpiCOR32i2Fpe5-wuhzcGjijW1iXnKaA4pbok32ockodVqTYGEfEA_JVpOC3ZQ==@protonmail.internalid>
2025-03-17 18:52 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 01/11] rust: error: Add EOVERFLOW Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 02/11] rust: add dma coherent allocator abstraction Abdiel Janulgue
2025-03-18 13:07 ` Andreas Hindborg
2025-03-18 15:37 ` Alice Ryhl
2025-03-20 23:54 ` Miguel Ojeda
2025-03-21 6:56 ` Andreas Hindborg
2025-03-22 22:58 ` Daniel Almeida
2025-03-17 18:52 ` [PATCH v15 03/11] samples: rust: add Rust dma test sample driver Abdiel Janulgue
2025-03-18 13:06 ` Danilo Krummrich
2025-03-17 18:52 ` [PATCH v15 04/11] MAINTAINERS: add entry for Rust dma mapping helpers device driver API Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 05/11] rust: dma: implement `dma::Device` trait Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 06/11] rust: dma: add dma addressing capabilities Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 07/11] rust: pci: implement the `dma::Device` trait Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 08/11] rust: platform: " Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 09/11] rust: dma: use `dma::Device` in `CoherentAllocation` Abdiel Janulgue
2025-06-03 12:18 ` Andreas Hindborg
2025-03-17 18:52 ` [PATCH v15 10/11] rust: samples: dma: set DMA mask Abdiel Janulgue
2025-03-17 18:52 ` [PATCH v15 11/11] rust: dma: add as_slice/write functions for CoherentAllocation Abdiel Janulgue
2025-03-18 14:09 ` Andreas Hindborg
2025-03-18 11:11 ` [PATCH v15 00/11] rust: add dma coherent allocator abstraction Danilo Krummrich
2025-03-18 14:11 ` Andreas Hindborg
2025-03-20 23:22 ` Miguel Ojeda
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).