概念
关键是在于这个虚拟化层,我们用虚拟化层来实现对硬件抽象层的虚拟化.
虚拟化的效率高是因为Hypervisor
的体系结构环境是相同的.
这里的II型是KVM这种.1.5型可能更多的是
物理设备只有一个CPU的时候用多任务假装是vcpu
.
有点像虚拟内存<->物理内存.用的也是页表的方式来建立对应关系.
和
vcpu
的方式是一样的实现vDev
.其实就是怎么把一个设备的划分成很多小的粒度,然后再分配资源给它.
最简Hypervisor执行流程:
- 加载Guest OS内核Image到新建地址空间。
- 准备虚拟机环境,设置特殊上下文。
- 结合特殊上下文和指令sret切换到V模式,即VM-ENTRY。
- OS内核只有一条指令,调用sbi-call的关机操作。
- 在虚拟机中,sbi-call超出V模式权限,导致VM-EXIT退出虚拟机,切换回Hypervisor。
- Hypervisor响应VM-EXIT的函数检查退出原因和参数,进行处理,由于是请求关机,清理虚拟机后,退出。
这里这个
V
模式一定要注意,之前我们只涉及了U
和S
模式.
S
变成了HS
.HS
是关键,作为联通真实世界和虚拟世界的通道.体系结构设计了双向变迁机制.
后边实现的很多东西都来自于HS
这个特权级的寄存器.
H扩展后,S模式发送明显变化:原有s[xxx]寄存器组作用不变,新增hs[xxx]和vs[xxx]
hs[xxx]寄存器组的作用:面向Guest进行路径控制,例如异常/中断委托等
vs[xxx]寄存器组的作用:直接操纵Guest域中的VS,为其准备或设置状态
意思好像是要用
HS
里的H
去假冒VS
?
根据
spv
的不同决定sret
会进入虚拟化还是进入user
.
这里还多一个
spvp
,指示HS对V模式下地址空间是否有操作权限,1表示有权限操作,0无权限.
总结下来感觉虚拟机更像是一个进程,但是它又比进程多很多东西,需要运行自己的一套寄存器.
实验
运行之后是触发了一个IllegalInstruction
的trap
.
所以确实是会报错的.
这里要注意是
QEMU
的版本问题,如果是默认的6.x
会导致无法正常进入vmexit_handler
.
我这里安装的QEMU
是9.1.0
版本,可以参见我自己的博客[rCore学习笔记 03]配置rCore开发环境 - winddevil - 博客园,下载的时候把版本改成9.1.0
即可.
这里知道li
指令访问了a7
寄存器违反了不能访问csr
的规定.
由于li
的长度为4
,我们做出如下修改tf.sepc += 4;
:
1 | // modules/axhal/src/arch/riscv/trap.rs |
课后作业
注意触发缺页异常之后要调整
sepc
的值,防止再回去再触发缺页异常然后无限循环了.
因为未知原因会卡住,这题的解题思路应该和h_1_0
是一样的.