Skip to contentSkip to conversation

explanation of __va() and __pa() macros.

DISCUSSION AFT 3 participants 5 messages Jun 22, 2012

lore
Share & tools
lore

AFT

author
#0 lore raw

Hi,

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>

#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.

cheers.
aft

#1 lore raw
Quoted 11 lines · AFT

Hi,

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>

Quoted 7 lines

#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.

See the comments at the beginning of the file you quoted:

/*
* Generic page.h implementation, for NOMMU architectures.
* This provides the dummy definitions for the memory management. */

For arch-specific code try looking, for instance, at arch/x86/include/asm/page.h .

Hope this helps,
Vlad

author
#2 lore raw
Quoted 27 lines · Vlad Dogaru
Quoted 11 lines · AFT

Hi,

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>

Quoted 7 lines

#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.

See the comments at the beginning of the file you quoted:

/*
* Generic page.h implementation, for NOMMU architectures.
* This provides the dummy definitions for the memory management. */

Quoted 5 lines

For arch-specific code try looking, for instance, at arch/x86/include/asm/page.h .

Hope this helps,
Vlad

Hi Vlad,

Thanks for the explanation. I should lookout for embedded comments with more attention from now.

cheers.
aft

#3 lore raw
In reply to AFT
Quoted 7 lines · AFT

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. */

Quoted 7 lines

#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

author
#4 lore raw
Quoted 68 lines · Bj?rn Mork
Quoted 7 lines · AFT

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. */

Quoted 7 lines

#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))

Quoted 7 lines
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