start.S文件在arch/arm/cpu/armv8下面,源码如下:
.globl _start
_start:
#if defined(LINUX_KERNEL_IMAGE_HEADER)
#include <asm/boot0-linux-kernel-header.h>
#elif defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK)
#include <asm/arch/boot0.h>
#else
b reset
#endif
//在生成的.config中并没有定义LINUX_KERNEL_IMAGE_HEADER和CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK,故程序直接跳到: b reset
.align 3 //定义8字节对齐,可以从汇编文件中看出来
.globl _TEXT_BASE
_TEXT_BASE:
.quad CONFIG_SYS_TEXT_BASE
.globl _end_ofs
_end_ofs:
.quad _end - _start
.globl _bss_start_ofs
_bss_start_ofs:
.quad __bss_start - _start
.globl _bss_end_ofs
_bss_end_ofs:
.quad __bss_end - _start
/*在u-boot的反汇编文件中定义如下:
0000000080020008 <_TEXT_BASE>:
80020008: 80020000 .word 0x80020000
8002000c: 00000000 .word 0x00000000
0000000080020010 <_end_ofs>:
80020010: 00081e48 .word 0x00081e48
80020014: 00000000 .word 0x00000000
0000000080020018 <_bss_start_ofs>:
80020018: 00081e48 .word 0x00081e48
8002001c: 00000000 .word 0x00000000
0000000080020020 <_bss_end_ofs>:
80020020: 000c7be0 .word 0x000c7be0
80020024: 00000000 .word 0x00000000
可以看到每个变量之间的地址差为8
reset:
b save_boot_params
/*查看反汇编代码如下:
0000000080020028 <reset>:
80020028: 14000036 b 80020100 <save_boot_params>
0000000080020100 <save_boot_params>:
80020100: 17ffffcb b 8002002c <save_boot_params_ret>
80020104: 00000000 .inst 0x00000000 ; undefined
80020108: 007a1200 .word 0x007a1200
可知跳到了本文件中的WEAK(save_boot_params)中,并且啥也没干又跳到了save_boot_params_ret*/
.globl save_boot_params_ret
save_boot_params_ret:
#if CONFIG_POSITION_INDEPENDENT
pie_fixup:
adr x0, _start /* x0 <- Runtime value of _start */
ldr x1, _TEXT_BASE /* x1 <- Linked value of _start */
sub x9, x0, x1 /* x9 <- Run-vs-link offset */
adr x2, __rel_dyn_start /* x2 <- Runtime &__rel_dyn_start */
adr x3, __rel_dyn_end /* x3 <- Runtime &__rel_dyn_end */
pie_fix_loop:
ldp x0, x1, [x2], #16 /* (x0, x1) <- (Link location, fixup) */
ldr x4, [x2], #8 /* x4 <- addend */
cmp w1, #1027 /* relative fixup? */
bne pie_skip_reloc
/* relative fix: store addend plus offset at dest location */
add x0, x0, x9
add x4, x4, x9
str x4, [x0]
pie_skip_reloc:
cmp x2, x3
b.lo pie_fix_loop
pie_fixup_done:
#endif
//在.config和整个uboot中并没有定义CONFIG_POSITION_INDEPENDENT
#ifdef CONFIG_SYS_RESET_SCTRL
bl reset_sctrl
#endif
//整个uboot中并没有定义CONFIG_SYS_RESET_SCTRL
#if defined(CONFIG_ARMV8__SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
.macro set_vbar, regname, reg
msr \regname, \reg
.endm
adr x0, vectors
#else
.macro set_vbar, regname, reg
.endm
#endif
/*在U-BOOT中CONFIG_ARMV8__SPL_EXCEPTION_VECTORS和CONFIG_SPL_BUILD都没有定义,故执行:
.macro set_vbar, regname, reg
msr \regname, \reg
.endm
adr x0, vectors
定义宏set_vbar,将通用寄存器reg的值写入状态寄存器regname中,并将终端向量的地址给到x0*/
switch_el x1, 3f, 2f, 1f
/*switch_el 的定义如下:
.macro switch_el, xreg, el3_label, el2_label, el1_label
mrs \xreg, CurrentEL
cmp \xreg, 0xc
b.eq \el3_label
cmp \xreg, 0x8
b.eq \el2_label
cmp \xreg, 0x4
b.eq \el1_label
.endm
此处switch_el定义为:读取CurrentEL状态寄存器的值,如果等于0xc则跳到el3_label,0x8则跳到el2_label,0x4则跳到el1_label,此处为根据中断等级跳到响应的位置*/
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 */
//使能EL3等级下的NS|IRQ|FIQ|EA和FP/SIMD
#ifdef COUNTER_FREQUENCY
ldr x0, =COUNTER_FREQUENCY
msr cntfrq_el0, x0 /* Initialize CNTFRQ */
#endif
//在include/configs/imx8qxp_mek.h中定义如下#define COUNTER_FREQUENCY 8000000 /* 8MHz */,写入cntfrq_el0
b 0f
2: set_vbar vbar_el2, x0
mov x0, #0x33ff
msr cptr_el2, x0 /* Enable FP/SIMD */
//使能EL2等级下的FP/SIMD
b 0f
1: set_vbar vbar_el1, x0
mov x0, #3 << 20
msr cpacr_el1, x0 /* Enable FP/SIMD */
//使能EL1等级下的FP/SIMD
0:
#ifdef CONFIG_ARMV8_SET_SMPEN
switch_el x1, 3f, 1f, 1f
3:
mrs x0, S3_1_c15_c2_1 /* cpuectlr_el1 */
orr x0, x0, #0x40
msr S3_1_c15_c2_1, x0
1:
#endif
//在.config中CONFIG_ARMV8_SET_SMPEN未定义
bl apply_core_errata
/*在本文件中定义了:
WEAK(apply_core_errata)
mov x29, lr /* Save LR */
branch_if_a53_core x0, apply_a53_core_errata
branch_if_a57_core x0, apply_a57_core_errata
0:
mov lr, x29 /* Restore LR */
ret
同时apply_a53_core_errata的定义如下:
apply_a53_core_errata:
#ifdef CONFIG_ARM_ERRATA_855873
mrs x0, midr_el1
tst x0, #(0xf << 20)
b.ne 0b
mrs x0, midr_el1
and x0, x0, #0xf
cmp x0, #3
b.lt 0b
mrs x0, S3_1_c15_c2_0 /* cpuactlr_el1 */
/* Enable data cache clean as data cache clean/invalidate */
orr x0, x0, #1 << 44
msr S3_1_c15_c2_0, x0 /* cpuactlr_el1 */
#endif
b 0b
而CONFIG_ARM_ERRATA_855873并没有定义,故跳到0处:
mov lr, x29 /* Restore LR */
ret
返回到主函数继续执行*/
bl lowlevel_init
/*从汇编文件中可以知道跳到了本文件下的lowlevel_init处并什么都没干:
00000000800200b8 <lowlevel_init>:
800200b8: aa1e03fd mov x29, x30
800200bc: aa1d03fe mov x30, x29
800200c0: d65f03c0 ret*/
#if defined(CONFIG_ARMV8_SPIN_TABLE) && !defined(CONFIG_SPL_BUILD)
branch_if_master x0, x1, master_cpu
b spin_table_secondary_jump
/* never return */
#elif defined(CONFIG_ARMV8_MULTIENTRY)
branch_if_master x0, x1, master_cpu
/*
* Slave CPUs
*/
slave_cpu:
wfe
ldr x1, =CPU_RELEASE_ADDR
ldr x0, [x1]
cbz x0, slave_cpu
br x0 /* branch to the given address */
#endif /* CONFIG_ARMV8_MULTIENTRY */
//CONFIG_ARMV8_SPIN_TABLE、CONFIG_SPL_BUILD和CONFIG_ARMV8_MULTIENTRY都没有定义
master_cpu:
bl _main
跳到main函数执行
这篇博客主要分析start.S文件,main函数在下一篇博客中进行分析