#1.KVM 虚拟化结构
KVM体现了Linux系统的哲学:只做一件事情,但是要做得最好。在KVM的Makefile文件中,可以查看到KVM的代码文件组织结构。先将 KVM 的Makefile 文件列举如下:
$ cd /kvm/arch/x86/kvm
$ cat Makefile
$ cat Makefile
ccflags-y += -Iarch/x86/kvm
CFLAGS_x86.o := -I.
CFLAGS_svm.o := -I.
CFLAGS_vmx.o := -I.
KVM := ../../../virt/kvm
kvm-y += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
$(KVM)/eventfd.o $(KVM)/irqchip.o $(KVM)/vfio.o
kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o
kvm-y += x86.o mmu.o emulate.o i8259.o irq.o lapic.o \
i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
hyperv.o page_track.o debugfs.o
kvm-intel-y += vmx.o pmu_intel.o
kvm-amd-y += svm.o pmu_amd.o
obj-$(CONFIG_KVM) += kvm.o
obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
obj-$(CONFIG_KVM_AMD) += kvm-amd.o
在 KVM 的核心模块中,包含了 IOMMU、中断控制、kvm arch、设备管理等部分的代码,这些代码形成了虚拟机管理的核心功能。从这些功能中可以看到,KVM并没有尝试实现一个完整的 PC 系统虚拟化,而将最重要的 CPU虚拟化、IO虚拟化和内存虚拟化部分针对硬件辅助的能力进行了有效的抽象和对接,并且暴露出 API 供上层应用使用。
$ cd /kvm/virt/kvm
$ cat kvm_main.c
在 kvm_main.c 中有一个 kvm_init 的函数是 KVM 初始化的入口。
头文件
/kvm/include/linux
/include/asm-x86
KVM的API是通过 /dev/kvm 设备进行访问的。/dev/kvm 是一个字符型设备。作为Linux的一个标准字符型设备,可以使用常见的系统调用如 open/close/ioctl 等指令进行操作。因为KVM的字符型设备的实现函数中,没有包含 write/read 等操作。所有对KVM的操作都是 ioctl 发送相应的控制字实现的。
KVM 所提供的用户控件 API 从功能上划分,可以分为三种类型。
KVM结构体在KVM的系统架构中代表一个具体的虚拟机。当通过 VM_CREATE_KVM 指令字创建一个新的 KVM虚拟机之后,就会创建一个新的 KVM 结构体对象。
KVM结构体对象中包含了 vCPU、内存、APIC、IRQ、MMU、Event事件管理等信息。该结构体中的信息主要在 KVM虚拟机内部使用,用于跟踪虚拟机的状态。在KVM中,连接了如下几个重要的结构体成员,它们对虚拟机的运行有重要的作用。
KVM 模块可以编译进内核中,也可以作为内核模块在 Linux 系统启动完成之后加载。加载时,KVM根据主机所用的体系架构是 Intel的VMX技术还是AMD的SVM技术,会采用略微不同的加载流程。
Linux的子模块入口通常通过 module_init 宏进行定义,由内核进行调用。KVM的初始化流程如下图:
该函数流程如下:
a. kvm_arch_init 注册 x86 arch 函数操作结构
b. kvm_irqfd_init; //初始化irqfd_cleanup_wq workqueue; KVM_IRQFD ioctrl时会用到
c. kvm_arch_hardware_setup ==》 kvm_x86_ops->hardware_setup
d. 对每个 Cpu 执行kvm_x86_ops->check_processor_compatibility(rtn);
e. 注册register_cpu_notifier(&kvm_cpu_notifier);
f. 注册register_reboot_notifier(&kvm_reboot_notifier);
g. 注册char 设备 misc_register(&kvm_dev);//kvm_dev是kvm对应用层的访问接口
h. register_syscore_ops(&kvm_syscore_ops);注册电源管理回调
i. kvm_preempt_ops 初始化, 该结构在创建vcpu时使用(kvm_vm_ioctl_create_vcpu)
static struct syscore_ops kvm_syscore_ops = { //当VMM host收到电源管理时被调用
.suspend = kvm_suspend,==》 kvm_x86_ops->hardware_disable
.resume = kvm_resume,==》 kvm_x86_ops->hardware_enable
};