xv6Kernel4Core - ccc-sp/riscv2os GitHub Wiki
xv6: 行程 -- 四核心的處理器,會有多少個 kernel 在跑?
我認為是四個,原因如下:
在 main.c 中,雖然只有 0 號核心做了特別多的事,但是其他核心在等到 started 之後,也做了 kvminithart() 的動作。
#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "defs.h"
volatile static int started = 0;
// start() jumps here in supervisor mode on all CPUs.
void
main() // kernel 的主程式,啟動核心並載入第一個 init 使用者行程
{
if(cpuid() == 0){ // 第 0 的 hart 用來跑核心
consoleinit(); // 準備好 console
printfinit(); // 準備好 printf
printf("\n");
printf("xv6 kernel is booting\n");
printf("\n");
kinit(); // physical page allocator // 準備好實體分頁
kvminit(); // create kernel page table // 準備好核心分頁表
kvminithart(); // turn on paging // 啟動分頁表
procinit(); // process table // 準備好行程表
trapinit(); // trap vectors // 設定好 trap 中斷
trapinithart(); // install kernel trap vector // 安裝核心的中斷向量
plicinit(); // set up interrupt controller // 設定中斷控制器
plicinithart(); // ask PLIC for device interrupts // 設定裝置中斷
binit(); // buffer cache // 檔案系統: 緩衝快取
iinit(); // inode cache // 檔案系統: inode快取
fileinit(); // file table // 檔案系統: 設置檔案表
virtio_disk_init(); // emulated hard disk // 檔案系統: 設置 virtio 虛擬硬碟
userinit(); // first user process // 啟動第一個使用者行程 init
__sync_synchronize();
started = 1; // 啟動已完成
} else { // 其他的 hart 用來跑一般程式
while(started == 0)
;
__sync_synchronize();
printf("hart %d starting\n", cpuid());
kvminithart(); // turn on paging // 啟動分頁表
trapinithart(); // install kernel trap vector // 安裝核心的中斷向量
plicinithart(); // ask PLIC for device interrupts // 設定裝置中斷
}
scheduler(); // 進入排程系統 (無窮迴圈)
}
kvminithart() 會設定成和 0 號核心相同的分頁表,因此具有和 0 號核心相同的行為。
// Switch h/w page table register to the kernel's page table,
// and enable paging.
void
kvminithart() // 啟動分頁機制
{
w_satp(MAKE_SATP(kernel_pagetable));
sfence_vma();
}
所以是四個核心同時都有執行 kernel,也有執行 user process ,四個核心都有自己的 Scheduler() 。
這樣看來, RISC-V 的每個核心不只有自己的《暫存器》,也有自己的 TLB 和 CSR 。