-
Notifications
You must be signed in to change notification settings - Fork 18
2. RVM 整体架构
如上图所示,RVM 是一个 Type-2 的 hypervisor。类似于 Linux + KVM + QEMU 的架构,一个基于 RVM 的 Type-2 hypervisor 的正常运行离不开下列组件:
- Host OS:目前支持 zCore 或 rCore。类比于 Linux。
- RVM:Host OS 中的一个模块。类比于 Linux 的 KVM。
- VMM 用户程序:一个用户态程序,通过系统调用访问 RVM API,构建完整的能运行 Guest OS 的应用。类比于 QEMU。
- Guest OS:在虚拟机上运行的 OS,目前已能运行 μCore。类比于 QEMU 上运行的 Guest OS。
RVM 主要提供了两个结构体:Guest
和 Vcpu
,分别是对一个 Guest 和 vCPU 的抽象。使用 RVM 的 Host OS 通过调用这两个结构体提供的函数,来实现 hyervisor 的功能。Host OS 也可通过系统调用的方式将这些函数提供给用户程序,以实现 Type-2 的 hypervisor。由于 rCore 和 zCore 分别兼容的是 Zircon 和 Linux 的系统调用,因此用户程序调用的方式有所不同:
-
zCore:每一个 RVM API 对应一个 zCore 的 syscall,并以
sys_guest
和sys_vcpu
开头,除了向 Guest 添加物理内存段的 API,它使用的是 VMO 和 VMAR 相关的 syscall,不需要专门提供 syscall。 -
rCore:与 Linux KVM 一样,RVM 被抽象为一个虚拟设备文件,用户程序首先通过
open("/dev/rvm", O_RDWR)
打开该文件,然后通过ioctl
系统调用访问 RVM;每个 RVM API 对应不同的ioctl
编号,编号起始值与 KVM 一样都是0xAE00
。
除了形式上的不同,在功能上它们可以一一对应。下表给出了 RVM API、zCore syscall 和 rCore ioctl 编号的对应关系:
API 原语/rCore ioctl | zCore syscall | RVM API | 说明 |
---|---|---|---|
RVM_GUEST_CREATE |
sys_guest_create |
Guest::new() |
创建一个 Guest |
RVM_GUEST_ADD_MEMORY _REGION |
sys_vmo_create sys_vmar_map
|
guest.add_memory_region() |
添加 Guest 的物理内存段 |
RVM_GUEST_SET_TRAP |
sys_guest_set_trap |
guest.set_trap() |
设置捕获哪些 I/O 操作 |
RVM_VCPU_CREATE |
sys_vcpu_create |
Vcpu::new() |
创建一个 vCPU |
RVM_VCPU_RESUME |
sys_vcpu_resume |
vcpu.resume() |
(恢复)运行 vCPU,阻塞当前线程,直到需要用户态模拟 |
RVM_VCPU_READ_STATE |
sys_vcpu_read_state |
vcpu.read_state() |
读 vCPU 状态(寄存器) |
RVM_VCPU_WRITE_STATE |
sys_vcpu_write_state |
vcpu.write_state() vcpu.write_io_state()
|
写 vCPU 状态(寄存器和 I/O 指令结果) |
RVM_VCPU_INTERRUPT |
sys_vcpu_interrupt |
vcpu.virtual_interrupt() |
让 vCPU 产生一个中断 |
可利用以上 API,构建完整的可运行 Guest OS 的用户程序,步骤如下:
- 创建一个 guest;
- 向 Guest 添加物理内存段,写入必要的数据(如 Guest OS 镜像);
- 创建和设置相关虚拟设备,通过
RVM_GUEST_SET_TRAP
设置哪些 I/O 操作由用户程序模拟; - 创建 vCPU;
- 轮询调用
RVM_VCPU_RESUME
,阻塞直到需要模拟 I/O 操作; - 模拟 I/O 操作,然后返回 5。
由于 vCPU 运行时会阻塞当前线程,因此当一个 Guest 中有多个 vCPU 时,需要将它们放在不同的线程中执行。