Skip to content

3. CPU 虚拟化

equation314 edited this page Aug 6, 2020 · 2 revisions

Intel VMX 简介

Intel VMX (Virtual-Machine eXtensions) 为 x86 处理器提供了硬件虚拟化支持。

启用虚拟化后的处理器处于一种特殊的模式,被称为 VMX operation。VMX operation 又可分为 VMX root operationVMX non-root operation,分别对应 Host 模式与 Guest 模式。从 VMX root operation 切换到 VMX non-root operation 即 VM Entry,反之,从 VMX non-root operation 切换到 VMX root operation 即 VM Exit

VMX 中有个重要的结构:Virtual-Machine Control Structure (VMCS),可认为是一段特殊的内存区域,用于对 root/non-root 模式的切换进行控制、保存 guest/host 的状态等。其中可以存储许多字段,包括以下 4 类,访问它们需要用到专门的指令(VMREAD/VMWRITE):

  1. 控制字段:对 VM entry/exit/execution 时的行为进行配置;
  2. 只读字段:提供 VM Exit 时的一些信息;
  3. Guest 状态:存放 Guest 的一些控制寄存器、段寄存器、RIP、RSP 等,会在 VM Entry 时载入进 CPU,VM Exit 时保存到 VMCS;
  4. Host 状态:存放 Host 的一些控制寄存器、段寄存器等、RIP、RSP 等,会在 VM Exit 时载入进 CPU,VM Entry 时保存到 VMCS。

VMX 提供了一些特殊指令,常用的几条如下:

  • VMXON:进入 VMX (root) operation
  • VMXOFF:离开 VMX operation
  • VMPTRLD:激活给定物理地址上的 VMCS
  • VMCLEAR:清理给定物理地址上的 VMCS
  • VMREAD:读 VMCS 字段
  • VMWRITE:写 VMCS 字段
  • VMLAUNCH/VMRESUME:进入 VMX non-root operation,首次进入要用 VMLAUNCH,之后每次用 VMRESUME

官方文档:

Guest 启动流程

基于 Intel VMX,创建和启动一个 Guest 和 vCPU 的流程如下:

  1. RVM_GUEST_CREATE
    • 分配 VMXON 所需的 4096 字节大小的物理内存;
    • 执行 VMXON,进入 VMX root operation;
  2. RVM_VCPU_CREATE
    • 分配 VMCS 所需的 4096 字节大小的一页物理内存;
    • 执行 VMCLEAR 和 VMPTRLD,激活该地址上的 VMCS;
    • 对 VMCS 进行初始配置,包括控制字段、Guest 状态、Host 状态;
  3. RVM_VCPU_RESUME
    • 保存 Host 通用寄存器到栈上,并载入 Guest 通用寄存器;
    • 执行 VMLAUNCH/VMRESUME,进入 VMX non-root operation,开始 Guest 的运行;
  4. 发生 VM Exit:
    • 处理器自动回到 VMX root operation;
    • 保存 Guest 通用寄存器到栈上,并恢复 Host 通用寄存器;
    • 根据 VMCS 中的 Exit reason 字段,进行相应的处理;
    • 回到第 3 步继续执行 Guest;
  5. 结束:
    • 执行 VMCLEAR,清理 VMCS;
    • 执行 VMXOFF,退出 VMX operation。

其中,在第 4 步最后也可不回第 3 步,而是返回到用户态,由用户程序来处理 VM Exit,一般用于 I/O 操作的模拟。考虑到这种情况,用户程序执行 RVM_VCPU_RESUME 时的流程可以用下图表示:

RVM_VCPU_RESUME

运行在 ring3 的用户程序通过系统调用进入 ring0,此时处理器也处于 VMX root operation,通过 VMLAUNCH/VMRESUME 进入 VMX non-root operation,开始 Guest 的运行。

Guest 运行过程中会因某些原因发生 VM Exit,自动退回到 VMX root operation。对于可以完全由 RVM 处理的 VM Exit,处理完后就可以继续执行 VMRESUME 来运行 Guest;不过也有一些 VM Exit 还需由用户程序处理,一般是 I/O 操作,这时就进行系统调用返回,将 I/O 操作转发给用户程序,回到 ring3 继续执行。

用户程序处理完后,可再次进行系统调用,重复刚才的流程。

VM Exit

类似于对中断处理,发生 VM Exit 后也需要根据退出原因进行相应的处理。退出原因保存在 VMCS 的 Exit reason 字段。RVM 中处理的主要几类 VM Exit 如下:

  • External interrupt:启用 VMX 后,外部中断不再使用基于 IDT 的中断处理流程,而是会发生该类 VM Exit,此时需要手动跳转到中断处理例程。
  • CPUID:Guest 执行 CPUID 指令,获取处理器的一些信息。
  • VMCALL:Guest 执行 VMCALL 指令,进行一次 hypercall。
  • I/O instruction:Guest 执行 IN/OUT 等 I/O 指令,用于设备的模拟。
  • EPT violation:Guest 访问 EPT 中没有映射的物理地址,可用于实现 EPT 延迟映射或 MMIO。
Clone this wiki locally