内存管理-9-内存常用宏函数

基于msm-5.4

一、常用宏函数

1. 页与页帧号转换

//include/asm-generic/memory_model.h
#define pfn_to_page(pfn)    (vmemmap + (pfn))
#define page_to_pfn(page)    (unsigned long)((page) - vmemmap)

注:使能了 CONFIG_SPARSEMEM_VMEMMAP 才使用的是这一组宏。vmemmap是一个struct page*类型的指针,实际上是当做数组使用。sizeof(page)=64,指针相减为偏移元素个数。


2. 页与物理地址转换

//include/linux/pfn.h
#define PFN_PHYS(x)    ((phys_addr_t)(x) << PAGE_SHIFT) //x<<12
#define PHYS_PFN(x)    ((unsigned long)((x) >> PAGE_SHIFT))

//include/asm-generic/memory_model.h
#define    __phys_to_pfn(paddr)    PHYS_PFN(paddr)
#define    __pfn_to_phys(pfn)    PFN_PHYS(pfn)

//arm64/include/asm/memory.h
#define page_to_phys(page)    (__pfn_to_phys(page_to_pfn(page)))
#define phys_to_page(phys)    (pfn_to_page(__phys_to_pfn(phys)))

//page_to_phys 展开后:(page - vmemmap) << PAGE_SHIFT)
//phys_to_page 展开后:vmemmap + (phys >> PAGE_SHIFT)

注:指针相减去,是struct page元素偏移个数,而不是单纯的数值相减。


3. 页与虚拟地址转换

//arm64/include/asm/memory.h
#define page_to_virt(x)    ({                        \
    __typeof__(x) __page = x;                    \
    u64 __idx = ((u64)__page - VMEMMAP_START) / sizeof(struct page);\
    u64 __addr = PAGE_OFFSET + (__idx * PAGE_SIZE);            \
    (void *)__tag_set((const void *)__addr, page_kasan_tag(__page));\
})
#define virt_to_page(x)    ({                        \
    u64 __idx = (__tag_reset((u64)x) - PAGE_OFFSET) / PAGE_SIZE;    \
    u64 __addr = VMEMMAP_START + (__idx * sizeof(struct page));    \
    (struct page *)__addr;                        \
})

//展开后为:

#define page_to_virt(x) \
(void *)(((u64)x - VMEMMAP_START)/sizeof(struct page) * PAGE_SIZE + PAGE_OFFSET)

#define virt_to_page(x) \
(struct page *)(VMEMMAP_START + ((((u64)x - PAGE_OFFSET) / PAGE_SIZE) * sizeof(struct page)))


4. page_address

实现是在 mm/highmem.c 中,返回page页映射的虚拟地址。实验,从伙伴系统中分配出页,其返回的虚拟地址与 page_to_virt(x) 返回的虚拟地址相等。

 

二、全局变量

1. pfn相关

/*
 * start_kernel --> setup_arch --> bootmem_init()
 */
bootmem_init()
{
    max_pfn = max_low_pfn = max; //memory内存区最大的页帧号
    min_low_pfn = min;           //memory内存区最小的页帧号
}

 

 

 

注:头文件包含关系

#include <linux/mm.h>
    #include <linux/mmdebug.h>
    #include <linux/gfp.h>
    #include <linux/bug.h>
    #include <linux/list.h>
    #include <linux/mmzone.h>
    #include <linux/rbtree.h>
    #include <linux/atomic.h>
    #include <linux/debug_locks.h>
    #include <linux/mm_types.h>
    #include <linux/mmap_lock.h>
    #include <linux/range.h>
    #include <linux/pfn.h>
    #include <linux/percpu-refcount.h>
    #include <linux/bit_spinlock.h>
    #include <linux/shrinker.h>
    #include <linux/resource.h>
    #include <linux/page_ext.h>
    #include <linux/err.h>
    #include <linux/page_ref.h>
    #include <linux/memremap.h>
    #include <linux/overflow.h>
    #include <linux/sizes.h>
    #include <linux/android_kabi.h>
    #include <linux/android_vendor.h>
    #include <asm/page.h>
        #include <linux/personality.h>
        #include <asm/pgtable-types.h>
        #include <asm/memory.h>
        #include <asm-generic/getorder.h>
    #include <asm/pgtable.h>
    #include <asm/processor.h>
    #include <linux/page-flags.h>
    #include <linux/huge_mm.h>

 

posted on 2024-07-01 16:08  Hello-World3  阅读(3)  评论(0编辑  收藏  举报

导航