Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Feb 2002 20:11:45 -0800
From:      Terry Lambert <tlambert2@mindspring.com>
To:        mike varga <mike.varga@cavium.com>
Cc:        freebsd-arch@freebsd.org
Subject:   Re: virtual address from physical
Message-ID:  <3C6DDC01.2C7AE9C0@mindspring.com>
References:  <009b01c1b692$1beea670$b210a8c0@netscreen5>

next in thread | previous in thread | raw e-mail | index | archive | help
mike varga wrote:

Quit sending HTML email to -arch.

[ ... applying magic decoder ring ... ]
| Does anyone know of an easy
| way to get a process's virtual
| address from a physical address?
| 
| Linux has functions that allow
| programmers to go both ways.
| --virtual to physical 
| --physical to virtual
| 
| Are there analogs in 
| FreeBSD?
| 
| I am aware of vtophys(),
| but can not find anything 
| that goes the other way.
| 
| I could search a process's
| page table for a base/len combination
| that my physical address falls within 
| and then add the offset?

This is what you have to do; it's a pmap lookup.  There
are a couple of utility functions that know how to do
this, and you can crib code from them.  They are in the
i386/pmap.c code.

In general, you can never know what physical memory is
backing a user page at a given time.

That is, if you make a call to a driver to schedule an
I/O to complete at a later time, unless the pages you
are planning on using for the I/O are wired down for
the duration of the I/O (guaranteed to never be swapped
out and overwritten), by the time the device decides to
DMA into/out of that memory area, the physical pages
where it will be writing to/reading from may not contain
that process memory that they contained before, and you
may be DMA'ing data to the device from some random page,
or to some random page, that's actually in another
process or in the kernel, by the time the driver does
its thing.

This is why it's better to allocated a wired down region
of the KVA space, and use that, instead, with the user
space address mapping being well known to the process,
and the region shared between a physical address and
not.

Passing the physical address back from the driver is not
a good idea.  The pmap lookup is expensive (as you've
noticed, in your proposed workaround).  No matter how
you look at it, it will be a reverse lookup.

The best you are going to get is a contibuous wired region
that you know the start address, because you told the
driver, or the driver allocated it in the KVA space, so
that when the address is passed back from the driver, you
can do a simple subtract (using your knowledge that the
mapping is contiguous in physical memory) to map between
KVA and physical address.  The mapping to the user space
address relies on the mapping of the kernel address to a
user space address.

For this reason, you should map the device allocated KVA
space into the process (via mmap()), or map the SYSVSHM
space into the kernel address space by ketting the KVA
address from the user space address via an ioctl() to
the device.

Because using the second method would not guarantee that
the pages would be physically contiguous, requiring a
(much faster than the reverse) forward lookup for the
pmap entry, mmap'ing memory allocated by the device
driver is preferred.


On Linux, this doesn't matter much, since without a
unified VM and buffer cache, the additional copy
overhead that results from maintaining VM and buffer
cache coherency for the data dwarfs the overhead of
doing the reverse lookup.

This means that on Linux, you save a copy by doing DMA
directly into user memory, whereas on FreeBSD, the copy
is already saved for you, so doing extra work to DMA
into a specific user buffer is meaningless, so long as
that buffer is shared between the KVA and user address
spaces (e.g. mmap or SYSVSHM, etc.).


If what you wanted to do were a normal thing, you would
want:

1)	A hash so that the reverse lookup was O(1) for
	bucket identification, with a minor requirement
	for forward lookup on top of that in case of
	collision

2)	Some "magic" interface to force wiring down of
	user pages, so that they don't move out from
	under the DMA between the time the request to
	the hardware is issued, and the time that the
	hardware completes the request and tries to
	read/write the memory, which may no longer be
	there.

If what you are talking about is a small number of memory,
then you could perform the forward translation once, at
request time.  You will still need to wire the memory down,
and there is really no user space interface for that; you
will have to wire down the memory in the driver itself, and
keep an incomplete request descriptor list in your driver,
and do the lookups there (rather than pmap), to do the
reverse translation, and to let the driver control wiring
down and knowing when to unwire the pages (after the
request(s) using them have all completed).

-- Terry

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3C6DDC01.2C7AE9C0>