arm页表在linux中的融合

参考:arm-linux内存页表创建

arm的第一级页表条目数为4096个,对于4K页第二级目录条目个数为256个,一级二级条目都是每个条目4字节。

在linux下二级分页如下:虚拟地址——> PGD转换——> PTE转换——>物理地址。

arm-linux假装第一级目录只有2048个条目,但其实每个条目是2个ulong大小即8字节,所以最终设置MMU的还是4096个条目,只是每访问1个pgd条目将可以访问到2个pte条目,linux为了实现其内存管理功能又在后面加上2个对应的假pte表,这个假pte表专门给linux内核代码自己用的,不会影响arm硬件(事实上还有一个重要原因是,linux要求pte表长度为4K即一页)。

#define PTRS_PER_PTE        512
#define PTRS_PER_PMD        1
#define PTRS_PER_PGD        2048

看懂这个就很容易弄懂所有的创建内存映射的内容了,像为什么PTRS_PER_PTE定义为512、为什么PTRS_PER_PGD是2048、为什么PGDIR_SHIFT是21等等

/*获得addr在dir一级页表描述符指定的二级页表中的二级页表描述符对应的linux_pte的虚拟地址*/
#define pte_offset_kernel(dir,addr)    (pmd_page_vaddr(*(dir)) + __pte_index(addr))

/*获得二级页表linux pte的虚拟地址*/
static inline pte_t *pmd_page_vaddr(pmd_t pmd)
{
    unsigned long ptr;

    ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1);
    ptr += PTRS_PER_PTE * sizeof(void *);

    return __va(ptr);
}
/*获得addr对应的pte entry在二级页表中的索引*/
#define __pte_index(addr)    (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))

 

 

typedef struct { unsigned long pte; } pte_t;
typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd[2]; } pgd_t;
typedef struct { unsigned long pgprot; } pgprot_t;

 

 

 

posted @ 2018-01-08 22:27  bluebluebluesky  阅读(802)  评论(0编辑  收藏  举报