一、处理器虚拟化
为什么死循环不能使得计算机彻底卡死?
原理上:
1、硬件会发生中断(类似于“强行插入”的ecall(rics-v的系统调用,类似与x86的syscall))
2、切换到操作系统代码执行
3、操作系统代码可以切换到另一个进程执行
协程库:
co_yield(); //切换协程
二、虚拟化:状态机管理
寄存器组($x0...$x31,$pc),物理内存只有一份
1、寄存器虚拟化:将寄存器状态保存至内存
2、内存虚拟化:$satp的数据结构(Supervisor Address Translation and Protection Register,supervisor模式下的地址翻译和保护寄存器)
操作系统代码最重要的 invariant(单处理器)
1、操作系统开始处理系统调用/中断,所有进程的状态都将被保存至内存
struct page{int prot, void *va, *pa;}
struct proc
{
uint64_t x1, x2, ..., x31;
struct page pages[MAXPAGS];
};
(1)保存
把 x1, x2, ..., x31保存到当前的proc即可
(2)恢复
把pags送到$stap对应的数据结构里
三、状态封存:体系结构相关处理
x86-64
1、中断/异常会伴随堆栈切换
(1)通过TSS指定一个”内核栈“
中断前的寄存器保存在堆栈上(典型的CISC行为)
xv6(不限于RISC-V)
1、把进程的trap trame分配到固定地址(通过$stap)
(1)trap frame保存到$sscratch
2、保存完毕后切换到内核线程执行(包括堆栈切换)