Chinaunix首页 | 论坛 | 博客
  • 博客访问: 545218
  • 博文数量: 183
  • 博客积分: 2650
  • 博客等级: 少校
  • 技术积分: 1427
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-22 17:02
文章分类
文章存档

2017年(1)

2015年(46)

2014年(4)

2013年(8)

2012年(2)

2011年(27)

2010年(35)

2009年(60)

分类: LINUX

2010-03-05 21:14:40

内核页目录的初始化 
 
/* swapper_pg_dir is the main page directory, address 0x00101000*/ 
 
>> 内核页目录,第0,1项和第768、767项均为映射到物理内存0-8M的页目录项 
>> 其页表的物理地址是0x00102000和0x00103000,即下面的pg0和pg1所在的位置 
>> (在启动的时候,将内核映像移到0x0010000处)。 
>> 之所以第0,1项与第768和767相同,是因为在开启分页前的线性地址0-8M和开启 
>> 分页之后的3G-3G+8M均映射到相同的物理地址0-8M 
 
/* 
 * This is initialized to create an identity-mapping at 0-8M (for bootup 
 * purposes) and another mapping of the 0-8M area at virtual address 
 * PAGE_OFFSET. 
 */ 
.org 0x1000 
ENTRY(swapper_pg_dir) 
 .long 0x00102007 
 .long 0x00103007 
 .fill BOOT_USER_PGD_PTRS-2,4,0 
 /* default: 766 entries */ 
 .long 0x00102007 
 .long 0x00103007 
 /* default: 254 entries */ 
 .fill BOOT_KERNEL_PGD_PTRS-2,4,0 
 
/* 
 * The page tables are initialized to only 8MB here - the final page 
 * tables are set up later depending on memory size. 
 */ 
>> 下面为物理地址0-8M的页表项 
>> 从0x4000到0x2000共2k个页表项,映射0-8M的物理内存 
 
.org 0x2000 
ENTRY(pg0) 
 
.org 0x3000 
ENTRY(pg1) 
 
/* 
 * empty_zero_page must immediately follow the page tables ! (The 
 * initialization loop counts until empty_zero_page) 
 */ 
 
.org 0x4000 
ENTRY(empty_zero_page) 
 
>> 进程0的页目录指向swapper_pg_dir 
#define INIT_MM(name) \ 
{        \ 
 mmap:  &init_mmap,    \ 
 mmap_avl: NULL,     \ 
 mmap_cache: NULL,     \ 
 pgd:  swapper_pg_dir,   \ 
 mm_users: ATOMIC_INIT(2),   \ 
 mm_count: ATOMIC_INIT(1),   \ 
 map_count: 1,     \ 
 mmap_sem: __RWSEM_INITIALIZER(name.mmap_sem), \ 
 page_table_lock: SPIN_LOCK_UNLOCKED,   \ 
 mmlist:  LIST_HEAD_INIT(name.mmlist), \ 

 
/* 
 * paging_init() sets up the page tables - note that the first 8MB are 
 * already mapped by head.S. 
 * 
 * This routines also unmaps the page at virtual kernel address 0, so 
 * that we can trap those pesky NULL-reference errors in the kernel. 
 */ 
void __init paging_init(void) 

 pagetable_init(); 
 
 __asm__( "movl %%ecx,%%cr3\n" ::"c"(__pa(swapper_pg_dir))); 
  
 。。。。。。。。。。。 

 
 
static void __init pagetable_init (void) 

 unsigned long vaddr, end; 
 pgd_t *pgd, *pgd_base; 
 int i, j, k; 
 pmd_t *pmd; 
 pte_t *pte, *pte_base; 
 
>> end虚拟空间的最大值(最大物理内存+3G) 
 /* 
  * This can be zero as well - no problem, in that case we exit 
  * the loops anyway due to the PTRS_PER_* conditions. 
  */ 
 end = (unsigned long)__va(max_low_pfn*PAGE_SIZE); 
 
 pgd_base = swapper_pg_dir; 
#if CONFIG_X86_PAE 
 for (i = 0; i < PTRS_PER_PGD; i++) 
  set_pgd(pgd_base + i, __pgd(1 + __pa(empty_zero_page))); 
#endif 
>> 内核起始虚拟空间在内核页目录表中的索引 
 i = __pgd_offset(PAGE_OFFSET); 
 pgd = pgd_base + i; 
 
>> #define PTRS_PER_PGD 1024 
>> 对页目录的从768项开始的每一项 
 for (; i < PTRS_PER_PGD; pgd++, i++) { 
>> vaddr为第i项页目录项所映射的内核空间的起始虚拟地址,PGDIR_SIZE=4M 
  vaddr = i*PGDIR_SIZE; 
  if (end && (vaddr >= end)) 
   break; 
#if CONFIG_X86_PAE 
  pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); 
  set_pgd(pgd, __pgd(__pa(pmd) + 0x1)); 
#else 
>> 对两级映射机制,pmd实际上是pgd 
  pmd = (pmd_t *)pgd; 
#endif 
  if (pmd != pmd_offset(pgd, 0)) 
   BUG(); 
 
  for (j = 0; j < PTRS_PER_PMD; pmd++, j++) { 
   vaddr = i*PGDIR_SIZE + j*PMD_SIZE; 
   if (end && (vaddr >= end)) 
    break; 
>> 假如内核不支持 Page Size Extensions  
   if (cpu_has_pse) { 
   。。。。。。。。。。 
   } 
>> 分配内核页表 
   pte_base = pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); 
>> 对每一项页表项 
   for (k = 0; k < PTRS_PER_PTE; pte++, k++) { 
    vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE; 
    if (end && (vaddr >= end)) 
     break; 
>> 将页面的物理地址填入页表项中 
    *pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL); 
   } 
>> 将页表的物理地址填入到页目录项中 
   set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte_base))); 
   if (pte_base != pte_offset(pmd, 0)) 
    BUG(); 
 
  } 
 } 
 
 /* 
  * Fixed mappings, only the page table structure has to be 
  * created - mappings will be set by set_fixmap(): 
  */ 
 vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK; 
 fixrange_init(vaddr, 0, pgd_base); 
 
#if CONFIG_HIGHMEM 
 。。。。。。。。。。。。 
#endif 
 
#if CONFIG_X86_PAE 
 。。。。。。。。。。。。 
#endif 
}
阅读(707) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~