Is the DMA address returned from this call the same as the physical address? LDD3 says the DMA address should be treated as opaque by the driver. I want to mmap this DMA buffer so user-space can read/write directly to it. Question is what PFN should I specify for the remap_pfn_range (which to my pleasant surprise now (kernel 3.4+) works for conventional memory same as for I/O memory). Can I just cast the DMA address to unsigned long and convert that to PFN? Isn't this a violation of what LDD3 said about opaqueness?
Does dma_alloc_coherent always use __get_free_pages internally? Does this mean the region is potentially always over-allocated (since first function takes bytes but second function allocates in units of pages)?
Is there a way to setup a single streaming mapping for multiple consecutive pages obtained from call to __get_free_pages? dma_map_page applies to only single pages.
No, the address returned is a virtual address, otherwise you wouldn't be able to access it from kernel space. It's dma_handle which represents the physical address, but it's opaque. You need to use virt_to_phys on the address it returns and then pass this to remap_pfn_range.
I don't believe it does (it's likely to be platform dependent though), but it does allocate pages. If you want smaller amounts of memory for DMA you should use dma_pool_create and then allocate regions from there.
You can use dma_map_single instead of dma_map_page.
I'd recommend consulting DMA-API.txt for more details on some of this stuff.
Related
I have a number of memory pointers, allocated by dma_pool_alloc. For all of them, I have DMA bus address (dma_addr_t), kernel virtual address (void*), and length. I have no problems addressing them as a single entity via read/write operations provided by character device, but this approach slows down speed pretty hard (many kernel calls). I would like to map them all to a single virtual address in userspace. Stuff like remap_pfn_range accepts only a single address, which doesn't really cut it. Is there a way to do it?
P.S. Yeah, there is a number of similar questions here on SO, but none of them refer to mapping more than a single physical address.
I am developing a Linux kernel driver on 3.4. The purpose of this driver is to provide a mmap interface to Userspace from a buffer allocated in an other kernel module likely using kzalloc() (more details below). The pointer provided by mmap must point to the first address of this buffer.
I get the physical address from virt_to_phys(). I give this address right shifted by PAGE_SHIFT to remap_pfn_range() in my mmap fops call.
It is working for now but it looks to me that I am not doing the things properly because nothing ensure me that my buffer is at the top of the page (correct me if I am wrong). Maybe mmap()ing is not the right solution? I have already read the chapter 15 of LDD3 but maybe I am missing something?
Details:
The buffer is in fact a shared memory region allocated by the remoteproc module. This region is used within an asymetric multiprocessing design (OMAP4). I can get this buffer thanks to the rproc_da_to_va() call. That is why there is no way to use something like get_free_pages().
Regards
Kev
Yes, you're correct: there is no guarantee that the allocated memory is at the beginning of a page. And no simple way for you to both guarantee that and to make it truly shared memory.
Obviously you could (a) copy the data from the kzalloc'd address to a newly allocated page and insert that into the mmap'ing process' virtual address space, but then it's not shared with the original datum created by the other kernel module.
You could also (b) map the actual page being allocated by the other module into the process' memory map but it's not guaranteed to be on a page boundary and you'd also be sharing whatever other kernel data happened to reside in that page (which is both a security issue and a potential source of kernel data corruption by the user-space process into which you're sharing the page).
I suppose you could (c) modify the memory manager to return every piece of allocated data at the beginning of a page. This would work, but then every time a driver wants to allocate 12 bytes for some small structure, it will in fact be allocating 4K bytes (or whatever your page size is). That's going to waste a huge amount of memory.
There is simply no way to trick the processor into making the memory appear to be at two different offsets within a page. It's not physically possible.
Your best bet is probably to (d) modify the other driver to allocate the specific bits of data that you want to make shared in a way that ensures alignment on a page boundary (i.e. something you write to replace kzalloc).
I'm writing a PCI device driver and i need to allocate some memory for DMA,
I'm using this function:
void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, int flag);
I pass dma_handle to the device.
The return value of this function is a virtual address i can use in the kernel, the thing is i don't want to save this address for each memory allocation im doing.
Is there a way to translate the physical address dma_handle to an address i can use in the kernel?
something like one of these functions/macros:
virt_to_page(kaddr)
page_to_pfn(page)
is there a phy_to_kvirt macro/function or any other way to translate a physical address to kernel virtual address?
thanks
No, there isn't, and dma_handle isn't just any physical address. It is a physical address from the point of view of the specific device. Different devices on different buses may have entirely different views of the main memory. In addition to that, the returned virtual address may be a dynamically mapped page instead of having a fixed relation with physical mapping of main memory.
There may be enough information in kernel structures to piece the information together on certain buses and architectures but no guarantees and don't expect it to be fast – the kernel's own dma_free_coherent() requires you to supply everything, virtual address, device and dma_handle to do its work, because that is the only way it can work universally across architectures and buses.
Just to reiterate: A dma_handle is meaningless on its own. Multiple devices could have the exact same dma_handle that still refers to different memory locations.
I was looking at allocating a buffer for a DMA transaction. I read that there are two ways of doing this - coherent mappings or streaming mappings.
Now, we want cache coherent buffers. However, we are not doing any scatter/gather so we want the benefits of the dma_map_single call. We have set aside some contiguous memory in the bootargs so we always have enough contiguous memory available.
So I was wondering, can we call dma_alloc_coherent and then dma_map_single after it with the virtual address that dma_alloc_coherent returns? The returned physical address of the map single would then be set as the dma handle that dma_alloc_coherent returned in its call.
Does this make sense? Or is it superfluous/incorrect to do it this way?
You can't use both. But you're also trying to solve a nonexistent problem. Just use dma_alloc_coherent(), which gives you a contiguous DMA memory buffer with both virtual and physical addresses. DMA to the physical address, access it from the CPU with the virtual address. What's the issue?
In almost all books and articles I have read about about HIGHMEM in Linux kernel, they say while using 3:1 split, not all of the 1GB is available to the kernel for mapping. And normally its 896MB or so, with the rest being used for kernel data structures, memory maps, page tables and such.
My question is, what exactly are these data structures? Page tables are normally accessed via a page table address register, right? And the base address of page table is normally stored as a physical address. Now why do one need to reserve a virtual address space for the entire table?
Similarly, I read about kernel code itself occupying space. What does that have to do with virtual address space? Is it not the physical memory that would be consumed for storing the code?
And finally, these data structures why do they have to reserve the 128MB space? Why can't they be used out of the entire 1GB address space, as required, like any other normal data structure in kernel would do?
I have gone through LDD3, Professional Linux Kernel Architecture and several posts here at stack-overflow (like: Why Linux Kernel ZONE_NORMAL is limited to 896 MB?) and an older LWN article, but found no specific information on the same.
With regards to page tables, it's true that the MMU wouldn't care if the page tables themselves weren't mapped in the virtual address space - for the purposes of address translations, that would be OK. But when the kernel needs to modify the page tables, they do need to be mapped in the virtual address space - and the kernel can't just map them in "just in time", because it needs to modify the page tables themselves to do that. It's a chicken-and-egg problem, which means that the page tables need to remain mapped at all times.
A similar problem exists with the kernel code. For the code to execute, it must be mapped in the virtual address space - and if the code that does the page table modification were itself not present, we'd have a similar chicken-and-egg problem. Given this, it's easier to leave the entireity of the kernel code mapped all the time, along with the kernel-mode stacks and any kernel data structures access by code where you wouldn't want to potentially take a page fault. One large example of such data structures is the array of struct page structures, representing each physical memory page.
The 128MB reserve is not for a specific data structure, that always use it.
It's virtual memory, reserved for various users, which might use it. Normally, it's not all used.
About physical and virtual memory: every allocation needs three things - a physical page, a virutal page, and mapping connecting the two. Linux almost never uses physical addresses directly, it always passes virtual address translation.
For most kernel memory allocation (called lowmem), this translation is quite simple - subtract some constant from the virtual address to get the physical. But still, a virtual address is used.
Linux's memory management was written when the virtual memory space (4GB) was much larger
than the physical memory, even on the largest machines. In such cases, wasting virtual addresses is not a problem. Today, when physical memory is large, this leads to inefficiencies and problems.
The vmalloc virtual address range is used by any caller of vmalloc. For example:
1. Loading kernel drivers (using modprobe or insmod).
2. Kernel modules often allocate with vmalloc. The alternative function kmalloc used to be limited to 128K, and it rounds the size up to a power of 2, so vmalloc is often preferred for large allocations.