Re: DMA from/to user-space memory

Robert Kaiser (rob@sysgo.de)
Fri, 15 May 1998 20:33:52 +0200 (MEST)


Hi,

On Fri, 15 May 1998, Linus Torvalds wrote:

>
>
> On Fri, 15 May 1998, David S. Miller wrote:
> >
> > The *big* problem I have with that is that the _application_ has to be
> > aware that DMA will be used to fill the buffer. Thus, you will never
> > be able to write a driver that implements, for instance, the plain
> > simple read() and write() system calls using user-space DMA, even
> > if your hardware is smart enough to do 32-bit addressing and unattended
> > scatter/gather DMA.
> >
> > ...
> >
> > Yes, but the _need_ of the application to be aware of the DMA being used
> > by the driver is a big disadvantage IMHO.
>
> Note that I was by no means intending to keep the DMA interface away from
> drivers. Yes, the application would have to be aware to some degree when
> it wants to use direct DMA transfers, but a lot of that can be hidden in
> the driver (so the dma_map() wouldn't necessarily be used _directly_ by
> the user, because the driver could use it internally and squirrel away the
> virtual->physical translations to make it more transparent to the user).

But then the _driver_ would be responsible for allocating the buffers,
right ? Not good IMHO.

>
> Note that doing the mlock at "read()" or "write()" time is just simply
> unacceptable. If you want to do it completely transparently for the user,
> then you follow the page table, you don't do anything like this at all.
> ....
> Again, if you actually want to do something like
>
> fd = socket(..)
> write(fd, area, size);
>
> and make that use DMA, then the way you do that is to do the page table
> following (paging them in if required), and temporarily bump the usage
> counter for that _page_ (you don't actually lock the page table, you only
> lock the use the actual page - it may be unmapped or something, but you're
> still going to access it).
>
> Btw, this works, I did it several years ago (not for DMA, but for an
> experimental zero-copy pipe). The code is not very complex, although there
> are corner issues wrt shared memory etc that you have to look out for.
> mlock() is not needed at any point. The good news is that all normal uses
> are uses without any of these corner cases, so you can choose to make the
> corner cases go slowly..

Just what I said: If there are ways to do this more efficiently (and
even more safely) without using mlock(), even better so! I'm only
concerned about the API (the three kernel-level functions I proposed).
The patch I sent you should be understood as a sample implementation
of this API written by someone with limited knowledge about Linux
memory management internals (me :-)).

> I was assuming that you were concerned about something like a frame
> grabber, where the operation would be something like

Yes, that was my initial reason to get into this, and yes, applications
using that driver are well aware when they are doing DMA.
However the driver's API, (which was dictated by a huge image processing
library from the board's manufacturer) assumes that allocation of
DMA memory is done by the application and that the driver must not
make any assumptions about how this allocation was done. You may call
this a broken design, but re-engineering this was simply not an option.

> (For example, mlock() has some huge security implications in that it locks
> a potentially huge number of pages into memory at one time,

Yes, and I really think that should be fixed. Would it be possible to
have mlock() limit the total (system-wide) count of locked pages to some
reasonable amount? The way it works now, each (root) process is allowed
to lock at most half of the system's pages, so if you have two processes
simultaneously doing that, you get a nice system lockup.

> while a
> on-the-fly page table walker only keeps those pages around that it is
> going to need next).

I'm not entirely sure if I got this right: Do you mean that you would
lock only one page at a time ? (i.e. for scatter gather, in addition
to restarting the DMA transfer from the DMA ISR, would you also have to
unlock the previous page and lock the next one ?) Then what if your
device is smart enough to to an unattended scatter/gather transfer ?
In order to exploit the potential of such hardware, you have to
lock all pages that make up a buffer and have the device do the DMA.

If a user process passes a really huge buffer (i.e. more pages than
you want to lock at a time, than a driver using my udma_* functions
could still split it into resonably-sized chunks of -say- 1MB each
and only keep one such chunk locked at a time.

(Note: when I say "locked", I don't necessarily mean "locked by
mlock()", but more something like "it is safe to assume
that the page is and will be physically present in memory
so that I can DMA from/to it).

Rob

----------------------------------------------------------------
Robert Kaiser email: rkaiser@sysgo.de
SYSGO RTS GmbH
Carl-Zeiss-Str. 41 phone: (49) 6131 9138-80
D-55129 Mainz / Germany fax: (49) 6131 9138-10

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu