本文共 3720 字,大约阅读时间需要 12 分钟。
__setup_mmu: sub r3, r4, #16384 @ Page directory size,r3 = 0x20004000 bic r3, r3, #0xff @ Align the pointer bic r3, r3, #0x3f00@ 这里r4中存放着内核执行地址,将16K的一级页表放在这个内核执行地址下面的16K空间里,@ 上面通过 sub r3, r4, #16384 获得16K空间后,@ 又将页表的起始地址进行16K对齐放在r3中。即ttb的低14位清零。/* * Initialise the page tables, turning on the cacheable and bufferable * bits for the RAM area only. */ mov r0, r3 @ r0 = 0x20004000 mov r9, r0, lsr #18 @ r9 = 0x2000 mov r9, r9, lsl #18 @ start of RAM,r9 = 0x20000000,先>>18,后<<18,就是256K对齐 add r10, r9, #0x10000000 @ a reasonable RAM size,r10 = 0x30000000,0x10000000==256M@ 上面这几行把一级页表的起始地址保存在r0中,并通过r0获得一个ram起始地址(256K对齐),@ 并从这个起始地址开始的256M ram空间对应的描述符的C和B位均置”1”, @ r9和r10中存放了这段内存的起始地址和结束地址。 mov r1, #0x12 @ XN|U + section mapping@ 一级描述符的bit[1:0]为10,表示这是一个section描述符。@ bit[4]为1, @ 此时bit[8:5]均为0,选择了D0域。 orr r1, r1, #3 << 10 @ AP=11,r1 = 0xC12@ 一级描述符的AP(access permission bits) bit[11:10]为11, @ 即all access types permitted in both modes @ bit[31:20]为physical address,为0 add r2, r3, #16384 @ r2 = 0x20008000@ 一级描述符表(页表)的结束地址存放在r2中。1: cmp r1, r9 @ if virt > start of RAM cmphs r10, r1 @ && end of RAM > virt bic r1, r1, #0x1c @ clear XN|U + C + B orrlo r1, r1, #0x10 @ Set XN|U for non-RAM orrhs r1, r1, r6 @ set RAM section settings str r1, [r0], #4 @ 1:1 mapping add r1, r1, #1048576@ == 0x100000 = 1M teq r0, r2 @ r0==r2时,不在jump 1处执行,此时r1=4G=0 bne 1b/* case 1:1: cmp r1, r9 @ if virt > start of RAM cmphs r10, r1 @ && end of RAM > virt bic r1, r1, #0x1c @ clear XN|U + C + B orrlo r1, r1, #0x10 @ Set XN|U for non-RAM*//* case 2:1: cmp r1, r9 @ if virt > start of RAM bic r1, r1, #0x1c @ clear XN|U + C + B orrlo r1, r1, #0x10 @ Set XN|U for non-RAM*//* case 3:1: cmp r1, r9 @ if virt > start of RAM cmphs r10, r1 @ && end of RAM > virt bic r1, r1, #0x1c @ clear XN|U + C + B orrhs r1, r1, r6 @ set RAM section settings*/@ r1 &= ~0x1c @ 1->r1 |= 0x10@ r10 end 0x300000000@ 2->r1 |= r6,r1 |= 0x0d,在256M范围内@ r9 start 0x20000000 @ 3->r1 |= 0x10 @ 上面这段就是对一级描述符表(页表)的初始化,@ 首先比较这个描述符所描述的地址是否在那个256M的空间中,如果在则这个描述符对应的内存区域是 cacheable ,bufferable。@ 如果不在则noncacheable, nonbufferable。@ 然后将描述符写入一个一级描述符表(页表)的入口,并将一级描述符表(页表)入口地址加4,而指向下一个1M section的基地址。@ 如果页表入口未初始化完,则继续初始化。 @ 一级描述符结构如下:@ 31 20 19 12 11 10 9 8 5 4 3 2 1 0@ 物理地址的基址 0 AP 0 域 1 C B 1 0@ || 1:1映射@ || @ 0 <=> 0~(1M-1)@ 1 <=> 1M~(2M-1)@ 2 <=> 2M~(3M-1)@ 4095 <=> (4G-1M)~(4G-1)@ 一级描述符表(页表)的高12位是每个setcion的基地址,可以描述4096个section。@ 一级页表大小为16K,每个页表项,即描述符占4字节,刚好可以容纳4096个描述符,@ 所以这里就映射了4096*1M = 4G的空间。 /* * If ever we are running from Flash, then we surely want the cache * to be enabled also for our execution instance... We map 2MB of it * so there is no map overlap problem for up to 1 MB compressed kernel. * If the execution is in RAM then we would only be duplicating the above. *//**/ orr r1, r6, #0x04 @ ensure B is set for this orr r1, r1, #3 << 10@ 这两行是设置AP和B mov r2, pc mov r2, r2, lsr #20 orr r1, r1, r2, lsl #20@ 将当前地址1M对齐,并与r1中的内容结合形成一个描述当前指令所在section的描述符。 add r0, r3, r2, lsl #2@ r3为刚建立的一级描述符表(页表)的起始地址0x20004000。@ 将当前地址(pc)的高12位左移两位(形成14位索引)与r3中的地址 @ (低14位为0)相加形成一个4字节对齐的地址 @ 这个地址也在16K的一级描述符表(页表)内,r0的[31:14]为0,所以该地址<2^14=16K。@ 当前地址对应着描述符(貌似这就是一个一级描述符)在一级描述符表(页表)中的位置,这个位置之前已经初始化过了。@ 对于从ram中运行这里只是又重新设置了一次,从flash中运行,会多映射2MB@ 一级页表中索引为r2左移2位。@ r0地址结构如下:@ 31 14 13 2 1 0@ 页表基址 页表index 0 0@ r0里存储的描述符格式如下:@ 31 20 19 12 11 10 9 8 5 4 3 2 1 0@ PC高12bit 0 AP 0 域 1 C B 1 0 str r1, [r0], #4 add r1, r1, #1048576 str r1, [r0]@ 这里将上面形成的描述符及其连续的下一个section描述 @ 写入上面4字节对齐地址处 mov pc, lrENDPROC(__setup_mmu)
mcrne p15, 0, r3, c2, c0, 0 @ load page table pointer,r3 = 0x20004000
MMU的段页表的虚拟地址与物理地址的转换过程