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>