首先有如下定义
* r8 = machinfo
* r9 = cpuid
* r10 = procinfo
一、在arch/arm/kernel/head.S中 create_page_table
214 .type __create_page_tables, %function
在arch/arm/kernel/head.S中定义了pgtbl宏
0x30008000-0x4000=0x30004000
附录:
1. macro指令格式如下:
.macro //定义一个宏: 名字是macro_name; 参数是macro_param
body
.endm //endm结束标志
include/asm/memory.h中
#define PAGE_OFFSET UL(0xc0000000)
此时寄存器如下:
#define PAGE_OFFSET UL(0xc0000000)
arch/arm/Makefile
TEXT_OFFSET=0x00008000 // 95 textofs-y := 0x00008000 //153 TEXT_OFFSET := $(textofs-y)
- include/asm-arm/arch-s3c2410/memory.h
- 14 #define PHYS_OFFSET UL(0x30000000)
-
- arch/arm/kernel/head.S中
- 29 #define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET) //0xc0008000 //3G都说内核的虚地址是3G,就是这么来的
- 30 #define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET) //0x30008000
- 55 #define KERNEL_START KERNEL_RAM_VADDR //0xc0008000
56 #define KERNEL_END _end
* r8 = machinfo
* r9 = cpuid
* r10 = procinfo
一、在arch/arm/kernel/head.S中 create_page_table
214 .type __create_page_tables, %function
- 215 __create_page_tables:
- 216 pgtbl r4 @ page table address //将页表基地址(0x30004000)存入r4中
- 217
- 218 /*
- 219 * Clear the 16K level 1 swapper page table //L221-L229:将页表基地址到页表结束地址(0x30004000--0x30008000)清零
- 220 */
- 221 mov r0, r4
- 222 mov r3, #0
- 223 add r6, r0, #0x4000
- 224 1: str r3, [r0], #4
- 225 str r3, [r0], #4
- 226 str r3, [r0], #4
- 227 str r3, [r0], #4
- 228 teq r0, r6
- 229 bne 1b
- 230 //L231-L241 配置内核页表项,寄存器:r3=0x0, r4=页表基地址(0x30004000), r6,r7临时变量
231 ldr r7, [r10, #PROCINFO_MM_MMUFLAGS] @ mm_mmuflags //L231 从proc_info中得到的页表项的标志赋给r7,标志在arch/arm/mm/proc-arm920.S中
- 239 mov r6, pc, lsr #20 @ start of kernel section //L232 pc>>20即pc/1M(每个页表项表示了1M的内存空间), pc/1M的结果表示了:内核地址是在页表(数组)中的第几项(索引)
240 orr r3, r7, r6, lsl #20 @ flags + kernel base //L240 r7是页表项的标志位, r6是页表项的基地址,将r6与r7合并组成了一个完整的页表项r3
241 str r3, [r4, r6, lsl #2] @ identity mapping //L241 r4是页表基地址,r6是页表(数组)中的索引,因为每一个页表项是4字节,所以内核所在的页表地址是: r4+r6*4 - //L241 即0x30004000+0x300*4=0x30004C00, 把完整的页表项的内容r3存到r4+r6*4(0x30004C00)处
242
243 /*
244 * Now setup the pagetables for our kernel direct
245 * mapped region.
246 */ //L247-248 填充虚拟内核页表(0xc0008000)的第0项; L249-L255填充剩余的所有虚拟页表项
247 add r0, r4, #(KERNEL_START & 0xff000000) >> 18 //L247 将KERNEL_START=0xc0008000映射到r0=r4+offset=0x30007000
248 str r3, [r0, #(KERNEL_START & 0x00f00000) >> 18]! //L248 将页表项的内容r3存到0x30007000处(KERNEL_START&0x00F00000为0),映射完第0项
249 ldr r6, =(KERNEL_END - 1) //L249 KERNEL的结束地址存入r6
250 add r0, r0, #4 //L250 r0=r0+4即r0指向下一个页表项
251 add r6, r4, r6, lsr #18 //L251 r6=r4+r6 即r6内核页表项的结束地址
252 1: cmp r0, r6 //L252-L255 循环: 比较是否己到结束地址,将内核页表项的4字节填充
253 add r3, r3, #1 << 20 //L253 1个页表项代表了1M内存,当填充下一个页表项时刚好需要填充在页表项的第20位,所以这儿只需将bit2加1即可
254 strls r3, [r0], #4 //L254 将更新后的内容填充到页表项地址中
255 bls 1b //L255
256
.....
275
276 /*
277 * Then map first 1MB of ram in case it contains our boot params.
278 */
279 add r0, r4, #PAGE_OFFSET >> 18 //L279 PAGE_OFFSET=0xc000000,r0即PAGE_OFFSET所在页表项的地址
280 orr r6, r7, #(PHYS_OFFSET & 0xff000000) //L280-284填充,原理同上
281 .if (PHYS_OFFSET & 0x00f00000)
282 orr r6, r6, #(PHYS_OFFSET & 0x00f00000)
283 .endif
284 str r6, [r0]
285
...
327 mov pc, lr
328 .ltorg
在arch/arm/kernel/head.S中定义了pgtbl宏
- 47 .macro pgtbl, rd
- 48 ldr \rd, =(KERNEL_RAM_PADDR - 0x4000)
- 49 .endm
附录:
1. macro指令格式如下:
.macro //定义一个宏: 名字是macro_name; 参数是macro_param
body
.endm //endm结束标志