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

 

在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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值