_start_kernel:
/* Mask all interrupts */
csrw CSR_SIE, zero
csrw CSR_SIP, zero
① 将sie,sip寄存器设置为0,关闭所有中断和清除中断的pending(不是异常)。
/* Load the global pointer */
.option push
.option norelax
la gp, __global_pointer$
.option pop
/*
* Disable FPU to detect illegal usage of
* floating point in kernel space
*/
li t0, SR_FS
csrc CSR_SSTATUS, t0
②关闭掉浮点,浮点至少在内核空间才会使用
#ifdef CONFIG_SMP
li t0, CONFIG_NR_CPUS
bgeu a0, t0, .Lsecondary_park
③如果使能了SMP,硬件的实际hart数量超过配置的数量部分直接进入
第二阶段,直接进入WFI模式。
#endif
/* Pick one hart to run the main boot sequence */
la a3, hart_lottery //hart_lottery是一个全局变量,刚开始为0
li a2, 1
amoadd.w a3, a2, (a3)//将a3地址的值赋值为a3,将a2的值加到a3地址处
bnez a3, .Lsecondary_start //判断a3的值是否为0,如果不为0,跳转
④彩票机制,挑选一个hart作为主hart运行,其他hart跳转到.Lsecondary_start
彩票机制是最先运行到该代码的hart对全局变量hart_lottery+1,后续hart运行时
检测到全局变量hart_lottery不为0时都需要跳转。
/* Clear BSS for flat non-ELF images */
la a3, __bss_start
la a4, __bss_stop
ble a4, a3, clear_bss_done
clear_bss:
REG_S zero, (a3)
add a3, a3, RISCV_SZPTR
blt a3, a4, clear_bss
clear_bss_done:
⑤ 向BSS段写0
/* Save hart ID and DTB physical address */
mv s0, a0 //hart ID
mv s1, a1 //DTB phy address
la a2, boot_cpu_hartid
REG_S a0, (a2)
⑥ 将hart id 保存到变量boot_cpu_hartid
/* Initialize page tables and relocate to virtual addresses */
la sp, init_thread_union + THREAD_SIZE //初始化一个临时栈空间,接下来会调用c函数
mv a0, s1
call setup_vm //调用setup_vm,传递参数为DTB的物理地址
la a0, early_pg_dir
call relocate //调用relocate,传递参数为early_pg_dir