Re: [PATCH v11 2/3] rust: add dma coherent allocator abstraction.

Alice Ryhl
2025-01-27T10:43:52Z

On Mon, Jan 27, 2025 at 11:37 AM Danilo Krummrich <dakr@kernel.org> wrote:
>
> On Fri, Jan 24, 2025 at 08:27:36AM +0100, Alice Ryhl wrote:
> > On Thu, Jan 23, 2025 at 11:43 AM Abdiel Janulgue
> > <abdiel.janulgue@gmail.com> wrote:
> > > + /// Reads 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 data returned should be regarded by the
> > > + /// caller as a snapshot of the region when this function is called, as 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.
> > > + pub unsafe fn as_slice(&self, offset: usize, count: usize) -> Result<&[T]> {
> >
> > You were asked to rename this function because it returns a slice, but
> > I wonder if it's better to take an `&mut [T]` argument and to have
> > this function copy data into that argument. That way, we could make
> > the function itself safe. Perhaps the actual copy needs to be
> > volatile?
>
> Why do we consider the existing one unsafe?
>
> Surely, it's not desirable that the contents of the buffer are modified by the
> HW unexpectedly, but is this a concern in terms of Rust safety requirements?
>
> And if so, how does this go away with the proposed approach?

In Rust, it is undefined behavior if the value behind an immutable
reference changes (unless the type uses UnsafeCell / Opaque or
similar). That is, any two consecutive reads of the same immutable
reference must return the same byte value no matter what happened in
between those reads.

If we manually perform the read as a volatile read, then it is
arguably allowed for the value to be modified by the hardware while we
read the value.

> > Well ... I understand that we did this previously and that we want to
> > avoid it because it causes too much reading if T is a struct and we
> > just want to read one of its fields. How about an API like this?
> >
> > dma_read!(my_alloc[7].foo)
> >
> > which expands to something that reads the value of the foo field of
> > the 7th element, and
> >
> > dma_write!(my_alloc[7].foo = 13);
>
> I really like how this turns out.

Yes, I think it would be a nice API.

Alice