bus_dmamap_load_uio() and user data
Max Laier
max at love2party.net
Sun Jan 10 20:13:02 UTC 2010
On Friday 08 January 2010 17:13:29 John Baldwin wrote:
> On Friday 08 January 2010 9:14:36 am Mark Tinguely wrote:
> > > You should use the pmap from the thread in the uio structure. Similar
> > > to this from the x86 bus_dma code:
> > >
> > > if (uio->uio_segflg == UIO_USERSPACE) {
> > > KASSERT(uio->uio_td != NULL,
> > > ("bus_dmamap_load_uio: USERSPACE but no
> > > proc")); pmap = vmspace_pmap(uio->uio_td->td_proc->p_vmspace); } else
> > > pmap = NULL;
> > >
> > > Later when doing VA -> PA conversions the code does this:
> > >
> > > if (pmap)
> > > paddr = pmap_extract(pmap, vaddr);
> > > else
> > > paddr = pmap_kextract(vaddr);
> >
> > We do that, but I notice that all the architecture that implement
> > bounce buffers assume the VA is in the current map. Most of the
> > addresses are KVA, but bus_dmamap_load_uio() can be in the user space.
> >
> > I was wondering about the sequence:
> >
> > bus_dmamap_load_uio() user space
> > dma_load_buffer()
> > add bounce page save UVA (in caller user map)
> >
> > later:
> >
> > bus_dma_sync
> > copies bounce buffer from saved UVA. <- here is my concern. The user
> > pmap is not remembered use current pmap.
> >
> > Since the bounce buffer copy routines have been running in other
> > architectures for years without corruption, I was wondering we can safely
> > assume that the dma sync is running in the same thread/address space as
> > the bus_dmamap_load_uio call. I was hoping you would say, don't worry the
> > scheduler would always reload the same thread to execute the dma sync code
> > ...
>
> Ahh. I think bus_dmamap_load_uio() doesn't do deferred callbacks (i.e.
> mandates BUS_DMA_NOWAIT), and probably is always invoked from curthread.
> Even in the case of aio, the thread's vmspace is the effective one at the
> time bus_dmamap_load_uio() would be invoked, so in practice it is safe.
I ran into ?this? problem with bus_dmamap_sync and bounce buffers while trying
to do a BUS_DMASYNC_POSTREAD in interrupt context. The sync code was trying
to copy from bounce buffer to the UVA without proper context -> SEGFAULT. I
tried to move the sync to the ioctl context that is used by the userland to
figure out which part of the buffer is "ready" ... this /kind of/ worked, but
lead to DMA problems in ata (which I didn't yet investigate) when trying to
write the buffer to disk.
I meanwhile moved to exporting a kernel buffer instead, using OBJT_SG - which
is a bit more work and eats KVA, but at least on amd64 there is no shortage of
that.
--
Max
More information about the freebsd-hackers
mailing list