; Zero out page tables & kernel data page
;初始化上面分配的物理内存KDataArea
mov r0, #0 ; (r0-r3) = 0's to store
mov r1, #0
mov r2, #0
mov r3, #0
mov r4, r10 ; (r4) = first address to clear
add r5, r10, #KDEnd-PTs ; (r5) = last address + 1
18 stmia r4!, {r0-r3}
stmia r4!, {r0-r3}
cmp r4, r5
blo %B18
下面的代码是为在使能mmu前初始化内存映射表page table。前面说过ce目前的arm实现不仅利用了cpu的mmu功能,还使用了两种mmu映射方式:最高的1MB(0xFFF00000-0xFFFFFFFF),使用二级映射,并使用不同的page类型;而其余地址空间,只使用一级映射。所以内存映射表的初始化也分为两步。这两步没有什么先后顺序,ce是先初始化二级映射,为了叙述方便这里先解释一级映射。注意这里的一级映射意思是虚拟地址只通过一次内存映射表的转换就能映射到对应的物理地址,而不是二级映射中的第一级映射的意思。如果是后者,将使用“第一级映射”加以区分。
另外有必要首先对一级映射加以解释。参考一级映射的示意图,Translation table base保存一级映射的内存映射表的物理地址,在这里也就是PTs,这个地址是16k对齐的,保存在CP15的寄存器c2中。给定一个虚拟地址vaddr,右移20bit后再左移2bit,作为内存映射表pt的索引(之所以要再左移2bit,是因为PTs保存一个地址需要4个byte),此时pt+(vaddr>>20)<<2就是该虚拟地址对应的一级映射描述符的物理地址,而pt[(vaddr>>20)<<2]就是该虚拟地址对应的一级映射描述符,最后vaddr对应的物理地址就是pt[(vaddr>>20)<<2]&0xfff00000+vaddr&0x000fffff。由此可见这种映射方式,一个描述符对应1M的物理空间。而pt[(vaddr>>20)<<2]的值,也就是一级映射描述符,是在下面初始化的。
; Fill in first level page table entries to create "un-mapped" regions
; from the contents of the MemoryMap array.
;
; (r9) = ptr to KData page
; (r10) = ptr to 1st level page table
; (r11) = ptr to MemoryMap array
;内核只初始化高2g的内核空间,低2g的用户空间的内存是在用户空间的程序运行时分配的,这里不必初始化。
;r10之前保存了PTs的物理地址,也就是一级映射的内存映射表的物理地址,要跳过(2g/1M)*4=0x2000,才能指向内核空间的起始地址0x80000000。
add r10, r10, #0x2000 ; (r10) = ptr to 1st PTE for "unmapped space"
;高2g空间又分为两部分,分别是0x80000000-0x9fffffff的cached和writebuffer空间(C+B),和0xa00000000-0xbfffffff的非cached和writebuffer空间(非C+B)。
;这两部分指向同一个物理空间,之所以要分成两个虚拟空间是系统需要。C+B空间用来进行高速的存储设备的访问,
;一般这种情况下不需要实时更新或读取具体的物理存储设备,所以高速的CPU不必等待具体的物理储存设备数据的更新或读取,
;而是采用writebuffer在其后写入,或读取以前保存在cache的数据。
;而非C+B用来访问物理寄存器或需要实时反应的设备,一般的寄存器访问都需要这种方式。
;所以ce为了区分这两种情况,采用了两个独立的虚拟内存空间的方法,需要分别初始化内存映射表。
;r7保存这个初始化的次数。首先初始化C+B空间的内存映射表。
mov r7, #2 ; (r7) = pass counter
;下面是构造一个一级映射描述符。参考一级映射示意图,对于一级映射要求描述符最后两个bit是二进制10,所以r0=0x02;
;r2之前被赋值为0x0c,即二进制1100,,意味着C和B被置位;
;参考文档2,0x400意味着通过该描述符访问对应的1M物理内存时,内核有读写权限,用户无访问权限;
;注意,这并不是意味着该内存地址用户是无法访问的,因为内核可以把该物理地址映射其它的用户可访问的虚拟地址。
mov r0, #0x02
orr r0, r0, r2 ; (r0)=PTE for 0: 1MB (C+B as set by OEM)
orr r0, r0, #0x400 ; set kernel r/w permission
20 mov r1, r11 ; (r1) = ptr to MemoryMap array
;r2,r3和r4分别保存g_oalAddressTable某一项的虚拟地址,物理地址和映射的大小(M)。
;例如,对应上面的g_oalAddressTable,r2=0x80000000, r3=0xA0000000, r4=64。
25 ldr r2, [r1], #4 ; (r2) = virtual address to map Bank at
ldr r3, [r1], #4 ; (r3) = physical address to map from
ldr r4, [r1], #4 ; (r4) = num MB to map
;最后一项全为0,由此可知是否遍历了该数组。
cmp r4, #0 ; End of table?
beq %F29
http://hi.baidu.com/garnetttt/blog/item/7860349b7bfcccb6c8eaf47b.html