RK3588的Uboot启动流程分析--Start.s(1)
首先通过U-boot/u-boot.lds查看U-boot启动后运行的第一个程序,U-Boot 的链接脚本(即u-boot.lds)是用于定义程序各段在内存中的布局和地址的文件。它在 U-Boot 的启动过程中起着至关重要的作用,决定了代码、数据、堆栈等的存储位置。以下是对 U-Boot 链接脚本的详细解析。
.text : { *(.__image_copy_start) arch/arm/cpu/armv8/start.o (.text*) *(.text*) } . = ALIGN(8);其中text,代表代码段,由此可以查看Uboot启动后执行的第一个程序所在的位置。
如上可知为Start.s
在Start.s中CONFIGxxx配置可以在编译uboot后生成的.config和u-boot/include/generated/autoconf.h中查看
在Start.s中的运行顺序
b reset ->
b save_boot_params_ret->
进入到save_boot_params_ret后执行下面的程序
adr x0, vectors switch_el x1, 3f, 2f, 1f 3: msr 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 */ #ifdef COUNTER_FREQUENCY ldr x0, =COUNTER_FREQUENCY msr cntfrq_el0, x0 /* Initialize CNTFRQ */ #endif b 0f 2: msr vbar_el2, x0 mov x0, #0x33ff msr cptr_el2, x0 /* Enable FP/SIMD */ b 0f 1: msr vbar_el1, x0 mov x0, #3 << 20 msr cpacr_el1, x0 /* Enable FP/SIMD */ 0:上述汇编代码首先将vectors的中断向量表的地址存入到x0,然后switch_el x1,3f,2f,1f是根据当前Uboot所处的运行环境中CPU分配的异常级别所决定的,Uboot处于EL2的异常级别,因此会跳转到2:Enable FP/SIMD FP开启了CPU对浮点数据处理的控制器,SIMD单指令多数据流(SIMD)是一种技术,通过单个指令在多个数据元素上并行执行相同的操作,从而提高计算效率。此处后续的代码用会使用到再进行详细说明。
0: /* * Enable instruction cache (if required), stack pointer, * data access alignment checks and SError. */ #ifndef CONFIG_SYS_ICACHE_OFF mov x1, #CR_I #else mov x1, #0 #endif switch_el x2, 3f, 2f, 1f 3: mrs x0, sctlr_el3 orr x0, x0, x1 msr sctlr_el3, x0 #ifndef CONFIG_SUPPORT_USBPLUG msr daifclr, #4 /* Enable SError. SCR_EL3.EA=1 was already set in start.S */ #endif b 0f 2: mrs x0, sctlr_el2 orr x0, x0, x1 msr sctlr_el2, x0 mrs x0, hcr_el2 orr x0, x0, #HCR_EL2_TGE orr x0, x0, #HCR_EL2_AMO #if CONFIG_IS_ENABLED(IRQ) orr x0, x0, #HCR_EL2_IMO #endif msr hcr_el2, x0 msr daifclr, #4 b 0f 1: mrs x0, sctlr_el1 orr x0, x0, x1 msr sctlr_el1, x0 msr daifclr, #4 0: isb使能完FP和SIMD后,执行上述内容,同样也是跳转到2:处。
上述操作主要是堆hcr_el2寄存器进行操作,目的是为了部分异常处理路由EL2异常级别下,也就是允许该级别下的程序响应和处理这些异常中断,此处#HCR_EL2_TGE开启了捕获通用异常也就是EL0异常级别下的异常路由到EL2,允许EL2的异常级别处理。
#HCR_EL2_AMO将物理SError异常路由到EL2,SError为异步异常,通常由外部触发。asynchronous Data Aborts,异步数据异常,数据异常即CPU读写内存数据时产生的异常:比如:如果误将ROM对应的区域的页表项设置为RW,同时该内存熟悉为write-back cacheable,当尝试写这段区域内存时,数据会先写入cache,而在后面的某个时间点,当其他操作触发相应的脏的cacheline回写内存时,此时内存系统就会返回错误(因为ROM是只读的),从而触发一个异步数据异常。 在Armv8环境中,这就是一个标准的SError。
外部引脚触发。 部分处理器,比如Cortex-A5x,拥有独立的引脚来触发SError,也就是说此时的SError是由SoC设计者自己定义的,比如:ECC和奇偶校验错误就常作为SError来触发。具体应该参考SoC的参考手册来确认SError可能的对应的错误类型。
如果不使能该异常,进入到Kernel阶段,内核也会使能,但是,这个SError即使不使能,当外部发生了SError异常后,它会一直发出异常,一直持续到内核使能了SError异常处理后,这时,内核会离开检测到该异常从而进入异常中断中。
提前使能,可以及时的发现该异常,同时更好的判断异常出现的原因能够更好的排查。
#HCR_EL2_IMO则是将将物理IRQ中断路由到EL2,此处这个IRQ就属于SError异步异常中的一类。
最后0:中的isb使用与刷新系统寄存器的数据的,系统寄存器如sctlr_el1,sctlr_el2,sctlr_el3等
