VMCS研究总结
VMCS是Intel VT-x中的核心组件之一,在虚拟化管理模块下完成任务。它占据一个页框空间,在硬件层面上实现读写操作,并与页表机制具有相似功能。每个域的具体描述可在官方文档中找到,但其具体存储位置信息不为开发者所掌握。开发者无需深入关注细节即可完成相关操作——通过VMWRITE和VMREAD指令进行读写操作。这种设计的好处在于能够透明地进行布局调整。
下面从三个方面总结一下:
一是vmcs组成部分;
二是kvm中vmcs分配与初始化路径;
三是kvm配置vmcs中一些重要的域。
首先来看vmcs组成部分,这个可以参考"IA32 Intel Architecture Software Developer's Manual Volume 3B System Programming Guide",这里简单总结一下:
-
- 虚拟机状态寄存器
-
- 主机状态寄存器
-
- 虚拟机执行控制字段
-
3.1 基于32位引脚的执行控制
-
3.2 基于32位CPU的执行控制
-
3.3 基于32位CPU的次要执行控制
-
3.4 32位异常掩码
-
3.5 64位物理地址用于I/O掩码A和B(每个为4KB)
-
3.6 64位TSC偏移量
-
3.7 APIC访问权限控制措施
-
- 虚拟机退出控制字段
-
4.1 32bit VM-Exit Controls
-
4.2 32+64bit VM-Exit Controls for MSRs
-
- VM-Entry Control Fields
-
5.1 32bit VM-Entry Controls
-
5.2 VM-Entry Controls for Event Injection
-
5.2.1 32bit VM-Entry Interruption-information field
-
5.2.2 32bit VM-Entry exception error code
-
5.2.3 32bit VM-Entry instruction length
-
5.3 32+64bit VM-Entry Controls for MSRs
-
- VM-Exit Information Fields
深入分析kvm资源分配以及初始化虚拟机组件(VMCS)的过程
首先,在kvm内核模块加载过程中,在hardware_setup阶段中执行 alloc_kvm_area函数,并对该过程进行扩展以完成对每一个cpu的分配。在配置管理中扮演着关键角色的是 setup_vmcs_config命令,在后续章节将详细介绍这一操作的详细流程。值得注意的是该命令仅负责将相关参数记录到 dedicated_vmc_config结构体中,并未实际修改任何物理资源的配置参数;真正的修改会在后续步骤中完成
vmx_init(vmx.c)
||
kvm_init(kvm_main.c)
||
kvm_arch_init(kvm_main.c) --> kvm_arch_hardware_setup
||
kvm_timer_init(x86.c) kvm_x86_ops->hardware_setup(vmx.c)
||
setup_vmcs_config(vmx.c) --> alloc_kvm_area(vmx.c)
| for_each_cpu
alloc_vmcs_cpu(vmx.c)
在创建vcpu的过程中需要注意的是每个vcpu都需要独立配置一个vmcs。观察发现在此步骤中使用alloc_vmcs_cpu来指定一个vmcs页。此外在配置过程中必须调用vmx_vcpu_setup函数以确保配置信息被正确保存到对应的vmcs页上。
KVM_CREATE_VCPU ---> kvm_vm_ioctl (kvm_main.c)
||
kvm_vm_ioctl_create_vcpu(kvm_main.c)
||
kvm_arch_vcpu_create(x86.c)
||
kvm_x86_ops->vcpu_create(vmx_create_vcpu in vmc.c)
||
alloc_vmcs(vmx.c) ---> vmx_vcpu_setup
||
alloc_vmcs_cpu(vmx.c) vmcs_writel --> guest_write_tsc
最后来看kvm对vmcs的一些重要配置。它几个部分的配置比较的分散:
配置IO bitmap A和B在vmx_init中配置;然而仅限于存储的是该IO bitmap所对应的物理内存地址。
VM执行控制模块、VM入口控制模块以及VM出口控制模块这三个核心组件。它们的具体配置可通过setup_vmcs_config函数获取(特别地,在该函数中包含通用配置参数设置这一基本功能))。其中关键的配置项包括:
1. PIN_BASED_EXT_INTR_MASK;标志着external interrupt会导致VMExit;
2. 不使用RDTSC_EXITING标志; rdtscc指令将不会导致VMExit,并且 guests can directly access the physical TSC.
3. CPU_BASED_USE_TSC_OFFSETTING;表明在基于物理处理器周期的情况下,在获取 guest 的时间戳时需要将时间戳偏移量(TCS_OFFSET)加到读取的物理时间戳上以获得 guest 的时间戳;
4. 基于CPU的IO位图使用情况标志;每个 guest 的 IO 指令是否会导致 VM_EXIT 需要检查 associated 的 IO bitmap
5. SECONDARY_EXEC_ENABLE_EPT;表示默认情况下会开启EPT特性;
6. 不支持VM_EXIT_ack_intr_on_exit的功能;
我的理解如下:原先在guest模式下,默认情况下会关闭中断功能,
但会导致VMExit(设置为上电重启)的操作。
当执行完exit操作后,
kvm内核代码会立即开启中断,
此时必须能够检测到该中断。
然而,
如果在exit过程中就已经完成了ACK操作,
那么后续再次开启中断时将无法检测到该中断。
7. 1至6都属于执行控制。具体而言,在设置VMCS配置时,Entry和Exit控制的固定配置相对较少。
