linux2.6.24文件路径arch/x86/kernel/head_32.S
汇编代码页表初始化部分:
page_pde_offset = (__PAGE_OFFSET >> 20);
default_entry:
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)
转为c:
#define INIT_MAP_BEYOND_END (128*1024)
__PAGE_OFFSET = 0xC0000000;
default_entry:
//0xC0000000>>22<<2=0xc00,线性地址右移22位为全局目录的索引,全局页目录的每一项大小为4字节,所以再左移2位,即乘4,就得到了索引的大小,即0xc00=768*4=3072
page_pde_offset = (__PAGE_OFFSET >> 20);
//计算页表的物理地址,pg0中为页表的线性地址
edi = pg0 - __PAGE_OFFSET;
//计算全局页目录的物理地址,swapper_pg_dir 的值是全局页目录的线性地址
edx = swapper_pg_dir - __PAGE_OFFSET;
//权限值,0111,设置读写权限
eax = 7;
10:
do{
//页表的物理地址加上权限值
ecx = edi + 7;
//将 页表的物理地址加上权限值 写入edx地址的内存中(int swapper_pg_dir[0]中)
*edx = ecx;
//将 页表的物理地址加上权限值 写入 edx地址+0xc00 地址的内存中,即写入int swapper_pg_dir[768]中
*(edx+page_pde_offset) = ecx;
//全局页目录一项大小为4,这里移动到下一项(int swapper_pg_dir[1])
edx += 4;
//初始化1024个页目录项,设置循环次数,1024=2^10,占10位
ecx = 1024;
11:
//将物理页帧地址存入int pg0[][1024]数组中,执行完后数组中内容为0x0007,0x1007...,0x3FF007
do
{
//将eax中的值存入页表物理地址,物理地址从0开始(物理页帧0的地址),pg0[][m] = 0x(m)007
*edi = eax;
//地址+4,下一表项地址pg0[][m+1]
edi += 4;
// 物理页帧地址+4096,即下一物理页帧的地址,4096=2^12,占12位
eax += 0x1000;
}while(--ecx);
//4*1024*n+128*1024+7
//ebp = &pg0[n] + 128*1024 + 7
ebp = edi + INIT_MAP_BEYOND_END + 7;
//baseaddr+4*1024*n+128*1024+7 > 4096*1024*n+7
//&pg0[n] + 128*1024 + 7 > 4096*1024*n+7
}while(ebp > eax);
//*init_pg_tables_end = &pg0[last]
*init_pg_tables_end = edi;