nics 发表于 2017-6-24 07:25:26

Linux KVM的API文档

  原创翻译,转载请注明出处。

1、概述
kvm API是虚拟机的控制命令的ioctl系统调用集合。分为如下三类:
    -system ioctls: 查询和设置那些能影响整个kvm子系统的全局属性。此外,有一个system ioctl是用来创建虚拟机的。
   
    -VM ioctls:查询和设置那些影响一个虚拟机的属性,比如内存布局。此外,一个vm ioctl用来创建虚拟机CPU(vcpu)。
    只能在创建虚拟机的进程(地址空间)运行VM ioctls。
   
    -vcpu ioctls:查询和设置那些控制单个vcpu的操作属性。
    只能在创建vcpu的线程执行vcpu ioctls
   
2、文件描述符
kvm API是以文件描述符为中心的。"/dev/kvm"是kvm子系统的初始化句柄。这个句柄用来执行system ioctls。在这个句柄上执行KVM_CREATE_VM ioctl将会创建一个虚拟机文件描述符(VM fd),这个VM fd就能用来执行VM ioctls。在VM fd上执行KVM_CREATE_VCPU ioctl就会创建一个虚拟CPU并且返回一个指向它的文件句柄(vcpu fd)。最后,vcpu fd的ioctls就能控制vcpu,包括实际运行的客户机代码的那些重要任务。

通常的文件描述符是可以通过fork()的手段和unix domain socket的“SCM_RIGHTS”设备在进程之间迁移的。然而,这种招数在kvm是明确不支持的。虽然这些并不对主机造成危害,但是这些行为不会被API保证成功。仅支持的用法是每个进程是一个虚拟机,一个线程是一个vcpu。

3、扩展
自Linux 2.6.22起,KVM ABI就已经稳定了,不再允许不能向后兼容的修改了。然而,kvm也提供了对API的查询和使用允许向后兼容的扩展。
这个扩展机制不基于内核的版本。作为替代的是,kvm定义了标识符扩展和一个查询特定扩展标识符是否可用的功能。如果是,那么一大堆的ioctls可以给应用程序使用。

4、API描述
这个章节主要是描述那些能用来控制kvm客户机的ioctls。对每一个ioctl,如下描述:
    Capability:每个KVM扩展都提供了这个ioctl。作为'basic',这意味着应该是每个支持API版本12的内核版本都应该提供。每个常量KVM_CAP_xyz,都需要在KVM_CHECK_EXTENSION下检查可用性。或者'none'意味着了没有内核支持这个ioctl,就没有这个能力bit位来检查可用性,如果内核不支持这个ioctl,会返回 -ENOTTY
   
    Architectures:tictl支持哪种指令集,X86平台包含i386和x86_64。
   
    Type:system,vm 或者 vcpu。
   
    Parameters:ioctl接受哪些参数
   
    Return:返回值。通常的错误码:EBADF,ENOMEM,EINVAL,没有详细的说明,但是错误的都是有具体含义的。
   
4.1 KVM_GET_API_VERSION
Capability: basic
Architectures: all
Type: system ioctl
Parameters: none
Returns: the constant KVM_API_VERSION (=12)

作为稳定的kvm API,用来识别API版本。版本号的变化是不可预期的。然而Linux 2.6.20和2.6.21都会报更早的版本。这个在文档里没有说明的,也是不支持的。如果KVM_GET_API_VERSION返回一个不等于12的值,应用程序应该拒绝执行。如果版本号检查通过,后面所有描述为‘basic’的ioctls都可以正常使用。

4.2 KVM_CREATE_VM
Capability: basic
Architectures: all
Type: system ioctl
Parameters: machine type identifier (KVM_VM_*)
Returns: 返回控制新虚拟机的文件描述符(VM fd).

新创建的VM是没有虚拟CPU和内存的。对VM fd的mmap()会访问虚拟机的物理地址空间。offset 0 对应客户机物理地址0。不推荐对VM fd使用mmap(),因为可以使用用户内存分配(KVM_CAP_USER_MEMORY)。
你必须非常确定才去使用参数0作为机器类型(machine type)。
为了能在S390平台上创建用户控制的虚拟机,要检查KVM_CAP_S390_UCONTROL选项,和使用标志KVM_VM_S390_UCONTROL作为特权用户(CAP_SYS_ADMIN)。

4.4 KVM_CHECK_EXTENSION
Capability: basic, KVM_CAP_CHECK_EXTENSION_VM for vm ioctl
Architectures: all
Type: system ioctl, vm ioctl
Parameters: extension identifier (KVM_CAP_*)
Returns: 0 表示不支持; 1 (或其他正整数) 表示支持

这个API允许应用程序来查询核心kvm API的相关扩展。用户空间传入一个扩展标识符(一个整数),然后会接收到一个整数来描述这个扩展的可用性。
通常,0表示不支持,1表示支持,但有些扩展会在返回值里报一些额外的信息。

初始化设置不同的虚拟机会有不同的能力。因此推荐使用VM ioctl来查询能力。

4.5 KVM_GET_VCPU_MMAP_SIZE
Capability: basic
Architectures: all
Type: system ioctl
Parameters: none
Returns: vcpu mmap区域的大小,单位是字节。

KVM_RUN ioctl与用户空间通信是通过一个共享内存区域。这个ioctl就是返回那个区域的大小。更多详情参考 KVM_RUN。

4.7 KVM_CREATE_VCPU
Capability: basic
Architectures: all
Type: vm ioctl
Parameters: vcpu id (apic id on x86)
Returns: vcpu fd on success, -1 on error

这个API往虚拟机里添加一个vcpu。添加vcpu不能超过max_vpcus的值(最大值)。vcpu的ID是在一个[0,max_vcpu_id)的开区间范围。

推荐的max_vcpus的值可以通过运行期的KVM_CHECK_EXTENSION ioctl()的KVM_CAP_NR_VCPUS来获取。
max_vcpus的最大可能值可以通过运行期的KVM_CHECK_EXTENSION ioctl()的KVM_CAP_MAX_VCPUS来获取。
如果不存在KVM_CAP_NR_VCPUS,应该假定最大vcpus是4。
如果不存在KVM_CAP_MAX_VCPUS,应该假定最大vcpus和KVM_CAP_NR_VCPUS返回的值一样。

max_vcpu_id的最大可能值可以通过运行期的KVM_CHECK_EXTENSION ioctl()的KVM_CAP_MAX_VCPU_ID来获取。
如果不存在KVM_CAP_MAX_VCPU_ID,那么max_vcpu_id就与KVM_CAP_MAX_VCPUS的返回值一样。

4.10 KVM_RUN
Capability: basic
Architectures: all
Type: vcpu ioctl
Parameters: none
Returns: 0 on success, -1 on error
Errors:
EINTR:   an unmasked signal is pending

这个ioctl用来运行一个客户机虚拟cpu。如果没有明显的参数,这里会有一个隐式的参数块可以从vcpu fd的mmap()的偏移0的位置获取,大小通过KVM_GET_VCPU_MMAP_SIZE确定。这个参数块是按照结构体struct kvm_run格式的。
  还有好多参数。。后续调重点列举,有兴趣的可以直接看内核文档。
页: [1]
查看完整版本: Linux KVM的API文档