On Wed Aug 12, 2026 at 11:32 PM BST, Danilo Krummrich wrote:
> On Fri Aug 7, 2026 at 3:04 PM CEST, Gary Guo wrote:
>> On Wed Aug 5, 2026 at 9:39 PM BST, Danilo Krummrich wrote:
>>> On Wed Aug 5, 2026 at 1:32 PM CEST, Robin Murphy wrote:
>>>> To be fair, that is sort of the intent in the C API as well, to be clear 
>>>> that DMA addresses must not simply be treated as physical addresses, and 
>>>> aren't necessarily address-like in general e.g. comparing two 
>>>> dma_handles is pretty meaningless, since they could have different 
>>>> values but still refer to the same underlying memory, or vice-versa. 
>>>> Adding or subtracting offsets within the bounds of the original 
>>>> allocation/mapping size is pretty much the only arithmetic that _is_ valid.
>>>
>>> Yes, I did suggest a dma::Range type [1] for this purpose, such that only 
>>> this
>>> kind arithmetic is possible to do.
>>>
>>> The dma::Range type should have a method returning its embedded raw value 
>>> which
>>> then can be used to program registers etc.
>>>
>>> This patch is only an intermediate step, that clarifies that intent of the
>>> current usage of dma_handle() (or now dma_address()), which is not to serve 
>>> as a
>>> handle.
>>
>> I suppose with I/O projections now it's rarer that people need to operate on 
>> dma
>> address directly? What do you envison as the use case for `dma::Range`?
>>
>> Also, I suppose we can also represent dma address ranges as `Io` views that 
>> does
>> not implement any accessor methods, so projection still works on them.
>
> Yes, that covers most cases. What about SGEntry cases and CoherentHandle?
>
> For instance, in nova-core we currently have
>
>       for sg_entry in sg_table.iter() {
>           let num_pages = 
> usize::from_safe_cast(sg_entry.dma_len()).div_ceil(GSP_PAGE_SIZE);
>           for i in 0..num_pages {
>               let entry = sg_entry.dma_address()
>                   + (u64::from_safe_cast(i) * 
> u64::from_safe_cast(GSP_PAGE_SIZE));
>               dst.extend_from_slice(&entry.to_le_bytes(), GFP_KERNEL)?;
>           }
>       }
>
> which could become
>
>       for sg_entry in sg_table.iter() {
>           sg_entry.dma_range().for_each_block(GSP_PAGE_SIZE, |addr| {
>               dst.extend_from_slice(&addr.to_le_bytes(), GFP_KERNEL)
>           })?;
>       }

If we have `DmaRange<T>: IoBase` and `fn dma_address() -> DmaRange<[u8]>`
then you could imagine doing

    io_project!(sg_entry.dma_range(), [panic: i * GSP_PAGE_SIZE..]).address()

A caveat is that it's slightly tricky to implement `IoBase` for `DmaRange` due
to the ptr_metadata feature being unstable... That said, this could be worked
around.

Best,
Gary

Reply via email to