KVM循序渐进耳之原理篇
字数 1514 2025-08-23 18:31:18
KVM虚拟化技术深入解析:从原理到实践
1. KVM环境搭建与初始化
1.1 环境准备
- 系统环境:CentOS 6 (2.6.32-754.35.1.el6.x86_64)
- QEMU版本:0.12.1 (qemu-kvm-0.12.1.2-2.506.el6_10.8)
1.2 依赖安装
yum install pciutils-devel
yum install libpic libpic-devel
1.3 QEMU-KVM编译与安装
-
配置编译环境:
./configure -
编译后重要可执行文件:
x86_64-softmmu/qemu-system-x86_64qemu-ioqemu-nbdqemu-img
-
安装选项:
- 拷贝到
/usr/bin - 创建软链接
- 使用
make install(推荐)
- 拷贝到
1.4 常见编译问题解决
- 版本不匹配时可能需要修改gcc选项或源码
- 复杂依赖环境可先yum安装qemu-kvm lib,然后卸载rmmod kvm/kvm-intel
2. QEMU-KVM虚拟机创建
2.1 创建虚拟机镜像
qemu-img create -f qcow2 centos6_vm1.img 10G
2.2 启动虚拟机
qemu-system-x86_64 -m 512 -smp 1 --enable-kvm -boot d -hda /kvm_vm/centos6_vm1.img -cdrom /root/CentOS-6.10-x86_64-minimal.iso
2.3 BIOS文件问题解决
-
查找bios.bin:
find / -name bios.bin -
拷贝到正确位置:
cp /root/qemu-kvm-0.12.1.2/pc-bios/bios.bin /usr/share/seabios/ cp /root/qemu-kvm-0.12.1.2/pc-bios/vapic.bin /usr/local/share/qemu/ -
修改源码调试路径(vl.c):
snprintf(buf, len, "%s/%s%s", data_dir, subdir, name); fprintf(stderr, "[+]bios path: %s\n", buf);
3. KVM初始化流程分析
3.1 KVM初始化入口
if (kvm_enabled()) {
int ret;
ret = kvm_init(smp_cpus);
if (ret < 0) {
fprintf(stderr, "failed to initialize KVM\n");
exit(1);
}
}
3.2 KVM模块加载
insmod kvm.ko
insmod kvm-intel.ko # 或 kvm-amd.ko
4. VMX技术深入解析
4.1 VMX检测流程
-
使用CPUID检测VMX支持:
static __init int cpu_has_kvm_support(void) { unsigned long ecx = cpuid_ecx(1); return test_bit(5, &ecx); // CPUID.1:ECX.VMX[bit 5] } -
BIOS设置检测:
static __init int vmx_disabled_by_bios(void) { u64 msr; rdmsrl(MSR_IA32_FEATURE_CONTROL, msr); return (msr & 5) == 1; // locked but not enabled }
4.2 VMXON操作
-
设置CR4.VMXE位:
write_cr4(read_cr4() | CR4_VMXE); -
执行VMXON指令:
asm volatile ("vmxon %0" : : "m"(phys_addr) : "memory", "cc");
4.3 VMX关键点总结
-
检测流程:
- 检测CPUID是否支持VMX
- 设置CR4.VMXE[bit 13] = 1
- VMX root模式下不可清除CR4.VMXE
-
BIOS控制:
- MSR.bit 0 lock:清除会导致常规保护异常
- bit 1:SMX中启用VMXON
- bit 2:SMX外启用VMXON
5. VMCS虚拟化控制结构
5.1 VMCS基本概念
- 作用:控制VMX non-root操作和VMX转换
- 特点:
- 每个VM可拥有不同VMCS
- 指针必须4KB对齐
- 包含Guest和Host状态信息
5.2 VMCS生命周期
- 创建:通过
KVM_CREATE_VCPUioctl申请vmcs_page - 初始化:使用
vmclear指令初始化Guest-vmcs区域 - 加载:使用
vmptrld指令加载working-VMCS
5.3 VMCS区域详解
5.3.1 Guest-State区域
// 控制寄存器
vmcs_writel(GUEST_CR3, 0);
// 调试寄存器
vmcs_writel(GUEST_DR7, 0x400);
// 通用寄存器
vmcs_writel(GUEST_RFLAGS, 0x02);
vmcs_writel(GUEST_RIP, 0xfff0);
vmcs_writel(GUEST_RSP, 0);
// 段寄存器
vmcs_write16(GUEST_CS_SELECTOR, 0xf000);
vmcs_writel(GUEST_CS_BASE, 0x000f0000);
vmcs_write32(GUEST_CS_LIMIT, 0xffff);
vmcs_write32(GUEST_CS_AR_BYTES, 0x9b);
// 段描述符
vmcs_write16(GUEST_TR_SELECTOR, 0);
vmcs_writel(GUEST_TR_BASE, 0);
vmcs_write32(GUEST_TR_LIMIT, 0xffff);
vmcs_write32(GUEST_TR_AR_BYTES, 0x008b);
5.3.2 Host-State区域
vmcs_writel(HOST_CR0, read_cr0());
vmcs_writel(HOST_CR4, read_cr4());
vmcs_writel(HOST_CR3, read_cr3());
vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS);
vmcs_write16(HOST_DS_SELECTOR, __KERNEL_DS);
vmcs_writel(HOST_RIP, (unsigned long)kvm_vmx_return);
5.4 VM-Execution控制字段
5.4.1 Pin-Based控制
vmcs_write32_fixedbits(MSR_IA32_VMX_PINBASED_CTLS_MSR,
PIN_BASED_VM_EXEC_CONTROL,
PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING);
5.4.2 Processor-Based控制
vmcs_write32_fixedbits(MSR_IA32_VMX_PROCBASED_CTLS_MSR,
CPU_BASED_VM_EXEC_CONTROL,
CPU_BASED_HLT_EXITING |
CPU_BASED_CR8_LOAD_EXITING |
CPU_BASED_CR8_STORE_EXITING |
CPU_BASED_UNCOND_IO_EXITING |
CPU_BASED_INVDPG_EXITING |
CPU_BASED_MOV_DR_EXITING |
CPU_BASED_USE_TSC_OFFSETING);
5.4.3 其他控制字段
// 异常位图
vmcs_write32(EXCEPTION_BITMAP, 1 << PF_VECTOR);
// I/O位图
vmcs_write64(IO_BITMAP_A, 0);
vmcs_write64(IO_BITMAP_B, 0);
// TSC偏移
rdtscll(tsc);
vmcs_write64(TSC_OFFSET, -tsc);
// CR0/CR4掩码
vmcs_writel(CR0_GUEST_HOST_MASK, KVM_GUEST_CR0_MASK);
vmcs_writel(CR4_GUEST_HOST_MASK, KVM_GUEST_CR4_MASK);
6. VM Entry/Exit控制
6.1 VM-Exit控制
vmcs_write32_fixedbits(MSR_IA32_VMX_EXIT_CTLS_MSR,
VM_EXIT_CONTROLS,
(HOST_IS_64 << 9));
6.2 VM-Entry控制
vmcs_write32_fixedbits(MSR_IA32_VMX_ENTRY_CTLS_MSR,
VM_ENTRY_CONTROLS, 0);
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
7. 常见问题与解决方案
7.1 VM Entry失败问题
- 错误代码:0x80000022 (MSR loading失败)
- 解决方案:
- 检查IA32_VMX_ENTRY_CTLS(0x484)寄存器
- 确保VM_ENTRY_CONTROLS正确设置
7.2 编译问题
- IS_ENABLED宏错误:Linux 3.1后引入,旧内核需手动解决
- GCC版本问题:
yum -y install compat-gcc-* yum -y install SDL-devel
8. 推荐书籍
- 《NewBluePill深入理解硬件虚拟机》
- 《QEMU/KVM源码解析应用》
9. 总结
KVM虚拟化技术核心在于:
- 通过VMX指令集实现硬件虚拟化
- 使用VMCS结构保存Guest/Host状态
- 精细控制VM Entry/Exit行为
- 完善的异常和中断处理机制
掌握这些核心原理后,可以进一步深入KVM内存虚拟化、设备虚拟化等高级主题。