How to create a kernel virtual mapping for physical addresses.
Given a physical address and a length (which may span contiguous pages), how does one go about creating a virtual mapping for that address? That address may be in high memory (above 4GB) in a 32bit system.
ioremap() wants a 32bit physical address on 32bit systems. kmap() and kmap_atomic() wants a struct page which I am not sure how to get from a physical address.
If there already is a kernel mapping, then using the existing kernel mapping would be fine if I could figure out how to get it, but if there is not one, then I need to make one.
I think setting the DMA mask to 32bit would mean that I do not have to deal with highmem addresses in my particular case, but I still do not know how to get a virtual address from a physical.
Any suggestions?
Don
Quoted 7 lines · On Saturday 09 April 2011 00:03:21 [email protected] wrote:
Given a physical address and a length (which may span contiguous pages), how does one go about creating a virtual mapping for that address? That address may be in high memory (above 4GB) in a 32bit system.
ioremap()wants a 32bit physical address on 32bit systems.kmap()andkmap_atomic()wants a struct page which I am not sure how to get from a physical address.
Use kmap() on the page you get from pfn_to_page().
Quoted 7 lines
If there already is a kernel mapping, then using the existing kernel mapping would be fine if I could figure out how to get it, but if there is not one, then I need to make one.
I think setting the DMA mask to 32bit would mean that I do not have to deal with highmem addresses in my particular case, but I still do not know how to get a virtual address from a physical.
DMA mask is only about devices doing DMA to your data, not about the kernel touching it.
Arnd
A message that is not in the archive (sent off-list or not yet received): [email protected]
Quoted 4 lines · On Thursday 21 April 2011 20:46:00 [email protected] wrote:
Thanks for your reply.
I have a block of highmem that I want to map into my 32bit driver. This block is 256M in size.
If you have highmem enabled, there probably is not enough space to map all of this at once into the vmalloc area. If you had that much virtual address space, you would not need highmem ;-)
Quoted 16 lines
I get the physical address and want to create a contiguous virtual buffer. I have been investigating
vmap()as a possible solution.I build up an array of pages as follows.
pfn = physical_address >> PAGE_SHIFT for (i = 0; i < num_pages; i++) { page = pfn_to_page(pfn); page_array[i] = page; ++pfn } map = vmap(page_array, num_pages, VM_IOREMAP, PAGE_KERNEL);Using the above method, I can memset the block of memory using map as my virtual address.
Quoted 6 lines
However, later, I get the following error message:
kernel tried to execute NX-protected page - exploit attempt? (uid: 0)
BUG: unable to handle kernel paging request at virtual address c5000840The address
0xc5000840is within the range of vmap()ed memory.
Maybe you have overwritten a kernel module and the kernel now tries to execute within the mapped area?
Quoted 1 line
What should I be doing instead?
It's not clear at all what you are actually trying to do. Which driver is this? If it's out-of-tree code, please post it here.
Arnd