多核启动
对于基本的xv6操作系统,系统开机之后,先进行sbi初始化,当初始化完成的时候,先执行
entry.S
文件的指令,在entry.S
文件中,操作系统会:- 给每一个CPU分配一个大小为$2^{15}$B的栈空间.
- 把当前CPU的核号传递给
a0
寄存器,由于RISC-V架构特性,a0
寄存器的值会传递给main
函数的hartid
参数. - 分配完之后跳转到main函数执行进一步的初始化.
.section .text
.globl _entry
_entry:
add t0, a0, 1
slli t0, t0, 15
la sp, boot_stack
add sp, sp, t0
call main
当
entry.S
文件执行完之后,操作系统会跳转到位于main.c
文件中的main
函数.1、首先先调用
inithartid(hartid)
函数把当前核的核号放置到tp
寄存器中.2、标记这个核已经成功启动,并且
3、如果还有核没有启动,就会执行多核启动的操作,通过核间中断的方式启动其他还没有成功启动的核,通知这些核核从
_entry
处开始执行:如果所有核都已经启动,for循环会循环一遍,但不会进入到if块中.for(int i = 1; i < NCPU; i++) {
//不是当前核并且这个核没有被唤醒.
if(hartid!=i&&booted[i]==0){
start_hart(i, (uint64)_entry, 0);
}
}
//通过调用sbi提供的中断函数来进行核间中断
static inline void start_hart(uint64 hartid,uint64 start_addr, uint64 a1) {
a_sbi_ecall(0x48534D, 0, hartid, start_addr, a1, 0, 0, 0);
}
3、如果是第一个启动的核(主核),要执行一系列的初始化操作,包括printf函数,页表,各种中断,进程,文件系统等等.如果不是第一个启动的核,就只需要配置中断以及本CPU核的页表部件.
4、调用
scheduler()
函数,转到U态,执行第一个用户进程,操作系统启动结束.1、一开始卡在OpenSbi的页面,未能进入操作系统代码中.
解决方法:sbi接口使用错误,使用了另外一种唤醒方式得以解决.
2、在多核启动的时候启动失败.
解决方法:添加阻塞控制逻辑:只有主核完成一系列初始化,其他核才能执行对应的初始化.
started=1;
}
else
{
// hart 1
while (started == 0)
;
Last modified 5mo ago