vfio
vfio
qemu
1
2
3
4
5
vfio_realize
=> vfio_attach_device
=> VFIOIOMMUClass->attach_device : vfio_iommu_legacy_class_init
: iommufd_cdev_attach
vfio_iommu_legacy_attach_device
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
vfio_iommu_legacy_attach_device
=> groupid = vfio_device_groupid()
=> group_patch = readlink("/sys//sys/devices/pci{domain}:{bus}/{domain}:{bus}/{b:d.f}/iommu_group")
# eg: ../../../kernel/iommu_groups/11
=> read/sscan (group_patch) -> groupid # eg: 11
=> group = vfio_get_group
=> group->fd = open("/dev/vfio/{groupid}")
=> ioctl(group->fd, VFIO_GROUP_GET_STATUS, &status)
=> if ! status.flags & VFIO_GROUP_FLAGS_VIABLE:
=> goto error
=> vfio_connect_container()
=> foreach_container:
=> ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)
=> vfio_ram_block_discard_disable(container, true)
=> if ioctl() is success:
=> vfio_kvm_device_add_group(group);
=> return
=> else:
=> continue
# if have not fit container, need create new
=> fd = qemu_open("/dev/vfio/vfio", O_RDWR, errp)
=> ret = ioctl(fd, VFIO_GET_API_VERSION)
=> Determine if the API version is supported
=> vfio_ram_block_discard_disable(container, true)
=> vioc = VFIO_IOMMU_GET_CLASS(bcontainer)
=> vfio_kvm_device_add_group(group)
=> vfio_kvm_device_add_fd(group->fd, &err)
=> struct kvm_device_attr attr = {.group = KVM_DEV_VFIO_FILE,
.attr = KVM_DEV_VFIO_FILE_ADD,
.addr = &fd}
=> if vfio_kvm_device_fd < 0:
# need create kvm_device fd
=> struct kvm_create_device cd = {.type = KVM_DEV_TYPE_VFIO}
=> kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)
=> vfio_kvm_device_fd = cd.fd
=> ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)
=> vfio_address_space_insert(space, bcontainer)
=> memory_listener_register(&bcontainer->listener, bcontainer->space->as)
=> vfio_get_device
=>
kernel
KVM_CREATE_DEVICE, KVM_DEV_TYPE_VFIO
1
ioctl(, KVM_CREATE_DEVICE, cd = {.type = KVM_DEV_TYPE_VFIO})
流程
1
2
3
4
5
6
7
8
9
10
kvm_vm_ioctl
=> case KVM_CREATE_DEVICE:
kvm_ioctl_create_device
=> dev(struct kvm_device) = kzalloc()
=> ops = kvm_device_ops_table[type]
=> init dev->ops, dev->kvm
=> ops->create()
=> list_add_rcu(&dev->vm_node, &kvm->devices);
=> anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
TYPE KVM_DEV_TYPE_VFIO OPS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
static const struct kvm_device_ops kvm_vfio_ops = {
.name = "kvm-vfio",
.create = kvm_vfio_create,
.release = kvm_vfio_release,
.set_attr = kvm_vfio_set_attr,
.has_attr = kvm_vfio_has_attr,
};
kvm_vfio_create
=> determine if VFIO device of this vm is exist
=> {
// Only one VFIO "device" per VM
list_for_each_entry(tmp, &dev->kvm->devices, vm_node)
if (tmp->ops == &kvm_vfio_ops)
return -EBUSY;
}
=> kv(struct kvm_vfio *) = kzalloc()
=> INIT_LIST_HEAD(&kv->file_list);
=> dev->private = kv
KVM_SET_DEVICE_ATTR, attr = {group = KVM_DEV_VFIO_FILE, attr = KVM_DEV_VFIO_FILE_ADD}
1
ioctl(, KVM_SET_DEVICE_ATTR, attr = {group = KVM_DEV_VFIO_FILE, attr = KVM_DEV_VFIO_FILE_ADD}
流程:
1
kvm_vfio_file_add
This post is licensed under CC BY 4.0 by the author.