eboot startup.s中设置一级页表的详细过程

参考:http://blog.chinaunix.net/u1/38994/showart_1881778.html

         http://blog.csdn.net/alien75/archive/2009/12/07/4955156.aspx

 

这几天研究了一下MMU和Cache,小有所得,现在把设置一级页表的汇编文件做详细的整理和解释以便后续查看。

32位的的CPU虚拟内存为232次方=4G,一个页表描述符(页表项)对应1M的虚拟内存空间,则4G对应4096个一级页表项,一个页表项又占用4字节,需要4096×4=16K的物理内存用于存放一级页表。但bootloader没有必要完整的构造4096个页表项,只要够用就可以了。

startup所构造的页表先要覆盖0x80000000-0x9FFFFFFF(允许cache)的VA,容量为512M,对应512个页表项,所需存储空间是2K,即物理RAM地址为0x30012000-0x300127FF。而0xA0000000-0xBFFFFFFF(禁止cache)对应页表项占用的物理地址为0x30012800-0x30012FFF。

内存中存放页表项的起始地址为pagetablestart(PTS). 参考:http://blog.csdn.net/chinesedragon2010/archive/2010/08/08/5796534.aspx

每一个页表项pageentry(PTE)包含四个字节的数据。一级页表项如下图所示:

使用一级页表把VA转化成PA的过程是:

1.VA的31-20位为索引值,19-0位为偏移量。

2.CP15的C2寄存器31-14位(PTS)与索引值右移18位,后两位置0,组成一个物理地址就是页表项的物理地址

3.根据这个物理地址找到页表项

4.页表项的31-20位为段基地址,剩余二十位如上图所示。

5.VA对应的PA为段基地址与偏移量的结合。

PA= *((VA(31-20))>>18 + PTS) & 0xFFF0000 +VA(19-0)

蓝色标注部分为页表项。

按位与0xFFF0000的涵义在于取页表项的31-20位,即段基地址。

 

;   Define RAM space for the Page Tables:
;
PHYBASE  EQU  0x30000000   ; physical start  物理地址起始处
PTs   EQU  0x30010000   ; 1st level page table address (PHYBASE + 0x10000)  一级页表的起始地址

 

 ; Compute physical address of the OEMAddressTable.
20 add  r11, pc, #g_oalAddressTable - (. + 8)  g_oalAddressTable 的地址放到R0

ARM处理器是流水线结构的,允许指令预取。在CPU执行当前指令的同时,可以从存储器中预取指令,所以当用户读取PC时,PC指向的是正在取指的指令,而非当前执行的指令,在ARM中,一般是当前执行指令下面的第2条指令(+8个字节)。所以这里的+8就不难理解了。

.是指当前指针,而.=pc-8; pc+g_oalAddressTable - (. + 8) =g_oalAdressTable. 

参考:http://topic.csdn.net/u/20070122/16/fc8ec835-e373-41d2-885e-6360348d58b2.html

 

ldr  r10, =PTs  ; (r10) = 1st level page table


 ; Setup 1st level page table (using section descriptor) 
 ; Fill in first level page table entries to create "un-mapped" regions
 ; from the contents of the MemoryMap array.
 ;
 ;   (r10) = 1st level page table
 ;   (r11) = ptr to MemoryMap array

 add  r10, r10, #0x2000    ; (r10) = ptr to 1st PTE for "unmapped space" r10中存放0x80000000VA在PTR中对应的PA

PTs保存在物理内存中的地址是0x30010000 ,0x2000是什么意义呢?我们知道没有缓存的虚拟地址起始地址是0x80000000,那这个虚拟地址对应的物理地址是多少呢?根据VA映射到PA的规则,见下图:

从0x80000000中取出[31:20]位,也即0x800来左移2位之后为0x2000,这个就是上面这个值的来由)加上translation base(在这里是PTs),add  r10, r10, #0x2000这行语句的意义,执行这行语句之后r0=0x30012000,这就是计算了4G虚拟地址空间中从0x80000000地址开始的虚拟地址对应的物理起始地址是0x30012000,也就是section base address=0x30012000bootloader只使用一级页表见P32李大为的书

 

 mov  r0, #0x0E     ; (r0) = PTE for 0: 1MB cachable bufferable R0存放页表项 使能cache&write buffer
 orr  r0, r0, #0x400   ; set kernel r/w permission AP值
