映射表(PGD)从虚拟地址0xc0004000开始,每项4字节,每项对应1M内存空间,每项的高12位就是这1M内存的高12位地址。
一开始,内核不会为所有内存建立映射,只会映射必要的一部分,这部分代码在arch/arm/kernel/head.S中由汇编代码完成。
以
S3C6410为例,下面是在刚刚进入start_kernel()后打印出来的一段内核映射表。注意内核自身的映射表项是从0xc0007000地址开
始。因为从0xc0004000开始的是整个4G空间的表,内核内存只占最高的那1G,所以要加一个偏移量:3G/1M * 4bytes =
0×3000。
2、__create_page_table中的
add r0,r4,#(KERNEL_START & 0xff000000)>>18
str r3,[r0,#(KERNEL_START & 0x00f00000) >> 18]!
这样分开写是由于arm 的立即数只能是8位表示。
3、也表中映射两个地址,一个是物理地址求出来的,一个是虚拟地址求出起来的!
add r0, r4, #(KERNEL_START & 0xff000000) >> 18
str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]!
KERNEL_START在文件的前面定义,为KERNEL_RAM_VADDR,即内核的虚拟地址。
而KERNEL_RAM_VADDR在文件的前面定义为(PAGE_OFFSET + TEXT_OFFSET)映射完整
的内核代码段,初始化数据段。PAGE_OFFSET为内核镜像开始的虚拟地址,
在arch/arm/include/asm/memory.h中定义。在配置内核时选定具体值,默认为0xC0000000。
因为最高12位的值是页表中的偏移地址,而第三高的四位必然为0,每个页表项为4字节,右移20位
之后,还得再左移两位回来,所以,这里只是左移18位。R3寄存器在经过了上面的操作之后,实际
上是变成了指向内核镜像代码段的指针(物理地址),在这个地方,再一次为内核镜像的第一个MB做了映射。R6随后指向了内核镜像的尾部。R0为页表项指针。这里以1MB为单位来映射内核镜像。
4、
r4 = pgtbl (page table 的物理基地址)
r8 = machine info (struct machine_desc的基地址)
r9 = cpu id (通过cp15协处理器获得的cpu id)
r10 = procinfo (struct proc_info_list的基地址)
阅读(826) | 评论(0) | 转发(0) |