u-boot对系统寄存器进行初始化代码

描述

在完成地址无关fixup后,u-boot开始对一些系统寄存器进行初始化。

第一段代码如下:

pie_fixup_done:
#endif

#ifdef CONFIG_SYS_RESET_SCTRL
    bl reset_sctrl --------------------------------------------------------------------- (1)
#endif

#if defined(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD) ---------- (2)
.macro set_vbar, regname, reg
    msr regname, reg
.endm
    adr x0, vectors
#else
.macro set_vbar, regname, reg
.endm
#endif
    /*
     * Could be EL3/EL2/EL1, Initial State:
     * Little Endian, MMU Disabled, i/dCache Disabled
     */
    switch_el x1, 3f, 2f, 1f ---------------------------------------------------------- (3)
3: set_vbar vbar_el3, x0
    mrs x0, scr_el3
    orr x0, x0, #0xf   /* SCR_EL3.NS|IRQ|FIQ|EA */
    msr scr_el3, x0
    msr cptr_el3, xzr   /* Enable FP/SIMD */
    b 0f
2: mrs x1, hcr_el2
    tbnz x1, #34, 1f   /* HCR_EL2.E2H */
    set_vbar vbar_el2, x0
    mov x0, #0x33ff
    msr cptr_el2, x0   /* Enable FP/SIMD */
    b 0f
1: set_vbar vbar_el1, x0
    mov x0, #3 < < 20
    msr cpacr_el1, x0   /* Enable FP/SIMD */
0:

#ifdef COUNTER_FREQUENCY -------------------------------------------------------------- (4)
    branch_if_not_highest_el x0, 4f
    ldr x0, =COUNTER_FREQUENCY
    msr cntfrq_el0, x0   /* Initialize CNTFRQ */
#endif

4: isb ------------------------------------------------------------------------------- (5)

...
...
#ifdef CONFIG_SYS_RESET_SCTRL
reset_sctrl:
    switch_el x1, 3f, 2f, 1f
3:
    mrs x0, sctlr_el3
    b 0f
2:
    mrs x0, sctlr_el2
    b 0f
1:
    mrs x0, sctlr_el1

0:
    ldr x1, =0xfdfffffa
    and x0, x0, x1

    switch_el x1, 6f, 5f, 4f
6:
    msr sctlr_el3, x0
    b 7f
5:
    msr sctlr_el2, x0
    b 7f
4:
    msr sctlr_el1, x0

7:
    dsb sy
    isb
    b __asm_invalidate_tlb_all ----------------------------------------------------- (6)
    ret
#endif
  • • (1)一般情况下此功能不需要使用,但是一些由其他固件引导启动的u-boot,board希望系统行为能按照自己预期行为执行而不受上一级加载器的影响,所以使用CONFIG_SYS_RESET_SCTRL来决定是否重置系统控制寄存器,包括保证处理器处于小端,关闭data cache,关闭mmu。 其中switch_el是一个宏,用于读取当前所处的异常级别,根据所处异常级别调用对应的系统控制寄存器。某些时候u-boot的加载并不是一定在el3级别,当存在atf等时,el3由atf控制,atf会将u-boot的运行级别切换到el2,以便保证自己的控制级别,所以u-boot通过switch_el来选择自己能够控制的系统寄存器。
  • • (2)定义设置异常向量表的宏,将异常向量表的地址写入/reg设置的系统寄存器即可完成异常向量表的设置,这里u-boot是需要设置异常向量表的,而spl默认是不需要设置异常向量表的,毕竟spl只是一个加载器只会运行一次,不过当定义了CONFIG_ARMV8_SPL_EXCEPTION_VECTORS时可以为spl也设置一个异常向量表。
  • • (3)同样的使用switch_el来跳转到对应级别的路径上去执行,在进行系统寄存器设置时,因为在这之前已经由SYS_RESET_SCTRL或者board自己保证处理器处于小端,mmu关,i-cache和d-cache处于关闭状态了,所以这里直接进行对应级别系统寄存器设置,首先是跳转到对应表设置对应级别的异常向量表。接着会有如下三种情况: 当处于EL3时,会设置安全配置系统寄存器(scr_el3),会将低四位bit设置为0xf,表示设置处理器处于非安全模式,任何级别的物理irq中断,物理fiq,异常abort中断,异常SError中断都将被路由到el3级别。后续这些设置将在启动Linux时被修改,这些设置仅用于在u-boot阶段。接着将cptr_el3清零,使用xzr是可以快速操作寄存器为零。这里保证任何级别下访问SIMD和floating-point指令不会导致触发异常陷入el3。 当处于EL2时,首先根据HCR_EL2.E2H判断系统是一个虚拟机管理器还是主机系统,当E2H = 0时,表示系统处于主机系统只需要做el3一样的操作配置SIMD和FP指令不会陷入el2即可。 当系统处于EL1时,则什么也不需要操作只需要配置SIMD和FP指令不会陷入el1。
  • • (4)u-boot在启动时系统的时钟频率不一定配置了,所以当在include/configs/xxxxxx.h中定义了COUNTER_FREQUENCY的频率值时,说明需要在此处配置系统时钟,所以根据宏 branch_if_not_highest_el判断当系统不处于EL3时则需要设置系统的时钟工作频率cntfrq_el0,后续Linux或者u-boot根据读出的这个值计算出系统每纳秒的滴答数从而供软件获取时间流逝值。
  • • (5)isb指令用于确保上述操作指令被正确真正的执行了,属于同步指令的一种。
  • • (6)在进行系统控制器复位时,dsb sy,isb,__asm_invalidate_tlb_all三个操作在这里的意义是,因为对处理器的小端,mmu,d-cache进行了复位,所以这里必须通过dsb和isb确保数据和指令全部执行和写入,这里进行了mmu和cache关闭操作,那么如果有缓存的tlb在这个时候这些缓存的tlb数据就是无效的,这里对可能缓存的tlb进行全部无效化,确保后续任何可能的mmu开启操作不会使用到这些无用的tlb条目而导致系统异常。
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分