请看 head.S 中这段代码:
/*
* Initialize page tables
*/
movl $pg0-__PAGE_OFFSET,%edi /* initialize page tables */
movl $007,%eax /* "007" doesn't mean with right to kill, but
PRESENT+RW+USER */
2: stosl
add $0x1000,%eax
cmp $empty_zero_page-__PAGE_OFFSET,%edi
jne 2b
在做页表了:从pg0~empty_zero_page来8k来做映射c0000000~c0000000+8m的虚拟空间到物理空间
0~8m,内核解压后+初始化到还没建立完整页目录页表前要用的ram是小于7m的,所以现在建个8m的
页表就行了。
/*
页表项是这样的一个32位结构:
31 12 11 9 8 7 6 5 4 3 2 1 0
| 物理页基地址| |...........|u/s|r/w|p 所以007是指基地址为0最后3为置位。
通过循环下边4条语句,把一个管理8m内存的页表给建起来了。 结果为:
页表项物理地址 页表项的值 对应的物理空间
0x102000 0x007 0~4k
0x102004 0x1007 8~16k
.
.
.
0x104000 0x2000007 8m-4k~8m
*/
2: stosl
add $0x1000,%eax
cmp $empty_zero_page-__PAGE_OFFSET,%edi /*empty_zero_page-__PAGE_OFFSET=0x104000*/
jne 2b //如果还没到empty_zero_page那个物理地址,就跳回2继续stosl,add了
[引用网络上的一段解释:By default, the linux kernel image(or vmlinux elf file) will begin its TEXT starting at 0xC0100000(The 3G edege). This can be found from makfile and link script-vmlinux.lnk.
Corresponding the above setting, PAGE_OFFSET is also set with the value of 0xC0000000.
Now, let's go back to the pg0, which is the (temporary) **first** page table, which will cover first 4M virtual<-->physical memory. (1024x4K page size). Note that kernel 2.2 only use pg0, whereas kernel 2.4 alsu use pg1 to cover another 4M. In other words, kernel 2.4 cover 8M when system initialized and before the paging_init get executed.
From head.S, we can find: both swapper_page_dir , pg0 and pg1 data structurre(an array actually) is **hard coded** at ox1000,0x2000 and 0x3000, respectively.
At this point, we may use to figure out your question.
After compiled and linked, what the addresses of swapper_page_dir, pg0 and pg1 symbol? From the map file, we can easily find these below conclusions:
swapper_page_dir: 0xC0101000
pg0: 0xC0102000
pg1:0xC0103000.
//The above values are determined by linker scripts and the compiler
Now, you tell me what the value of $pg0-PAGE_OFFSET....:-)
Given that the kernel image will be loaded at **physical address of 1M-0x100000. Hence, we understand that $pg0-PAGE_OFFSET is the value of the physical address of the pg0 pointer.
]
我们知道,内核 image 的起始物理地址是 0x100000,而pg0 相对与 kernel image 的地址是 0x2000, pg1 是 0x3000, empty_zero_page 是 0x4000
这段代码要把 pg0 至 empty_zero_page 之间的共 8K 内存初始化。
初始化后,这 2048 项的内容是:
0x0007, 0x1007, 0x2007, 0x3007 .......
取这些 32 地址的高20位,将低12位设置为0,就得到了物理页面的其实地址,因此,pg0, pg1 映射的是 前8M的物理页面。
这里的低 3 bit 为 111,表示 PRESENT+RW+USER
再看 swapper_pg_dir 的第 0 项和第1项,分别是 0x00102007 和 0x00103007,其高 20 bit 正是指向 pg0 和 pg1的起始地址,至于低 3 bit 为 111,同样表示 PRESENT+RW+USER
请看附件我画的一张物理内存布局图