Re: Address spaces on a i386 - Getting Confused (fwd)

Jamie Lokier (lkd@tantalophile.demon.co.uk)
Thu, 1 Apr 1999 03:55:41 +0200


Hello,

Stephen C. Tweedie wrote:
> > To provide transparent user-space DMA, i.e. user does read() and a DMA
> > is done directly, you also have to allow for those things happening
> > into kernel space. As that's the API read() et al. provide, and it is
> > used on occasion. (Hence set_fs()).
>
> That's not really an issue. It's very much like mmap(): the general
> case is IO to/from a local block device (handled by generic_readpage(),
> which calls the filesystem's own bmap function to map the data to disk).
> For that, we are always talking buffer_head IO, in which b_data is
> always a kernel virtual address, and the device drivers already take
> care of any necessary translations.

What if I do
(a) mmap(/dev/fb)
(b) read file into mmaped area.

This is currently valid: anything the CPU can read/write is fair game
for a system call. And /dev/fb is a fairly sane device. /dev/ramdisk
is another, that needn't be in the kernel address range. (Think of
those patches to treat uncached memory as a ramdisk).

But the pte entries will not point to addresses which are valid kernel
addresses. It can be detected but you must make a point of doing so for
safety.

> Again, we're using exactly the same techniques which (say) ptrace uses
> to walk the user VA. It had _better_ work!

Nice detective work, us :-)
-- ptrace has exactly this bug. No-one noticed yet.

I just checked the i386 version. It will not crash because it
checks the address, however it will not return the data that the
target process sees, or write it. It will return zeros.

For ptrace I consider this an omission that is rarely missed. At least
it shows how to easily detect the weirdly-mapped cases. For user-space
DMA to/from block devices as you're doing, I guess it is not too bad if
DMA simply falls back to the current indirect DMA in these cases.

> >> Finding the bus address of a kernel physical address is easy.
>
> > virt_to_bus(phys_to_virt()) doesn't work on i386 due to the bit masking
> > operations used.
>
> I can't see any way in which it should fail for any valid VA page.

See example above. It will fail for those addresses.

> Again, we are _only_ talking about valid VA entries. This will be fine.
> These pages already have kernel virtual addresses (or large parts of the
> kernel would stop working), and they already have valid bus addresses.

No, memory-mapped devices don't have kernel virtual addresses in their
ptes, however they are still fair game for system calls. The kernel,
for the most part, is fine with that.

It looks like, for your purposes, it is easy enough to detect this and
fall back to not doing direct DMA.

It is not so easy for me as I wish to support DMA transparently between
devices the way that bttv -> framebuffer does it now.

> Fair enough, but I'm not talking to the devices directly. Buffer_heads
> are already defined to have a virtual address in bh->b_data, and the
> block device driver layer is already required to do the right thing with
> that.

Agreed 100%. Your strategy is brilliant! Avoid the general problem :-)

> No. There are no device drivers right now in Linux which "specifically"
> support user-space DMA: until recently there simply hasn't been such a
> thing for them to support.

Exceptions already: bttv et al., and various peoples' network things.
Done with grotesque, bug-prone and non-portable hacks.

> Converting a virtual address to a bus
> address is a standard function in the architecture-dependent code.

I disagree -- in the general case of "an address visible to the kernel",
such as vmalloc() memory, this is a prominently absent standard
function.

However for your purpose it is not a problem. So long as you check the
result of phys_to_virt() against PAGE_OFFSET and high_memory and fall
back to indirect DMA when outside that range, all will be well.

Later, if anyone cares, these special cases can be optimised to
permit DMA between devices on specific architectures.

> OK, we probably need to talk about this offline. I'll follow up on this
> tomorrow.

Me need sleep. Real bad :) Moving house later :)

-- Jamie

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/