多核启动

对于基本的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态,执行第一个用户进程,操作系统启动结束.

bug记录

1、一开始卡在OpenSbi的页面,未能进入操作系统代码中.

解决方法:sbi接口使用错误,使用了另外一种唤醒方式得以解决.

2、在多核启动的时候启动失败.

解决方法:添加阻塞控制逻辑:只有主核完成一系列初始化,其他核才能执行对应的初始化.

    started=1;
  }
  else
  {
    // hart 1
    while (started == 0)
    ;

Last updated