内核页表的初始化

1.

swapper_pg_dir : Global Page Directory (全局页目录,即最顶层页目录,PGD) 的地址

pgd_index(addr): 宏函数,返回PGD包含的项中,地址字段 值为addr的项的索引。

PAGE_OFFSET:宏函数,返回进程地址空间(线性地址)中kernel所属的地址空间的起始地址,x86_32下是0xc0000000

PAGE_SIZE:宏函数,返回页大小(4096B或2MB)

max_low_pfn:宏函数,返回一个物理内存的页块号,该页块是最后一个由kernel直接进行 逻辑/物理 映射的页块

set_pmd:宏函数,将值写入PMD(Page Middle Directory)中指定的项

__pmd:宏函数,将一个无符号整数值转换成PMD表项类型,即pmd_t

pgprot_val:宏函数,将一个无符号整数转换成__prot类型,该类型保存一个页表/页目录项的保护标志位

__pgprot:宏函数,将一个__prot类型的值转换成一个无符号整数

 

物理内存在4GB以内时,kernel重初始化内核页表的过程。(此时为2级分页PGD->PTE->PF),由于LINUX内核总是使用大页面(即一页面为2MB或4MB,而非常规的4096B),即PTE->PF(共10+12=22位,4MB)不设置页表,而是直接将内存看作页面。此模式下,PGD共有1024项,其中内核占768~1023项,总计内核寻址空间为256*4MB = 1GB


pgd = swapper_pg_dir + pgd_index(PAGE_OFFSET); /* 768 */
phys_addr
= 0x00000000;
while (phys_addr < (max_low_pfn * PAGE_SIZE) ) {
pmd
= one_md_table_init(pgd); /* returns pgd itself */
set_pmd(pmd, __pmd(phys_addr
| pgprot_val( __pgprot(0x1e3))));
/* 0x1e3 == Present , Accessed ,Dirty, Read/Write, Page Size, Global */
phys_addr
+= PTRS_PER_PTE * PAGE_SIZE; /* 0x400000 */
++pgd;
}


开启PAE(Physical Address Extending)或物理内存大于4GB时,kernel重初始化内核页表的过程。(此时为3级分页PGD->PMD->PTE->PF),在这种情况下,PTE与PF寻址位数为9+12=21,即此时LINUX内核使用2MB大小的页面。此模式下,PDG共4项,其中内核占第三项,PMG共512项,总计内核寻址空间为512*2MB = 1GB

 

pgd_idx = pgd_index(PAGE_OFFSET); /* 3 */
for (i=0; i<pdg_idx; i++)
set_pgd(swapper_pg_dir
+ i , __pgd( __pa(empty_zero_page) | 0x001) );
/* 0x001 == Present */
pgd
= swapper_pg_dir + pgd_idx;
phys_addr
= 0x00000000;
for( ; i<PTRS_PER_PGD; ++i , ++pgd) {
pmd
= (pmd_t*) alloc_bootmem_low_pages(PAGE_SIZE);
set_pgd(pgd, __pa(pmd)
| 0x001); /* 0x001 == Present */
if( phys_addr < max_low_pfn * PAGE_SIZE)
for(j=0; j<PTRS_PER_PMD && hys_addr < max_low_pfn * PAGE_SIZE; ++j) {
set_pmd(pmd, __pmd(phys_addr
| pgprot_val(__pgprot(0x1e3))));
/* 0x1e3 == Present , Accessed ,Dirty, Read/Write, Page Size, Global */
phys_addr
+= PTRS_PER_PMD * PAGE_SIZE;
}
}
swapper_pg_dir[
0] = swapper_pg_dir[pgd_idx];




one_md_table_init()

直接返回pgd所指向的页目录表项

static pmd_t * __init one_md_table_init(pgd_t *pgd)
{
    pud_t *pud;
    pmd_t *pmd_table;
#ifdef CONFIG_X86_PAE
    pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); 
    set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); 
    pud = pud_offset(pgd, 0);
    if (pmd_table != pmd_offset(pud, 0))
        BUG();
#else


pmd_table和pgd指向同一个页目录项
|-------------------------------------|
|   pud = 
pud_offset(pgd, 0);         |
|   pmd_table = 
pmd_offset(pud, 0);   |
|-------------------------------------|

#endif
    return pmd_table;
}

#define pud_offset(pgd, start)      (pgd)
static inline pmd_t * pmd_offset(pud_t * pud, unsigned long address)
{           
   
return (pmd_t *)pud;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值