explanation of __va() and __pa() macros.

AFT aftnix at gmail.com
Fri Jun 22 10:45:15 EDT 2012


Bjørn Mork <bjorn at mork.no> writes:

> AFT <aftnix at gmail.com> writes:
>
>> My source is from 2.6 git tree. In LDD3 its said that a logical address
>> is mapped to physical address and vice versa by the macros __va() and
>> __pa().
>>
>> In my source tree they are defined as follows:
>>
>> <include/asm-generic/page.h>
>
> There's an important comment in the beginning of that file:
>
> /*
>  * Generic page.h implementation, for NOMMU architectures.
>  * This provides the dummy definitions for the memory management.
>  */
>
>
>> #define __va(x) ((void *)((unsigned long) (x)))
>> #define __pa(x) ((unsigned long) (x))
>>
>>
>> I'm not actually understanding how these "cute" looking casting is
>> performing "address mapping". I thought address mapping involves more
>> complex operations.
>
> The dummy definition is the identity mapping.  You can look at the real
> implementations to see more complex mappings:
>
> bjorn at nemi:/usr/local/src/git/linux$ egrep '#define __(p|v)a\(' arch/*/include/asm/page.h 
> arch/alpha/include/asm/page.h:#define __pa(x)                   ((unsigned long) (x) - PAGE_OFFSET)
> arch/alpha/include/asm/page.h:#define __va(x)                   ((void *)((unsigned long) (x) + PAGE_OFFSET))
> arch/avr32/include/asm/page.h:#define __pa(x)           PHYSADDR(x)
> arch/avr32/include/asm/page.h:#define __va(x)           ((void *)(P1SEGADDR(x)))
> arch/frv/include/asm/page.h:#define __pa(vaddr)         virt_to_phys((void *) (unsigned long) (vaddr))
> arch/frv/include/asm/page.h:#define __va(paddr)         phys_to_virt((unsigned long) (paddr))
> arch/h8300/include/asm/page.h:#define __pa(vaddr)               virt_to_phys(vaddr)
> arch/h8300/include/asm/page.h:#define __va(paddr)               phys_to_virt((unsigned long)paddr)
> arch/hexagon/include/asm/page.h:#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
> arch/hexagon/include/asm/page.h:#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
> arch/ia64/include/asm/page.h:#define __pa(x)            ({ia64_va _v; _v.l = (long) (x); _v.f.reg = 0; _v.l;})
> arch/ia64/include/asm/page.h:#define __va(x)            ({ia64_va _v; _v.l = (long) (x); _v.f.reg = -1; _v.p;})
> arch/m32r/include/asm/page.h:#define __pa(x)                    ((unsigned long)(x) - PAGE_OFFSET)
> arch/m32r/include/asm/page.h:#define __va(x)                    ((void *)((unsigned long)(x) + PAGE_OFFSET))
> arch/mips/include/asm/page.h:#define __pa(x)                                                            \
> arch/mips/include/asm/page.h:#define __pa(x)                                                            \
> arch/mips/include/asm/page.h:#define __va(x)            ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))
> arch/mn10300/include/asm/page.h:#define __pa(x)                 ((unsigned long)(x))
> arch/mn10300/include/asm/page.h:#define __va(x)                 ((void *)(unsigned long)(x))
> arch/openrisc/include/asm/page.h:#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET))
> arch/openrisc/include/asm/page.h:#define __pa(x) ((unsigned long) (x) - PAGE_OFFSET)
> arch/parisc/include/asm/page.h:#define __pa(x)                  ((unsigned long)(x)-PAGE_OFFSET)
> arch/parisc/include/asm/page.h:#define __va(x)                  ((void *)((unsigned long)(x)+PAGE_OFFSET))
> arch/powerpc/include/asm/page.h:#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + VIRT_PHYS_OFFSET))
> arch/powerpc/include/asm/page.h:#define __pa(x) ((unsigned long)(x) - VIRT_PHYS_OFFSET)
> arch/powerpc/include/asm/page.h:#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + PAGE_OFFSET - MEMORY_START))
> arch/powerpc/include/asm/page.h:#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + MEMORY_START)
> arch/s390/include/asm/page.h:#define __pa(x)                 (unsigned long)(x)
> arch/s390/include/asm/page.h:#define __va(x)                 (void *)(unsigned long)(x)
> arch/score/include/asm/page.h:#define __pa(x)           ((unsigned long)(x) - PAGE_OFFSET)
> arch/score/include/asm/page.h:#define __va(x)           ((void *)((unsigned long) (x) + PAGE_OFFSET))
> arch/sh/include/asm/page.h:#define __pa(x)              ___pa((unsigned long)x)
> arch/sh/include/asm/page.h:#define __va(x)              (void *)___va((unsigned long)x)
> arch/tile/include/asm/page.h:#define __pa(kaddr) virt_to_phys((void *)(unsigned long)(kaddr))
> arch/tile/include/asm/page.h:#define __va(paddr) phys_to_virt((phys_addr_t)(paddr))
> arch/um/include/asm/page.h:#define __pa(virt) to_phys((void *) (unsigned long) (virt))
> arch/um/include/asm/page.h:#define __va(phys) to_virt((unsigned long) (phys))
> arch/x86/include/asm/page.h:#define __pa(x)             __phys_addr((unsigned long)(x))
> arch/x86/include/asm/page.h:#define __va(x)                     ((void *)((unsigned long)(x)+PAGE_OFFSET))
> arch/xtensa/include/asm/page.h:#define __pa(x)                  ((unsigned long) (x) - PAGE_OFFSET)
> arch/xtensa/include/asm/page.h:#define __va(x)                  ((void *)((unsigned long) (x) + PAGE_OFFSET))
>
>
>
> Bjørn

Hi Bjorn,

Thanks for the reply. 

cheers,
aft



More information about the Kernelnewbies mailing list