All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Hindborg <a.hindborg@kernel.org>
To: Abdiel Janulgue <abdiel.janulgue@gmail.com>,
	acourbot@nvidia.com, dakr@kernel.org, jgg@ziepe.ca,
	lyude@redhat.com
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Tamir Duberstein" <tamird@gmail.com>,
	"FUJITA Tomonori" <fujita.tomonori@gmail.com>,
	linux-kernel@vger.kernel.org,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Randy Dunlap" <rdunlap@infradead.org>,
	"Herbert Xu" <herbert@gondor.apana.org.au>,
	"Caleb Sander Mateos" <csander@purestorage.com>,
	"Petr Tesarik" <petr@tesarici.cz>,
	"Sui Jingfeng" <sui.jingfeng@linux.dev>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	"Robin Murphy" <robin.murphy@arm.com>,
	airlied@redhat.com, iommu@lists.linux.dev,
	rust-for-linux@vger.kernel.org,
	"Abdiel Janulgue" <abdiel.janulgue@gmail.com>
Subject: Re: [PATCH v3 1/2] rust: add initial scatterlist abstraction
Date: Fri, 08 Aug 2025 15:13:12 +0200	[thread overview]
Message-ID: <877bze553r.fsf@kernel.org> (raw)
In-Reply-To: <20250718103359.1026240-2-abdiel.janulgue@gmail.com>

"Abdiel Janulgue" <abdiel.janulgue@gmail.com> writes:

> Add the rust abstraction for scatterlist. This allows use of the C
> scatterlist within Rust code which the caller can allocate themselves
> or to wrap existing kernel sg_table objects.
>
> Co-developed-by: Alexandre Courbot <acourbot@nvidia.com>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> Signed-off-by: Abdiel Janulgue <abdiel.janulgue@gmail.com>
> ---

<cut>

> +    /// Obtain the raw `struct scatterlist *`.
> +    pub(crate) fn as_raw(&self) -> *mut bindings::scatterlist {
> +        self.0.get()
> +    }
> +
> +    /// Returns the DMA address of this SG entry.

In what address space? Device or CPU?

> +    pub fn dma_address(&self) -> bindings::dma_addr_t {
> +        // SAFETY: By the type invariant of `SGEntry`, ptr is valid.
> +        unsafe { bindings::sg_dma_address(self.0.get()) }
> +    }
> +
> +    /// Returns the length of this SG entry.
> +    pub fn dma_len(&self) -> u32 {
> +        // SAFETY: By the type invariant of `SGEntry`, ptr is valid.
> +        unsafe { bindings::sg_dma_len(self.0.get()) }
> +    }
> +
> +    /// Internal constructor helper to set this entry to point at a given page. Not to be used directly.
> +    fn set_page(&mut self, page: &Page, length: u32, offset: u32) {

Is it safe to call this with invalid length?

> +        let c: *mut bindings::scatterlist = self.0.get();
> +        // SAFETY: according to the `SGEntry` invariant, the scatterlist pointer is valid.
> +        // `Page` invariant also ensure the pointer is valid.
> +        unsafe { bindings::sg_set_page(c, page.as_ptr(), length, offset) };
> +    }
> +}
> +
> +/// Trait implemented by all mapping states.
> +pub trait MappingState {}
> +
> +/// Trait implemented by all mapping states representing the fact that a `struct sg_table` is
> +/// mapped (and thus its DMA addresses are valid).
> +pub trait MappedState: MappingState {}
> +
> +/// Represents the fact that a `struct sg_table` is not DMA-mapped.

Could you explain what "DMA-mapped" means? Does it mean that everything
is set up so that a device can access the memory?

> +pub struct Unmapped;
> +impl MappingState for Unmapped {}
> +
> +/// Represents the fact that a `struct sg_table` is DMA-mapped by an external entity.

What is external entity?

> +pub struct BorrowedMapping;
> +impl MappingState for BorrowedMapping {}
> +impl MappedState for BorrowedMapping {}
> +
> +/// A managed DMA mapping of a `struct sg_table` to a given device.
> +///
> +/// The mapping is cleared when this object is dropped.
> +///
> +/// # Invariants
> +///
> +/// - The `scatterlist` pointer is valid for the lifetime of a `ManagedMapping` instance.
> +/// - The `Device` instance is within a [`kernel::device::Bound`] context.
> +pub struct ManagedMapping {
> +    dev: ARef<Device>,
> +    dir: DmaDataDirection,
> +    // This works because the `sgl` member of `struct sg_table` never moves, and the fact we can
> +    // build this implies that we have an exclusive reference to the `sg_table`, thus it cannot be
> +    // modified by anyone else.
> +    sgl: *mut bindings::scatterlist,
> +    orig_nents: ffi::c_uint,

Could you use a more descriptive name for this field? We don't _have_ to
contract all words to the least possible amount of letters.

> +}
> +

