Re: DMA to user space

From: John Wilson (
Date: Thu Mar 16 2000 - 11:48:17 EST

On Thu, Mar 16, 2000 at 08:22:38AM -0500, Richard B. Johnson wrote:
> No. Not a "user-buffer". It may be possible to memory-map something that's
> to user space, but even that's not guaranteed. To have something
> in the ix86 machines, it needs to be:
> (1) Physical, below 16 Megabytes
> (2) DATA alignment must be such that a 64k block is not crossed
> during a DMA transfer. The ix86 machines use a page register
> to access 64k pages.
> (3) You need access to the DMA controller which the kernel isn't
> going to give you, without a fight iopl(3), etc., from user-
> space.

No no, these requirements are for ISA DMA, not DMA in general. I'm using
a PCI device, so there are no address restrictions (on x86 anyway, I dunno
how PCI works on CPUs with >32 addr bits), and it has its own DMA paging
registers so it doesn't require a contiguous buffer either. The buffer
just has to be locked in place, which sounds like mlock() would be my friend.

Also, my driver is a real driver, it doesn't run in user space. I just want
it to be able to set the device up so that the DMA buffer (*only*) is in
user space, and let 'er rip.

> > The advantage of doing the DMA in user space is that arbitrarily many devices
> > (potentially using different drivers) could be connected to the same 4
> > MB user buffer. Not many users will need this, but it works great in the
> > DOS version of the application and if possible I'd like to avoid having to
> > explain to customers why moving to the "better" OS means losing features.
> >
> DMA has nothing at all to do with this. DMA transfers data between
> physical areas, memory-to-ports, ports-to-memory, or (one channel)
> memory-to-memory. They are not "connected-to" some common buffer.

Again, you're talking about 8237 DMA channels on the ISA bus. Nothing to do
with my device. Its mapping registers have been set up so that all of the
random DMA it does will fall into a particular 4 MB buffer. So it's "connected
to" this buffer. I want to connect multiple devices (not necessarily all
using the same driver, since these bus bridges are made by three different
vendors) to the *same* buffer, which I can't do if the buffer is hidden
inside one of those drivers. That's why I want it to use the user's buffer.

> If you have N devices that are memory-mapped to the same physical
> address, they will interfere.

Clearly, but it's not a memory-mapped device, it's a bus master which wants to
do DMA to random addresses in the user's 4 MB buffer, on its own initiative.
I'm talking about ownership of the buffer to which it does the random DMA,
which is plain old memory.

> If you have N devices that can copy
> their data from a port to a shared buffer then, in principle, you
> can use these devices together if you can synchronize the copying
> operation. You can copy to/from ports without ever using DMA.
> This means that you can copy directly to/from any user buffer
> you want. You don't need to even know its physical address.

No I can't. The point of this device is to connect random unknown 1970s
DMA bus master devices to the PC. My application is a "black box" emulator,
its job is to do what it's told and let the emulated OS be in charge of the
actual devices on the other side of the bus bridge. It has no knowledge of
whether what the emulated system is going to do will cause DMA to happen,
or to what address(es), or whether it will read or write. So I *can't* have
private buffers for each device which are copied to/from the user's buffer.

I can't synchronize things between transfers, because again I have no way of
knowing whether a transfer is going on, and it's perfectly possible (actually
very likely) to have more than one transfer in progress at any given time.
All DMA devices on the foreign bus are bus masters so they have their own
buf addr and word count registers, and since they're "black boxes" I don't
know the meaning of the command/status values that I pass back and forth
between the emulated OS and the hardware, so I don't know what they will
make the foreign devices do.

Anyway as I said in my original message, I've already got the driver
more or less working (well, readl() seems to be returning what should be
"impossible" values some of the time) by using a driver-owned buffer which
the user job mmaps into a window. But I consider that a kludge. I'm a big
fan of doing what I actually *mean* whenever possible, rather than living
with some twisted hack that happens to work *most* of the time, so I'd prefer
to simulate the effect of doing DMA into the user's buffer, by *really* doing
DMA into the user's buffer!

So, back to my question: is it possible to place a DMA buffer in user space?
Is mlock() enough to hold the user's pages in place? Does virt_to_phys()
work on user addresses passed as argp to ioctl(), or does it only work on
get_free_page() addresses? I'm used to systems with entirely separate address
spaces for kernel mode and user mode, so I don't know how Linux gets around the
that in the x86, does it map a window into user space or does it just partition
a single 32-bit address space so kernel mode gets the low end and user space
gets the rest? Or would I have to fiddle with the user's page table directly?

John Wilson
D Bit

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
Please read the FAQ at

This archive was generated by hypermail 2b29 : Thu Mar 23 2000 - 21:00:18 EST