1.3. KVM概述之API
文章目录
1. KVM API纵览
KVM的 API是通过/dev/kvm
设备进行访问的。/dev/kvm
是一个字符型设备。

作为 Linux 的一个标准字符型设备,可以使用常见的系统调用如 open、close、ioctl等指令进行操作。
因为KVM的字符型设备的实现函数中,没有包含write、read等操作。所有对KVM的操作都是通过ioctl发送相应的控制字实现的。
KVM所提供的用户空间API从功能上划分,可以分为三种类型,如表所示。

通常,
-
对于KVM API的操作是从打开/dev/kvm设备文件开始的,通过使用系统调用open之后,会获得针对kvm subsystem的一个fd文件描述符。
-
然后通过ioctl系统指令针对该文件描述符进行进一步的操作。
-
通过KVM_CREATE_VM指令将创建一个虚拟机并返回该虚拟机对应的fd文件描述符,然后根据该描述符来控制虚拟机的行为。
-
通过KVM_CREATE_VCPU指令,将创建一个虚拟CPU并且返回该vCPU对应的fd。
需要注意的一点是,在 Linux 的系统调用中,通过 fork()系统调用创建的子进程将继承父进程的文件访问描述符 fd,从而实现多进程访问。而在 KVM内部的API实现中,并没有针对这种情况进行保护。
2. system ioctls调用
system ioctls系统调用用于控制KVM运行环节的参数,相关工作包括全局性的参数设置和虚拟机创建等工作,其主要指令字如表所示。

KVM_CREATE_VM 是其中比较重要的指令字。通过该参数,KVM 将返回一个文件描述符,该文件描述符指向内核控件中一个新的虚拟机。
全新创建的虚拟机没有vCPU,也没有内存,需要通过后续的ioctl指令进行配置。使用mmap()系统调用,则会直接返回该虚拟机对应的虚拟内存空间,并且内存的偏移量为 0。如果 KVM支持 KVM_CAP_USER_MEMORY扩展特性,则应使用其他方法。
3. vm ioctl系统调用
vm ioctl系统调用实现了对虚拟机的控制。vm ioctl控制指令的参数大多需要从 KVM_CREATE_VM 中返回的 fd 文件描述符来进行操作,涉及的操作主要针对某一个虚拟机进行控制,如配置内存、配置vCPU等。

KVM_RUN和KVM_CREATE_VCPU是vm ioctl系统调用的两个重要指令字。在通过 KVM_CREATE_VCPU为 VM虚拟机创建 vCPU,并且获得 vCPU对应的fd文件描述符!!! 之后,可以进行KVM_RUN启动虚拟机!!! 的操作。
KVM_RUN 指令字虽然没有任何参数,但是在调用 KVM_RUN 启动了虚拟机之后,可以通过 mmap()系统调用映射 vCPU 的 fd 所在的内存空间!!! 来获得kvm_run 结构体信息!!!。该结构体位于内存偏移量 0,结束位置在 KVM_GET_VCPU_MMAP_SIZE指令所返回的大小中。
kvm_run结构体的定义在include/uapi/linux/kvm.h
中,通过读取该结构体可以了解 KVM 内部的运行状态,可以类比为计算机芯片中的寄存器组。其中主要的字段及说明如表4所示。

4. vcpu ioctl系统调用
vcpu ioctl系统调用主要针对具体的每一个虚拟的vCPU进行配置,包括寄存器读/写、中断设置、内存设置、调试开关、时钟管理等功能,能够对 KVM的虚拟机进行精确的运行时配置。
4.1. 寄存器控制
对于一个 VM的 CPU来说,寄存器控制是最重要的一个环节,vcpu ioctl在寄存器控制方面提供了丰富的指令字,如表所示。

4.2. 中断和事件管理
KVM在中断管理和事件管理中,也提供了丰富的指令字。在KVM运行期间,可以通过中断管理向vCPU插入中断,或者获取vCPU的一些事件(如热插拔等),该部分指令字如表所示。

4.3. 内存管理
内存管理是虚拟机管理中一个重要的组成部分,KVM也提供了相应的API支持,该部分指令字如表所示。

4.4. 其它管理
除了上面的vCPU 管理、中断管理和内存管理之外,KVM 最后还提供了其他方面的管理,如 CPUID 的设置、调试接口等,这部分接口的指令字如表所示。