linux頁表機制的建立分為兩個階段,第一個階段在啟動初始化時,調用匯編代碼實現臨時的分頁;第二階段在內核初始化時建立完整的完整的頁表機制。對於物理地址擴展(PAE)分頁機制中,intel通過在她得處理器上把管腳數從32增加到36已經滿足了這些需求,尋址能力可以達到64GB。不過,只有引入一種新的分頁機制把32位線性地址轉換為36位物理地址才能使用所增加的物理地址。linux為對多種體系的支持,選擇了一套簡單的通用實現機制。在這裡,只分析x86 32位下的實現。
下圖為一個linux分頁機制框架圖:
一、臨時內核頁表初始化
在setup_32.S中
[cpp]
- page_pde_offset = (__PAGE_OFFSET >> 20);
-
- movl $pa(__brk_base), %edi
- movl $pa(swapper_pg_dir), %edx
- movl $PTE_IDENT_ATTR, %eax
- 10:
- leal PDE_IDENT_ATTR(%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 the end + MAPPING_BEYOND_END.
- */
- movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
- cmpl %ebp,%eax
- jb 10b
- addl $__PAGE_OFFSET, %edi
- movl %edi, pa(_brk_end)
- shrl $12, %eax
- movl %eax, pa(max_pfn_mapped)
-
- /* Do early initialization of the fixmap area */
- movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax
- movl %eax,pa(swapper_pg_dir+0xffc)
對於頁表初始化的原理如果可以參考intel手冊。
其中常量PTE_IDENT_ATTR定義在patable_types.h中。
[cpp]
- #define PTE_IDENT_ATTR 0x003 /* PRESENT+RW */
二、啟動分頁機制
實現代碼在head_32.S中。
[cpp]
- movl $pa(swapper_pg_dir),%eax
- movl %eax,%cr3 /* set the page table pointer.. */
- movl %cr0,%eax
- orl $X86_CR0_PG,%eax
- movl %eax,%cr0 /* ..and set paging (PG) bit */