SMP启动分析:
主要分为以下几个阶段:
- ROM阶段
- OpenSbi底层初始化阶段
- OpenSbi设备初始化阶段
-
- clodboot
-
- warmboot
- Linux阶段
-
- colboot->启动Linux->在kernel_init中经过层层调用,发送SBI_EXT_HSM_HART_START这个ecall到opensbi;
-
- opensbi处理这个ecall将下发参数保存到hartid对应的scratch区域中,发送核间中断,唤醒hartid对应的hart,然后继续执行warmboot的相关流程代码,,最终执行到kernel中;
当CPU上电后,进入ROM阶段
ROM阶段主要进行固件的搬移和参数的准备:
- 设置设备树地址,放入a1寄存器:
- 设置dynamic方式需要的参数,放入a2寄存器存放的地址偏移:
/** Offset of magic member in fw_dynamic_info */
#define FW_DYNAMIC_INFO_MAGIC_OFFSET (0 * __SIZEOF_POINTER__)
/** Offset of version member in fw_dynamic_info */
#define FW_DYNAMIC_INFO_VERSION_OFFSET (1 * __SIZEOF_POINTER__)
/** Offset of next_addr member in fw_dynamic_info (version >= 1) */
#define FW_DYNAMIC_INFO_NEXT_ADDR_OFFSET (2 * __SIZEOF_POINTER__)
/** Offset of next_mode member in fw_dynamic_info (version >= 1) */
#define FW_DYNAMIC_INFO_NEXT_MODE_OFFSET (3 * __SIZEOF_POINTER__)
/** Offset of options member in fw_dynamic_info (version >= 1) */
#define FW_DYNAMIC_INFO_OPTIONS_OFFSET (4 * __SIZEOF_POINTER__)
/** Offset of boot_hart member in fw_dynamic_info (version >= 2) */
#define FW_DYNAMIC_INFO_BOOT_HART_OFFSET (5 * __SIZEOF_POINTER__)
/** Expected value of info magic ('OSBI' ascii string in hex) */
#define FW_DYNAMIC_INFO_MAGIC_VALUE 0x4942534f
- 主要rom阶段要将分配的Cache1和Cache2给关闭,不然会导致后续阶段执行问题;
OpenSbi底层初始化阶段
经过lottery后将选定一个boot hart,其余的hart将等待其重定位和scratch空间和栈空间初始化工作的完成。
_start:
/* Find preferred boot HART id */
MOV_3R s0, a0, s1, a1, s2, a2
call fw_boot_hart
add a6, a0, zero
MOV_3R a0, s0, a1, s1, a2, s2
li a7, -1
beq a6, a7, _try_lottery
/* Jump to relocation wait loop if we are not boot hart */
bne a0, a6, _wait_relocate_copy_done
_try_lottery:
/* Jump to relocation wait loop if we don't get relocation lottery */
la a6, _relocate_lottery
li a7, 1
amoadd.w a6, a7, (a6)
bnez a6, _wait_relocate_copy_done
/* Save load address */
la t0, _load_start
la t1, _start
REG_S t1, 0(t0)
boot hart在完成fdt的重定位后将进入c阶段
_fdt_reloc_done:
/* mark boot hart done */
li t0, BOOT_STATUS_BOOT_HART_DONE
la t1, _boot_status
REG_S t0, 0(t1)
fence rw, rw
j _start_warm
其余的hart在等待BOOT_STATUS_BOOT_HART_DONE标志后,将也会进入c阶段
_wait_for_boot_hart:
li t0, BOOT_STATUS_BOOT_HART_DONE
la t1, _boot_status
REG_L t1, 0(t1)
/* Reduce the bus traffic so that boot hart may proceed faster */
nop
nop
nop
bne t0, t1, _wait_for_boot_hart