Getting the physical address of kmalloc's memory

No, this is not a 'google first' post. (Or at least I hope it isn't, because I did spend some serious time already on this. :-) )

I work on ARM, and am writing a device driver. The problem is that I have a peace of memory I dynamically allocate with kmalloc( ..,..,GPF_KERNEL). Now our embedded device has a DMA-unit, which of course doesn't want to see the return address of kmalloc, because it is virtual.

Now, the question is whether:

virt_to_phys( kmalloc_return_address )

gives me the physical address. Some posters at Google say 'yes', other say 'no' and again others say it depends on the platform. The latter therefore doesn't sound logical.

On ARM, I suspect it is not, because my system violently crashes if I feed this address to my DMA-unit. If I then take a fixed physical address and via ioremap get a virtual address (actually a cookie, but on ARM this is fortunately the same, which made testing easy), and do a virt_to_phys on that cookie, I indeed don't get back my physical address. So this strengthes me in my assumtion, virt_to_phys does something, but not what I hoped/some believe ... (*)

So the first question is: What does virts_to_phys actually do (all all platforms)?

Second question is, because I found the function consistent_alloc. This function which is as I understood ARM and PPC only, and allocates a uncached, but also unbuffered peace of memory (The latter is at least not achived with kmalloc). However, it also gives me the hardware-address. So, in my case this should solve the problem, but this still makes me wonder, what developers on other platforms have to do to get a physical address of a kmalloc-ed peace of memory.

So the second question: Does there exists a portable method at all?

Or am I missing somnething completely? In that case please educate me. :-)

Regards,

Armin

(*) Although it seems that for IA32 this behaviour is 'normal' in the way, that virt_to_phys is not defibed for ioremap-ed addresses. However, in the case - as on ARM - where cookies and virtual addresses are by luck identical, this shouldn't matter since thevirt-to_phys function/macro cannot tell of course whether it is a cookie or 'true' virtual address.

Reply to
Armin Gerritsen
Loading thread data ...

Armin,

try to use virt_to_bus(). The comments in linux/include/asm-arm/memory.h suggest, that it may be the function you're looking for.

j.

Reply to
Jacek Rafal Radzikowski

[...] Armin,

try to use virt_to_bus(). The comments in linux/include/asm-arm/memory.h suggest, that it may be the function you're looking for.

j.

Reply to
Jacek Rafal Radzikowski

Usually the allocated buffer can consist of multiple pieces. So a single virt_to_phys( kmalloc_return_address ) does not describe it. I suppose there is a function (but not kmalloc) that allocates memory in a single piece for DMA use. Of course this will fail if the system was running for some time, as not larger pieces of sequential RAM are existing any more.

-Michael

Reply to
Michael Schnell

Nope. kmalloc()/get_free_pages(), et. al., memory is always contiguous. A single virt_to_phys() will work fine. However, vmalloc() memory is _not_ necessarily contiguous but nobody would ever consider DMA into vmalloc()'ed memory ;-)

Reply to
Tommy Reynolds

Not with kmalloc ... It is guaranteed to be consecutive blocks. Actually, that's why one must use kmalloc instead of vmalloc for DMA-units or similar tasks. (BTW consistent_alloc does the same.)

Armin

Reply to
Armin Gerritsen

Doesn't work. Actually I found the answer in the Linux Documentation thanks to some poster in another group ...

It seems that all virt_to_xxxx calls should not be used for _this purpose_.

On some platforms it may work, but that is not portable and also not the intended use of the functions. So in short: They do not what the name might suggest.

The answer lays in:

/usr/src/linux/Documentation/DMA-mapping.txt

which explains some variants of consistent_alloc as used on ARM/PPC. These variants are supposed to be platform-independent.

Regards,

Armin

Reply to
Armin Gerritsen

I did a little looking around and it seems to me that you need to give kmalloc the GFP_ATOMIC parameter to get a single consecutive block.

-Michael

Reply to
Michael Schnell

Sorry, my hint to GPF_ATOMIC seems to be misleading,

but I found that there is a flag __GPF_DMA, that might to be set if the block needs to be accessed by DMA.

-Michael

Reply to
Michael Schnell

Thanks anyway. Note, that I shouldn't use kmalloc at all, since there is no direct way of getting its physical address afterwards. It turned out that virt_to_xxxx do NOT do what the name may suggest and a lot of people think it does! It is NOT a generic way to translate between physical/bus and virtual addresses. What it mostly does is add a few offsets related to pages. On some platforms that may be enough for some specific usecases, but on other platforms and usecases it does not.

Simply said: don't use virt_to_xxxx in drivers at all, for translating between physical and virtual addressed of memory allocated with kmalloc, since it will not be guaranteed to work.

However, if you use the pci_alloc_consistent functions it works in a portable way. The name is misleading, since it cabn also be used for non-PCI devices. Simplypass on NULL for the PCI-device descriptor. On ARM, one can also use alloc_consistent, which is actually the ARM-implementation of the pci-function if one looks at the source. However, the same GFP_XXX parameters apply there (where in case of pci_alloc_consistent the GFP_DMA is automaticly added, while in consistent_alloc it is not and one has to do it oneself), so your comment was still very helpfull

Regards,

Armin

Reply to
Armin Gerritsen

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.