我们日常开发过程中都会用到各大云服务(阿里云, GCP 等)的 VPS 和自己电脑上的虚拟机(VMware, PVE 等).
作为上层的软件开发者, 我们不需要了解其底层实现的细节就可以享受虚拟化带来的便利, 谈及其中最核心的 CPU 虚拟化技术时也常常轻描淡写地一笔带过.
最近出于好奇检索了更多资料, 整理一些 CPU 虚拟化相关的资料在此.
总览
在没有硬件虚拟化的情况下, x86 指令集有 Ring0-Ring3 4个特权等级, OS内核运行在 Ring0, 用户态程序运行在 Ring3, 虚拟内存机制为每个进程提供了独立的地址空间.
这种情况下, 因为缺少了能隔离多个内核态的 CPU 指令, 想要在同一台机器上运行多个独立的 OS 就变得困难. QEMU 通过 recompile 实现了完全 User-mode 下的全系统模拟, 但是代价是巨大的性能损失. (我还实现过一个纯解释执行的 QEMU 青春版)
为了解决上述问题, Intel 和 AMD 都提出了自己的硬件虚拟化方案(VT 和 SVM), 以下以 Intel VT-x 为例.
VMX 相关指令
VT-x 中, Intel 引入了一系列相关指令用于支持硬件虚拟化的实现.
Intel Mnemonic | Description |
---|---|
INVEPT | Invalidate Translations Derived from EPT |
INVVPID | Invalidate Translations Based on VPID |
VMCALL | Call to VM Monitor |
VMCLEAR | Clear Virtual-Machine Control Structure |
VMFUNC | Invoke VM function |
VMLAUNCH | Launch Virtual Machine |
VMRESUME | Resume Virtual Machine |
VMPTRLD | Load Pointer to Virtual-Machine Control Structure |
VMPTRST | Store Pointer to Virtual-Machine Control Structure |
VMREAD | Read Field from Virtual-Machine Control Structure |
VMWRITE | Write Field to Virtual-Machine Control Structure |
VMXOFF | Leave VMX Operation |
VMXON | Enter VMX Operation |
VT-x 引入了两种额外的 CPU 模式:
- VMX Root 操作模式: 通过
VMXON
指令进入, 此时主机成为 Hypervisor - VMX Non-Root 操作模式: Guest 所处的模式, 在 VMX Root 模式下通过
VMLAUNCH
进入, 限制了敏感资源的访问, 访问敏感资源会触发VM exits
退出到VMX Root
VMX 生命周期如下:
- 软件通过
VMXON
指令进入 VMX 操作模式。- VMM 可以通过
VM entries
进入 Guest VM(单次只能执行一个 VM),VMM 通过VMLAUNCH
(第一次进入 VM)与VMRESUME
(从 VMM 中恢复到 VM)指令来使能VM entry
,通过VM exits
重获控制权。VM exits
通过 VMM 指定的入口点移交控制权,VMM 对 VM 的退出原因进行响应后通过VM entry
返回到 VM 中。- 当 VMM 想要停止自身运行并退出 VMX 操作模式时,其通过
VMXOFF
指令来完成。
VMX Root 就类似 Ring0 权限, VMX Non-Root 中运行的 Guest 就类似运行在 Ring3 下. Guest 访问敏感资源的请求(特权寄存器)会被交给 VMX Root 的 VM-exits Handler 处理. VMX Root 可以调度多个 Guest 同时运行.
VMCS
VMCS(Virtual Machine Control Structure) 是用于储存 Guest 和 Host 状态的一个结构体, 主要储存寄存器状态(用于保存/恢复现场)以及控制 VM 行为的一些 Flag.
VMCS 不能直接读写, 需要通过 VMREAD
和 VMWRITE
指令修改.
EPT
EPT(Extended Page Table, 拓展页表) 与页表类似, 提供了地址转换的功能.
CPU 能将 VMX Non-Root 模式下的物理内存读写根据 EPT 映射成对主机物理地址的读写.
在常用的虚拟机中, 每个 Guest 内的物理地址都会被独立的映射到主机上不同的物理地址区块上, 实现互不干扰, 独立运行.
与主机中的页表类似, EPT 也支持访问控制 (Read, Write, Execute), 访问控制功能后续在 Hypervisor-assisted debugger 中发挥了重要作用: 可以给正常运行的程序移除指定区域的 RWE 权限, 这样程序执行到对应位置时则会触发 VM-exits, 可以 trace 被调试程序的行为, 并进一步修改程序.
更多实际应用
硬件虚拟化技术开始主要用于在一台 bare metal 上运行多个 OS, 近年来也被用于软件调试, 二进制安全等领域:
更多资料
CTF Wiki 上的虚拟化介绍: https://ctf-wiki.org/pwn/virtualization/basic-knowledge/cpu-virtualization/#reference
自己实现一个 Hypervisor: https://rayanfam.com/topics/hypervisor-from-scratch-part-1
本文采用 CC BY-NC-SA 4.0 许可协议发布.
作者: lyc8503, 文章链接: https://blog.lyc8503.net/post/hypervisor-explore/
如果本文给你带来了帮助或让你觉得有趣, 可以考虑赞助我¬_¬