25 

mov  r1, r11   ; (r1) = ptr to MemoryMap array r1指向g_oalAddressTable 的指针

 
30 

 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

 cmp  r4, #0    ; End of table?
 beq  %f40

表示cachable地址0x80000000~0xa0000000映射MMU创建完毕,表结尾,前跳到40标号,创建对应的uncached映射MMU

 

 ldr  r5, =0x1FF00000
 and  r2, r2, r5    ; VA needs 512MB, 1MB aligned.  对va虚拟地址进行512M对齐

//也就是r2的上限值不能超过0x20000000即512M,因为r10现在指向1级映射表的0x80000000虚拟地址,
//又因为0x80000000+0x20000000=0xa0000000开始地址存放的是uncached地址,所以这里要做512M数据限制

 

 ldr  r5, =0xFFF00000
 and  r3, r3, r5    ; PA needs 4GB, 1MB aligned. 对pa物理地址进行4G对齐

 add  r2, r10, r2, LSR #18  VA右移18位再加上PTS(页表项的基地址)
 add  r0, r0, r3    ; (r0) = PTE for next physical page 获取下一个物理页的入口地址

35 

 str  r0, [r2], #4   //存到r2对应的PTR偏移中
 add  r0, r0, #0x00100000  ; (r0) = PTE for next physical page

//1M递增,因为1<<18=256K,而每一个PTE描述4k页,所以最终描述256k*4k=1M地址空间,一个页表项对应虚拟内存1M空间

 sub  r4, r4, #1    ; Decrement number of MB left
 cmp  r4, #0
 bne  %b35   ; Map next MB //遍历到该region结束

 

 bic  r0, r0, #0xF0000000  ; Clear Section Base Address Field
 bic  r0, r0, #0x0FF00000  ; Clear Section Base Address Field //清空页表项的31-20位,即段基地址
 b    %b30   ; Get next element            //继续创建oemaddrtab_cfg.inc描述的下一region,直到cachedVA对应的PTE全部完成
 //创建对应的0xa0000000开始的uncached映射MMU表
40 

 tst  r0, #8

//比较C高速缓存是否仍然置位,如果仍然置位了,那么说明还没有执行uncached创建,如果C位已经清0,那么说明,uncached循环也执行完毕了,所以跳回到25标号继续创建
 bic  r0, r0, #0x0C    ; clear cachable & bufferable bits in PTE //清除B写缓冲和C高速缓存

 add  r10, r10, #0x0800    ; (r10) = ptr to 1st PTE for "unmapped uncached space"

r10现在对应0xA0000000虚拟地址的PTR起始地址,因为原来r10为80000000,现在只需要再加上20000000就好了,hex(0x20000000>>18)为0x800,

//所以r10 = r10 + 0x800;之后r10指向了0xa0000000虚拟地址对应的PTR起始地址
 bne  %b25   ; go setup PTEs for uncached space

//ok,现在0x80000000 cachable空间和0xa0000000 uncached空间都已经创建完毕了
 sub  r10, r10, #0x3000    ; (r10) = restore address of 1st level page table

//该句好像有问题,不过还好后面用到r10之前,又对r10进行了重新赋值,所以也更说明,该句操作无意义

——————————————————————————————————————————————————从这里开始不怎么明白了,后续解决

//接下来为虚拟0地址建立cachable和uncached映射

 ; 1. Setup mmu to map (VA == 0) to (PA == 0x30000000).
 ; 1-1. cached area.
 ldr  r0, =PTs  ; PTE entry for VA = 0
 ldr  r1, =0x3000040E  ; cache/buffer/rw, PA base == 0x30000000//以C,B均开启的方式映射虚拟地址0到pa物理地址0x30000000
 str  r1, [r0]

 

 ; 1-2. uncached area.
 add  r0, r0, #0x0800  ; PTE entry for VA = 0x0200.0000 , uncached  //接下来的0x2000000虚拟地址被映射为虚拟0地址的uncached起始地址
 ldr  r1, =0x30000402  ; uncache/unbuffer/rw, base == 0x30000000//以C,B均不开启的方式映射虚拟地址0到pa物理地址0x30000000
 str  r1, [r0]

