Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2108198
  • 博文数量: 333
  • 博客积分: 10161
  • 博客等级: 上将
  • 技术积分: 5238
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-19 08:59
文章分类

全部博文(333)

文章存档

2017年(10)

2014年(2)

2013年(57)

2012年(64)

2011年(76)

2010年(84)

2009年(3)

2008年(37)

分类: LINUX

2013-07-05 15:52:35

内核维持着一组自己使用的页表,驻留在主内核全局目录中,主内核页全局目录的最高目录项部分作为参考模型,为系统中每个普通进程对应的页全局目录项提供参考模型(进程的内核态从oxc0000000-----oxffffffff的线性地址!)

   内核页表的初始化化分为2个阶段:

   第一阶段:在还未启动分页机制下初始化化一个寻址范围在0---8M的内核页表,这个最小限度的地址空间仅能内核装载到RAM和对其初始化核心数据结构。该部分是由startup_32()汇编语言函数实现的(arch/i386/kernel/head.s)以下是startup_32中初始化内核页表的代码片段及其解析:

              page_pde_offset = (__PAGE_OFFSET >> 20);

              movl $(pg0 - __PAGE_OFFSET), %edi
              movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
              movl $0x007, %eax   /* 0x007 = PRESENT+RW+USER */
            10:  /*初始化页目录表*/
               leal 0x007(%edi),%ecx   /* Create PDE entry */
               movl %ecx,(%edx)   /* Store identity PDE entry */
               movl %ecx,page_pde_offset(%edx)  /* Store kernel PDE entry */
               addl $4,%edx
               movl $1024, %ecx   /*设置循环次数*/
           11:              /*初始化页表*/
               stosl
               addl $0x1000,%eax
               loop 11b
              /* End condition: we must map up to and including INIT_MAP_BEYOND_END */
              /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */
               leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp
               cmpl %ebp,%eax
               jb 10b
               movl %edi,(init_pg_tables_end - __PAGE_OFFSET) /* 此时的edi中存放pg0+0x2000,将此值存入init_pg_tables_end中,表示页表初始化结束 */

 

            .......................................................

 

                   /*
                     * Enable paging              启用分页机制
                   */
                  movl $swapper_pg_dir-__PAGE_OFFSET,%eax
                  movl %eax,%cr3  /* set the page table pointer.. */
                  movl %cr0,%eax
                  orl $0x80000000,%eax
                  movl %eax,%cr0  /* ..and set paging (PG) bit */

    注意代码中的子针变量都减去一个线性偏移_PAGE_OFFSET。这是因为在编译内核时。这些变量引用的是启用分页后线性空间的地址。所以为得到实际的物理地址应减去这个线性偏移量。

 

第二阶段:初始化最终内核页表,注意此时分页机制已启动。初始化使得从oxc0000000开始的线性地址转化为从0开始的物理地址。

初始化发生在paging_init()函数中,而该函数位于setup_arch()中,而setup_arch()在start_kernel函数中被调用。

   paging_init()函数执行步骤:

   1:调用pagetable_init建立内核页表;

   2:把swapper_pg_dir的物理地址写道cr3寄存器中;

   3:根据CPU能力及编译内核时的配置,正确的设置cr4的PAE标志位;

   4:调用__flush_tlb_all使得TLB(转换后援缓冲器)的所用项无效。

重点来看pagetable_init函数:

    该函数首先获得页全局目录的线性地址,然后将其传入kernel_physical_mapping_init函数,该函数最终建立线性地址到物理地址的线性映射关系。kernel_physical_mapping_init代码及解析如下:

    static void __init kernel_physical_mapping_init(pgd_t *pgd_base)
{
 unsigned long pfn;
 pgd_t *pgd;
 pmd_t *pmd;
 pte_t *pte;
 int pgd_idx, pmd_idx, pte_ofs;

 pgd_idx = pgd_index(PAGE_OFFSET);
 pgd = pgd_base + pgd_idx;
 pfn = 0;

 for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
  pmd = one_md_table_init(pgd);
  if (pfn >= max_low_pfn)
   continue;
  for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
   unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;

   /* Map with big pages if possible, otherwise create normal page tables. */
   if (cpu_has_pse) {
    unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;

    if (is_kernel_text(address) || is_kernel_text(address2))
     set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
    else
     set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
    pfn += PTRS_PER_PTE;
   } else {
    pte = one_page_table_init(pmd);

    for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++) {
      if (is_kernel_text(address))
       set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
      else
       set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
    }
   }
  }
 }
}

调用结束后还要初始化固定地址映射的线性地址页表代码如下:

              vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;    //将固定地址映射页表放在页全局目录的1023项(最后一项)
              page_table_range_init(vaddr, 0, pgd_base);  

最后为了初始化高地址内存而调用permanent_kmaps_init方法。

阅读(3358) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~