If I have only the physical address of the memory buffer to which is mapped the device buffer via the PCI-Express BAR (Base Address Register), how can I map this buffer to user-space?
For example, how does usually the code should look like in Linux-kernel?
unsigned long long phys_addr = ...; // get device phys addr
unsigned long long size_buff = ...l // get device size buff
// ... mmap(), remap_pfn_range(), Or what should I do now?
On: Linux x86_64
From: https://stackoverflow.com/a/17278263/1558037
ioremap()
maps a physical address into a kernel virtual address.remap_pfn_range()
maps physical addresses directly to user space.
From: https://stackoverflow.com/a/9075865/1558037
int remap_pfn_range(struct vm_area_struct *vma, unsigned long virt_addr,
unsigned long pfn, unsigned long size, pgprot_t prot);
remap_pfn_range - remap kernel memory to userspace
May be can I use it so?
unsigned long long phys_addr = ...; // get device phys addr
unsigned long long size_buff = ...l // get device size buff
remap_pfn_range(vma, vma->vm_start, (phys_addr >> PAGE_SHIFT),
size_buff, vma->vm_page_prot);
Question: But, where can I get wma
, and what I must pre-do with wma
before call to remap_pfn_range()
?
The Linux kernel, at least, versions 2.6.x use the
ioremap()
function.You should make a previous call to
request_mem_region()
to check if that memory space is already reclaimed by another driver, and politely request that memory to be owned by your code (driver). The complete example should look like this:You can check your ownership by checking
/proc/iomem
, which will reflect the address range and the owner of every piece of memory in your system.UPDATE: I don't really know if this works for 64-bit kernels. It does for 32-bit. If 64-bit kernel don't have these kernel functions, they will have similar ones, I guess.