您的位置:首页 > 运维架构 > 网站架构

linux mips架构PHYS_OFFSET、CAC_BASE、HIGHMEM_START、PAGE_OFFSET、virt_to_phys、phys_to_virt、page_to_phys的定义

2011-10-08 14:18 393 查看
在include/asm-mips/mach-generic/spaces.h中:

#ifndef PHYS_OFFSET

#define PHYS_OFFSET _AC(0, UL)

#endif

#ifdef CONFIG_32BIT

#define CAC_BASE _AC(0x80000000, UL)

#define IO_BASE _AC(0xa0000000, UL)

#define UNCAC_BASE _AC(0xa0000000, UL)

#ifndef MAP_BASE

#define MAP_BASE _AC(0xc0000000, UL)

#endif

/*

* Memory above this physical address will be considered highmem.

*/

#ifndef HIGHMEM_START

#define HIGHMEM_START _AC(0x20000000, UL)

#endif

#endif /* CONFIG_32BIT */

#ifdef CONFIG_64BIT

#ifndef CAC_BASE

#ifdef CONFIG_DMA_NONCOHERENT

#define CAC_BASE _AC(0x9800000000000000, UL)

#else

#define CAC_BASE _AC(0xa800000000000000, UL)

#endif

#endif

#ifndef IO_BASE

#define IO_BASE _AC(0x9000000000000000, UL)

#endif

#ifndef UNCAC_BASE

#define UNCAC_BASE _AC(0x9000000000000000, UL)

#endif

#ifndef MAP_BASE

#define MAP_BASE _AC(0xc000000000000000, UL)

#endif

/*

* Memory above this physical address will be considered highmem.

* Fixme: 59 bits is a fictive number and makes assumptions about processors

* in the distant future. Nobody will care for a few years :-)

*/

#ifndef HIGHMEM_START

#define HIGHMEM_START (_AC(1, UL) << _AC(59, UL))

#endif

#define TO_PHYS(x) ( ((x) & TO_PHYS_MASK))

#define TO_CAC(x) (CAC_BASE | ((x) & TO_PHYS_MASK))

#define TO_UNCAC(x) (UNCAC_BASE | ((x) & TO_PHYS_MASK))

#endif /* CONFIG_64BIT */

/*

* This handles the memory map.

*/

#ifndef PAGE_OFFSET

#define PAGE_OFFSET (CAC_BASE + PHYS_OFFSET)

#endif

其中:_AC的定义见inlude\linux\const.h

#ifdef __ASSEMBLY__

#define _AC(X,Y) X

#define _AT(T,X) X

#else

#define __AC(X,Y) (X##Y)

#define _AC(X,Y) __AC(X,Y)

#define _AT(T,X) ((T)(X))

#endif

在非汇编程序中将两个参数拼接在一起

在include/asm-mips/io.h里:

/*

* virt_to_phys - map virtual addresses to physical

* @address: address to remap

*

* The returned physical address is the physical (CPU) mapping for

* the memory address given. It is only valid to use this function on

* addresses directly mapped or allocated via kmalloc.

*

* This function does not give bus mappings for DMA transfers. In

* almost all conceivable cases a device driver should not be using

* this function

*/

static inline unsigned long virt_to_phys(volatile const void *address)

{

return (unsigned long)address - PAGE_OFFSET + PHYS_OFFSET;

}

/*

* phys_to_virt - map physical address to virtual

* @address: address to remap

*

* The returned virtual address is a current CPU mapping for

* the memory address given. It is only valid to use this function on

* addresses that have a kernel mapping

*

* This function does not handle bus mappings for DMA transfers. In

* almost all conceivable cases a device driver should not be using

* this function

*/

static inline void * phys_to_virt(unsigned long address)

{

return (void *)(address + PAGE_OFFSET - PHYS_OFFSET);

}

/*

* Change "struct page" to physical address.

*/

#define page_to_phys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT

在arch/mips/include/asm里:

/*

* __pa()/__va() should be used only during mem init.

*/

#ifdef CONFIG_64BIT

#define __pa(x) \

({ \

unsigned long __x = (unsigned long)(x); \

__x < CKSEG0 ? XPHYSADDR(__x) : CPHYSADDR(__x); \

})

#else

#define __pa(x) \

((unsigned long)(x) - PAGE_OFFSET + PHYS_OFFSET)

#endif

#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - PHYS_OFFSET))

在arch/mips/include/asm/page.h中:

#define ARCH_PFN_OFFSET PFN_UP(PHYS_OFFSET)

在inclue/asm-generic/memory_model.h中:

#if defined(CONFIG_FLATMEM)

#ifndef ARCH_PFN_OFFSET

#define ARCH_PFN_OFFSET (0UL)

#endif

...

#endif

#if defined(CONFIG_FLATMEM)

#define __pfn_to_page(pfn) (mem_map + ((pfn) - ARCH_PFN_OFFSET))

#define __page_to_pfn(page) ((unsigned long)((page) - mem_map) + \

ARCH_PFN_OFFSET)

...

#endif

#define page_to_pfn __page_to_pfn

#define pfn_to_page __pfn_to_page

其中宏__page_to_pfn(page)返回的是数组下标。理解了指针相减就明白了

假如page的实际地址是 p1, mem_map的地址是 p2;

那么这个宏结果就是 (p1-p2)/sizeof(struct page) + PHYS_PFN_OFFSET;

参考:

//对同类型的结构体指针进行+,-运算,结果是加减多少个结构体.

//1.对于减运算

//两个同类型的结构体指针进行"-"运算,结果为两个单元地址空间之间一共距离多少个这种结构体

//例:page_to_pfn()函数:将mem_map_t类型的页管理单元page,转换为它所管理的页对应的物理页帧号

#define page_to_pfn(page) (((page) - mem_map) + PHYS_PFN_OFFSET)

//page - mem_map=表示从mem_map到page一共有多少个mem_map_t这种结构体,即:一共有多少个页

//2.对于加运算

//对结构体指针进行"+"运算,如:mem_map + 3;结果为mem_map所在地址加上3个mem_map_t结构体大小结构块之后的最终地址

//例:pfn_to_page()函数:将物理页帧号转换为管理该页的mem_map_t类型指针page

#define pfn_to_page(pfn) ((mem_map + (pfn)) - PHYS_PFN_OFFSET)

//变换一种形式可以更容易理解:(mem_map + (pfn - PHYS_PFN_OFFSET))

//其中index = pfn - PHYS_PFN_OFFSET表示物理页帧号pfn对应的偏移索引号index
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: