Friday, February 7, 2020

kvm_all.c - ioctls (kvm_ioctl, kvm_vm_ioctl, kvm_vcpu_ioctl, kvm_device_ioctl)

kvm_all.c是QEMU与KVM通信相关的一个非常重要的文件,因此它必然也有许多和通信相关的内容。KVM是一个内核模块,普通权限的QEMU若要和KVM通信,则使用ioctl是最方便的。

在kvm_all.c中,封装了多个ioctl相关的函数:kvm_ioctl, kvm_vm_ioctl, kvm_vcpu_ioctl, kvm_device_ioctl,这些ioctl最终会反映到系统的KVM,VM和vCPU三个级别上。 这些ioctl与KVM分类的ioctl基本一一对应。

要通过ioctl访问KVM内核模块,QEMU-KVM必须打开/dev/kvm,并将结果文件描述符存储在KVMState->fd中。

这四个函数基本内容一模一样,只是通过不同的文件描述符来发送ioctl。接下来来依次介绍它们。

1. kvm_ioctl
调用这个发送的ioctl,需要由KVMState->fd去发送,其中KVMState->fd是通过打开/dev/kvm获得的文件描述符。
定义如下:

int kvm_ioctl(KVMState *s, int type, ...) {
……
    ret = ioctl(s->fd, type, arg);
……
}

2. kvm_vm_ioctl
调用这个函数发送的ioctl主要经由KVMState->vmfd来执行。

定义如下:

int kvm_vm_ioctl(KVMState *s, int type, ...) {
……
    ret = ioctl(s->vmfd, type, arg);
……
}

3. kvm_vcpu_ioctl
与前面类似的,这个ioctl经由cpu->kvm_fd来执行。 CPUState等的定义可参考上一篇(http://www.qemu.world/?x=entry:entry200207-131048)文章。

定义如下:

int kvm_vcpu_ioctl(CPUState *cpu, int type, ...){
……
    ret = ioctl(cpu->kvm_fd, type, arg);
……
}

4. kvm_device_ioctl
这个稍稍有点不一样,它是个更通用一点的wrapper,先看定义:

int kvm_device_ioctl(int fd, int type, ...)
{
……
    ret = ioctl(fd, type, arg);
……
}

fd是从第一个参数传来的,基本就是个工具函数,使用例子例如:

int kvm_device_check_attr(int dev_fd, uint32_t group, uint64_t attr)
{
……
    return kvm_device_ioctl(dev_fd, KVM_HAS_DEVICE_ATTR, &attribute) ? 0 : 1;
}