moudi
moudi

Reputation: 528

Use reserved-memory and understand memremap() function

I try to implement my own Linux driver for a reserved-memory area. I following on this description: https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841683/Linux+Reserved+Memory

The memory reservation already works as expected. Now I'm writing my Linux driver using the memremap() function in my probe function:

paddr = r.start;
vaddr = memremap(paddr, 4096, MEMREMAP_WB);
printk("Allocated reserved memory, vaddr: 0x%0X, paddr: 0x%0X\n", (u32)vaddr, paddr);
printk("Allocated reserved memory, paddr (2): 0x%0x\n", virt_to_phys(vaddr));

I try to understand the memremap() and virt_to_phys() since it is important for the driver to access the right physical adders at paddr. With the linese above, I would expect, that I have two times the same physical address paddr.

Unfortunately the output is:

[10370.743577] Allocated reserved memory, vaddr: 0xE0847000, paddr: 0x20000000
[10370.750564] Allocated reserved memory, paddr (2): 0x20847000

So there is an offset of 0x847000 bytes when try to get the physical address back from vaddr using virt_to_phys(). Where does this offset come from? I would expect that the driver reads and writes to 0x20000000 instead of 0x20847000.

Upvotes: 0

Views: 96

Answers (1)

MirkoBanchi
MirkoBanchi

Reputation: 2253

virt_to_phys() computes the physical address with a simple subtraction and works only for logical kernel addresses which are, for example, those got from kmalloc. In a typical 3GB/1GB memory split layout, kernel is mapped starting from 0xC0000000 and a logical address (let's call it la) is a virtual address corresponding to a physical address (pa):

pa = la - 0xC0000000

In your case, the virtual address returned by memremap is not a logical address but virt_to_phys does not know it and performs the subtraction:

0xE0847000 - 0xC0000000 = 0x20847000

Upvotes: 0

Related Questions