<cut>

> +
> +/// Provides a list of pages that can be used to build a `SGTable`.
> +pub trait SGTablePages {
> +    /// Returns an iterator to the pages providing the backing memory of `self`.
> +    ///
> +    /// Implementers should return an iterator which provides information regarding each page entry to
> +    /// build the `SGTable`. The first element in the tuple is a reference to the Page, the second element
> +    /// as the offset into the page, and the third as the length of data. The fields correspond to the
> +    /// first three fields of the C `struct scatterlist`.
> +    fn iter<'a>(&'a self) -> impl Iterator<Item = (&'a Page, usize, usize)>;

Would it make sense to use a struct with proper names here, rather than
a tuple?

<cut>

> +    /// let mut pages = KVec::new();
> +    /// let _ = pages.push(Page::alloc_page(GFP_KERNEL)?, GFP_KERNEL);
> +    /// let _ = pages.push(Page::alloc_page(GFP_KERNEL)?, GFP_KERNEL);
> +    /// let sgt = SGTable::new_owned(PagesArray(pages), GFP_KERNEL)?;
> +    /// # Ok::<(), Error>(())
> +    /// ```
> +    pub fn new_owned(pages: P, flags: kernel::alloc::Flags) -> Result<Self> {
> +        // SAFETY: `sgt` is not a reference.
> +        let mut sgt: bindings::sg_table = unsafe { core::mem::zeroed() };

I think this unsafe goes away with recent pin-init patches.

https://lore.kernel.org/r/20250523145125.523275-1-lossin@kernel.org

> +
> +        // SAFETY: The sgt pointer is from the Opaque-wrapped `sg_table` object hence is valid.
> +        let ret =
> +            unsafe { bindings::sg_alloc_table(&mut sgt, pages.entries() as u32, flags.as_raw()) };
> +        if ret != 0 {
> +            return Err(Error::from_errno(ret));
> +        }
> +        // SAFETY: We just successfully allocated `sgt`, hence the pointer is valid and have sole access to

nit: I would prefer "exclusive" over "sole".


Best regards,
Andreas Hindborg



  parent reply	other threads:[~2025-08-08 13:13 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-18 10:33 [PATCH v3 0/2] rust: add initial scatterlist abstraction Abdiel Janulgue
2025-07-18 10:33 ` [PATCH v3 1/2] " Abdiel Janulgue
2025-07-23  0:44   ` Daniel Almeida
2025-07-24  5:40   ` Alexandre Courbot
2025-08-04  8:56     ` Abdiel Janulgue
2025-08-05 15:42       ` Jason Gunthorpe
2025-08-05 16:12         ` Danilo Krummrich
2025-07-24 20:19   ` Lyude Paul
2025-07-26 14:10     ` Alexandre Courbot
2025-08-01 18:26   ` Robin Murphy
2025-08-04  9:04     ` Alexandre Courbot
2025-08-08 13:13   ` Andreas Hindborg [this message]
2025-08-08 20:23     ` Benno Lossin
2025-07-18 10:33 ` [PATCH v3 2/2] samples: rust: add sample code for " Abdiel Janulgue
2025-07-23  0:54   ` Daniel Almeida
2025-07-23  8:07     ` Alexandre Courbot
2025-08-08 12:18   ` Andreas Hindborg
2025-07-18 10:50 ` [PATCH v3 0/2] rust: add initial " Danilo Krummrich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=877bze553r.fsf@kernel.org \
    --to=a.hindborg@kernel.org \
    --cc=abdiel.janulgue@gmail.com \
    --cc=acourbot@nvidia.com \
    --cc=airlied@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=csander@purestorage.com \
    --cc=dakr@kernel.org \
    --cc=fujita.tomonori@gmail.com \
    --cc=gary@garyguo.net \
    --cc=herbert@gondor.apana.org.au \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@ziepe.ca \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=lyude@redhat.com \
    --cc=m.szyprowski@samsung.com \
    --cc=ojeda@kernel.org \
    --cc=petr@tesarici.cz \
    --cc=rdunlap@infradead.org \
    --cc=robin.murphy@arm.com \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=sui.jingfeng@linux.dev \
    --cc=tamird@gmail.com \
    --cc=tmgross@umich.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.