KVM全称是Kernel-based Virtual Machine,
目前开源的虚拟化技术包括XEN,KVM,QEMU
- 从上图看Xen的特点是硬件模拟这块直接由Xen Hypervisor进程完成,并且其是属于半虚拟化,也就是说Dom U里面的Guest OS需要一定改造
- 最右图属于使用QEMU的user mode emulation模式,不需要有Guest os,可运行user mode application,通过TCG进行指令级的动态翻译(比如arm—x86),常用于指令集仿真场景。
- 中间即KVM模式,属于全虚拟化,Guest OS的资源比如memory,irq等由qemu进程创建,qemu发起对KVM控制,调用cpu 切换到Guest OS运行。KVM属于linux kernel针对虚拟化的实现,x86 arch下对应intel VT-x,AMD-v技术(即vmx与svm)。
接下来具体介绍下KVM,如下图
从进程角度讲qemu,host os,guest OS(这里os进程指kernel),三者是三个进程,三者相互交互。在guest OS的视角察觉不到其他两者(virtio这种半虚拟化除外)。如图一个qemu process负责运行一个guest os。
三者的关系一般为:
- host os 通知qemu通过向其进程发送eventfd形式(qemu epoll it);
- qemu控制host os一般通过对其设备节点/dev/kvm进行ioctl。
- guest os一般不直接与host os,qemu进行交互,在guest OS 进程的视角是察觉不到host os与qemu,guest os一般直接发起对guest memory访问,该memory的io行为由虚拟化硬件功能比如iommu可以直接捕获。
kvm memory virtualization:
- 结合上图先看右中部分,guest physical memory这块对于QEMU进程其实是一段virtual memory region即qemu全局的address_space_memory,申请到这块memory region会通过host os KVM模块 ioctl KVM_SET_USER_MEMORY_REGION的方式递交给HW EPT(Extension Page Table) MMU接管。
- 看图中左下角部分当guest os 访问GPA时是由EPT转换成HPA访问。EPT主要类似MMU的PageTable用来负责维护GVA->GPA->HPA的映射关系。(这里针对intel VT-X)。
GVA:Guest Virtual Address GPA:Guest Physical Address
HPA:Host Physical Address
memory region init:
- 内存虚拟化的开始由qemu发起add memory region,该memory作为成guest os的physical memory使用,guest os image可以boot到该memory。
- 调用流程如下:有qemu的main函数调用qemu_init,接着通过ioctl将memory托管给kvm,在kernel mode里,kvm创建mem slot,用于记录memory 相关数据,HVA,GPA,size,dirty page bitmap等,并加入mem slot list,后续guest os 发生page fault过程会用到该数据。
memory io:
- 如图在左侧QOM init后层层调用,通过ioctl KVM_RUN,切换到kernel mode, 调用vmx_vmenter更新vmcs切换进入Guest os mode,运行Guest OS。当Guest OS发生memory访问会产生hadrware EPT VILOATION(类似page fault)这时发生vmx_vmexit切换到Host os mode,进入EPT VIOLATION异常处理流程获取到访问内容,接着继续切入Guest os继续运行。
- VFIO device create
在用户态将vfio分为container/group/device。通过打开dev/vfio 可以得到container,通过打来/dev/vfio/X 可以得到group。通过ioctl可以得到device
一个VM对应一个container,container可包含多个group,一个group可包含多个device
一般在pass through情况下container:group:device为1:1:1
具体VFIO介绍可参考
https://www.kernel.org/doc/Documentation/vfio.txt
下面为VFIO device创建过程
QEMU中依次获取到container,group,创建device,通过ioctl在linux KVM中创建VFIO设备
- VFIO BAR 虚拟化
VFIO的pci设备memory 虚拟化主要是PCI BAR space的虚拟化。包括MMU参与的BAR mmap将HVA(GPA)转换成HPA,IOMMU参与的BAR remap将HVA转换成GPA(HVA).
如下图通过MMU+IOMMU即完成BAR GVA-->HPA的转换,intel cpu中该IOMMU技术称为VT-d
iommu driver位于linux-5.7.9/drivers/iommu/dmar.c。当guest 访问BAR时,会触发iommu 中断(类似于pagefault),从而访问到GPA(HVA)。
- VFIO-PCI BAR mmap
下图是VFIO-PCI BAR mmap的过程,QEMU把已经创建的用户空间的bar memory region,通过
mmap vfio device设备节点/dev/vfio/xxx,映射到host kernel space,并做了pci_iomap, 对该region进行remap_pfn_range页表映射,即配置好mmu。
- VFIO-PCI BAR remap
下图为 BAR remaping过程,涉及到vfio driver,iommu driver
这里说明下intel vt-x(EPT),vt-d (iommu) 是memory虚拟化的关键