1. General description
kvm API 接口就是一组 ioctl
集合,用来控制虚拟机的各个方面。这些 ioctl 可以分为四类:
- system ioctl ,这些ioctl的查询与设置会影响整个虚拟机子系统,它们主要用来创建虚拟机。
- vm ioctl, VM即是 Virtual Machine; 这些ioctl接口主要用于查询/设置虚拟机。例如设置内存布局。此外,VM ioctl 还用于创建虚拟 CPU (vcpus) 和设备(device)。
- vcpu ioctl, 这些接口主要用来操控单个vcpu
- device ioctl, 与vcpu ioctl类似,主要用于操控单个虚拟机设备。
2. File descriptors
kvm API 以文件描述符为中心。
通过 open("/dev/kvm")
获得 kvm 子系统的句柄;此句柄可用于调用系统 ioctl。通过调用ioctl KVM_CREATE_VM
将创建一个 VM 文件描述符,该描述符可用于发出 VM ioctl(第二类 ioctl)。 VM fd 上的 KVM_CREATE_VCPU
或 KVM_CREATE_DEVICE
ioctl 将创建一个虚拟 cpu 或虚拟设备 device,并返回对应的文件描述符。使用 vcpu 或 device fd 可以执行对应的 ioctl (第三类,四类 ioctl)。
需要注意的是,虽然 VM ioctl 只能从创建 VM 的进程发出,但 VM 的生命周期与其文件描述符相关联,而不是与其创建者(进程)相关联。换句话说,直到最后一个对 VM 文件描述符的引用被释放后,VM 及其资源(包括相关的地址空间)才会被释放。例如,如果在 ioctl(KVM_CREATE_VM) 之后发出 fork(),则在父(原始)进程及其子进程都将其引用 VM 的文件描述符释放后,才会释放 VM资源。
由于必须释放文件描述符的所有饮用才会释放 VM 资源,因此强烈建议不要轻易通过 fork()、dup() 等创建 VM 的引用,这可能会产生不必要的副作用,例如当虚拟机关闭时,由虚拟机进程分配的内存可能不会被释放/取消。
3. Extensions
从 Linux 2.6.22 开始,KVM ABI 已经稳定:不允许向后不兼容的更改。但是,有一个扩展工具允许查询和使用 API 的向后兼容扩展。
扩展机制不基于 Linux 版本号。相反,kvm 定义了扩展标识符和一个查询特定扩展标识符是否可用的工具。如果是,则对应的 ioctl 是可用的。
4. API description
本节介绍 kvm guest 的 ioctl api。对于每个 ioctl,都提供了以下信息和描述:
guest 与 host: 一般来说,host 是虚拟机的宿主机,对虚拟机进行管理,而 guest 即虚拟机,这个是相当host 的一个概念。
- Capability: 即哪个 KVM 扩展提供了这个 ioctl。它可以是以下值
- basic:它将由任何支持 API 版本 12(参见第 4.1 节)的内核提供。即一种基础能力。
- KVM_CAP_xyz: 需要使用 KVM_CHECK_EXTENSION(参见第 4.4 节)检查当前内核可用性。
- none:不是所有内核都支持这个 ioctl,但没有对应的接口来检查它的可用性,在不支持的内核上调用这个ioctl, 它将返回
ENOTTY
- Architectures: 即这个 ioctl 适用于哪些指令集架构,x86 包括 i386 和 x86_64
- Type: 按照第一节对ioctl 的分类,system, vm, vcpu, device
- Parameters: ioctl 的参数
- Returns:ioctl 的返回值; 对于一般性的错误,会返回编号
EBADF
,ENOMEM
,EINVAL
4.1 KVM_GET_API_VERSION
获取当前 kvm 的接口版本
Capability:basic
Architectures:all
Type:system ioctl
Parameters:none
Returns:the constant KVM_API_VERSION (=12)
这个ioctl的返回值预期就是12,如果返回值为12,说明这个是符合预期的,所有 Capability 为 basic 的 ioctl 都是可用的。
4.2 KVM_CREATE_VM
创建虚拟机
Capability:basic
Architectures:all
Type:system ioctl
Parameters:machine type identifier (KVM_VM_*)
Returns:a VM fd that can be used to control the new virtual machine.
如果我们想先创建一个即没有虚拟 CPU,也没有内存的虚拟机,那可以使用 0 作为机器类型。
如果是在 S390 上创建虚拟机,请先执行 KVM_CAP_S390_UCONTROL
检查,并使用标志 `KVM_VM_S390_UCONTROL` 作为特权用户。
这里标注 KVM_CREATE_VM 是一种 basic 能力,实际在 s390 上不一定是100%支持的,如果在 s390 上使用, 需要执行 KVM_CAP_S390_UCONTROL 进行检查。
在 arm64 上,VM 的物理地址大小(IPA 大小限制)默认限制为 40 位(即 1TB )。如果主机支持扩展 KVM_CAP_ARM_VM_IPA_SIZE,则可以配置限制。如果支持,请使用 KVM_VM_TYPE_ARM_IPA_SIZE(IPA_Bits) 设置机器类型标识符中的大小.
例如已知某arm单板支持 KVM_CAP_ARM_VM_IPA_SIZE
, 则可以通过以下方式设置虚拟机内存寻址大小
dev_fd= open("/dev/kvm");
vm_fd = ioctl(dev_fd, KVM_CREATE_VM, KVM_VM_TYPE_ARM_IPA_SIZE(48));
如果配置的 IPA_SIZE
大小是不被支持的,则 create vm将失败。
4.3 KVM_GET_MSR_INDEX_LIST, KVM_GET_MSR_FEATURE_INDEX_LIST
Capability: basic, KVM_CAP_GET_MSR_FEATURES for KVM_GET_MSR_FEATURE_INDEX_LIST
Architectures:x86
Type:system ioctl
Parameters:struct kvm_msr_list
(in/out)
Returns:0 on success; -1 on error
Errors:
EFAULT | 无法读取或写入 msr 索引列表 |
---|---|
E2BIG | msr 索引太大,无法放入用户指定的数组中。 |
struct kvm_msr_list {
__u32 nmsrs; /* number of msrs in entries */
__u32 indices[0];
};
用户在 nmsrs 中填写索引数组的大小, kvm 调整 nmsrs 以反映 msrs 的实际数量,并用它们的数字填充索引数组。
4.4 KVM_CHECK_EXTENSION
查询当前内核对 kvm API 的扩展支持。
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或其它数字表示支持
其参数为一个扩展标识符KVM_CAP_*
, 返回0表示不支持, 1或其它数表示支持。
4.5 KVM_GET_VCPU_MMAP_SIZE
获取 vcpu 的控制内存区域大小。
KVM_RUN ioctl 通过共享内存区域与用户空间通信。此 ioctl 返回该区域的大小。
Capability:basic
Architectures: all
Type:system ioctl
Parameters:none
Returns:size of vcpu mmap area, in bytes
此内存空间是用户可以控制的 vcpu 内存。其与cpu构架是无关的,所以这是个 system ioctl, 我们调用 ioctl 时需要穿入dev_fd
,而不是vcpu_fd
除了 KVM_RUN 通信区域的大小, 此接口返回的 mmap 还包含了VCPU 文件描述符的其他区域,如:
- 如果扩展
KVM_CAP_COALESCED_MMIO
是可用的,则内存页KVM_COALESCED_MMIO_PAGE_OFFSET * PAGE_SIZE
也包含在此 mmap 内存区域内。 - 如果扩展
KVM_CAP_DIRTY_LOG_RING
是可用的,则KVM_DIRTY_LOG_PAGE_OFFSET * PAGE_SIZE
的一些页也是在该 mmap 内存区域,8.3 节有更详细的描述。
4.6 KVM_SET_MEMORY_REGION
此 ioctl 已过时并已删除
Capability:basic
Architectures:all
Type:vm ioctl
Parameters:struct kvm_memory_region (in)
Returns:0 on success, -1 on error
4.7 KVM_CREATE_VCPU
创建 vcpu
Capability: basic
Architectures: all
Type: vm ioctl
Parameters: vcpu id (apic id on x86)
Returns: vcpu fd on success, -1 on error
新增一个 vcpu 到虚拟机。最多可以添加 max_vcpus。 vcpu id 是 [0, max_vcpu_id) 范围内的整数。
如何获取 max_vcpus 值:
可以在运行时使用 KVM_CHECK_EXTENSION
ioctl, 传入参数 KVM_CAP_NR_VCPUS
, 返回推荐的 max_vcpus 值。传入参数 KVM_CAP_MAX_VCPUS
, 返回最大可能的 max_vcpus 值。
如果 KVM_CAP_NR_VCPUS
不存在,您应该假设 max_vcpus 为 4, 如果 KVM_CAP_MAX_VCPUS 不存在,您应该假设 max_vcpus 与 KVM_CAP_NR_VCPUS
返回的值相同.
可以在运行时使用 KVM_CHECK_EXTENSION
ioctl, 传入参数 KVM_CAP_MAX_VCPU_ID
, 获取 max_vcpu_id 的最大可能值。
4.8 KVM_GET_DIRTY_LOG (vm ioctl)
获取所有脏页的位图
Capability:basic
Architectures:all
Type:vm ioctl
Parameters:struct kvm_dirty_log
(in/out)
Returns:0 on success, -1 on error
给定一个 memory solt,返回自上次调用此 ioctl 以来所有脏页的位图。位 0 是内存插槽中的第一页。
(免费订阅,永久学习)学习地址: Dpdk/网络协议栈/vpp/OvS/DDos/NFV/虚拟化/高性能专家-学习视频教程-腾讯课堂
更多DPDK相关学习资料有需要的可以自行报名学习,免费订阅,永久学习,或点击这里加qun免费
领取,关注我持续更新哦! !
(确保清除整个 kvm_dirty_log 以避免填充问题)
/* for KVM_GET_DIRTY_LOG */
struct kvm_dirty_log {
__u32 slot;
__u32 padding;
union {
void __user *dirty_bitmap; /* one bit per page */
__u64 padding;
};
};
如果 KVM_CAP_MULTI_ADDRESS_SPACE 可用,slot
字段的第 16-31 位指定要返回脏位图的地址空间。有关 slot 字段使用的详细信息,请参阅 KVM_SET_USER_MEMORY_REGION。
4.9 KVM_SET_MEMORY_ALIAS
此 ioctl 已过时并已被删除。
4.10 KVM_RUN
运行 guest vcpu。
Capability: basic
Architectures: all
Type: vcpu ioctl
Parameters: none
Returns: 0 on success, -1 on error
虽然该接口没有显示指定参数,但是需要我们事先配置好 struct kvm_run
4.11 KVM_GET_REGS
获取CPU的通用寄存器信息,参数 struct kvm_regs, 该接口不支持 arm64 构架
Capability: basic
Architectures: all except arm64
Type: vcpu ioctl
Parameters: struct kvm_regs (out)
Returns: 0 on success, -1 on error
Reads the general purpose registers from the vcpu.
/* x86 */
struct kvm_regs {
/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
__u64 rax, rbx, rcx, rdx;
__u64 rsi, rdi, rsp, rbp;
__u64 r8, r9, r10, r11;
__u64 r12, r13, r14, r15;
__u64 rip, rflags;
};
/* mips */
struct kvm_regs {
/* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
__u64 gpr[32];
__u64 hi;
__u64 lo;
__u64 pc;
};
4.12 KVM_SET_REGS
设置CPU的通用寄存器信息,参数 struct kvm_regs, 该接口不支持 arm64 构架
Capability: basic
Architectures: all except arm64
Type: vcpu ioctl
Parameters: struct kvm_regs (in)
Returns: 0 on success, -1 on error
Writes the general purpose registers into the vcpu.
See KVM_GET_REGS for the data structure.