//经过上面设置可以看到
//虚拟地址0对应0x30000000的cachable
//虚拟地址0x2000000对应0x30000000的uncached.

 ; Comment:
 ; The following loop is to direct map RAM VA == PA. i.e.
 ;   VA == 0x30XXXXXX => PA == 0x30XXXXXX for S3C2400
 ; Fill in 8 entries to have a direct mapping for DRAM
 ;
 ldr  r10, =PTs     ; restore address of 1st level page table
 ldr  r0,  =PHYBASE//PHYBASE为0x30000000,将虚拟地址映射到相同的物理地址

 add  r10, r10, #(0x3000 / 4) ; (r10) = ptr to 1st PTE for 0x30000000//就是(0x30000000 >> 18

//现在r10指向了和DDR地址相等的PA地址对应的PTR地址处?????不明白

 add  r0, r0, #0x1E    ; 1MB cachable bufferable
 orr  r0, r0, #0x400   ; set kernel r/w permission
 mov  r1, #0
 mov  r3, #64

//映射64M空间,因为我们的物理DDR只有64M(见上面的oemaddrtab_cfg.inc表图),不能大于512,因为下面只支持到512次循环(r1为循环次数,每循环1次,创建1M空间映射表)

45 

 mov  r2, r1    ; (r2) = virtual address to map Bank at
 cmp  r2, #0x20000000:SHR:BANK_SHIFT //0x20000000>>20=512M,
 add  r2, r10, r2, LSL #BANK_SHIFT-18 //add r2, r10, r2, 4即r2 = r10 + r2*4;正好为PTR操作时的4字节对齐边界
 strlo    r0, [r2]  //如果还没有操作到512M,那么填充PTR,如果现在映射操作已经操作过了512M大小,那么忽略

 add  r0, r0, #0x00100000  ; (r0) = PTE for next physical page
 subs     r3, r3, #1
 add  r1, r1, #1
 bgt  %b45

 

 ldr  r10, =PTs     ; (r10) = restore address of 1st level page table

 ; The page tables and exception vectors are setup.
 ; Initialize the MMU and turn it on.
 mov  r1, #1
 mcr  p15, 0, r1, c3, c0, 0   ; setup access to domain 0
 mcr  p15, 0, r10, c2, c0, 0  将页表基地址存储在CP15的C2寄存器中

 mcr  p15, 0, r0, c8, c7, 0   ; flush I+D TLBs //flush所有MMU相关空间
 mrc     p15,0,r1,c1,c0,0
 
 orr  r1, r1, #0x0071   ; Enable: MMU //设置打开MMU标志到r1
 orr  r1, r1, #0x0004  ; Enable the cache //设置打开cache标志到r1


 ldr  r0, =VirtualStart //取出VirtualStart编译期间得到的虚拟地址值,在0x30038000~0x30038000+eboot_size之间

 cmp  r0, #0    ; make sure no stall on "mov pc,r0" below //执行该比较,使r0踏实的读入VirtualStart数值

 mcr  p15, 0, r1, c1, c0, 0 //将MMU设置标志写入p15协处理器,生效设置
 mov  pc, r0    ;  & jump to new virtual address //跳转过去,此刻之后MMU已经打开,所有允许操作的虚拟地址都在PLATFORM/SMDK2440A/Src/Inc/oemaddrtab_cfg.inc中定义

 nop


 ; MMU & caches now enabled.
 ;   (r10) = physcial address of 1st level page table
 ;
 VirtualStart

 mov  sp, #0x80000000 ; have to be modefied. refer oemaddrtab_cfg.inc, DonGo //设置栈空间,从这里来看,sp栈顶对应的DDR物理地址为0x30000000,然后向下生长,从boot.bib中

    /*

    ARGS     80020800  00000800  RESERVED
    RAM      80021000  0000B000  RAM   
    STACK    8002c000  0000A000  RESERVED 2c000+a000=36000,保留2000,即8K空间做EBOOT的SP栈空间
    EBOOT    80038000  00040000  RAMIMAGE
    BINFS    80080000  00021000  RESERVED

*/
 add  sp, sp, #0x30000 ; arbitrary initial super-page stack pointer

 

 b    main 跳转到MAIN函数


        ENTRY_END

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值