> On 27 Feb 2026, at 12:32 PM, Cédric Le Goater <[email protected]> wrote:
>
> On 2/25/26 04:49, Ani Sinha wrote:
>> Normally the vfio pseudo device file descriptor lives for the life of the VM.
>> However, when the kvm VM file descriptor changes, a new file descriptor
>> for the pseudo device needs to be generated against the new kvm VM
>> descriptor.
>> Other existing vfio descriptors needs to be reattached to the new pseudo
>> device
>> descriptor. This change performs the above steps.
>> Tested-by: Cédric Le Goater <[email protected]>
>> Reviewed-by: Cédric Le Goater <[email protected]>
>> Signed-off-by: Ani Sinha <[email protected]>
>> ---
>> hw/vfio/helpers.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++
>> 1 file changed, 92 insertions(+)
>> diff --git a/hw/vfio/helpers.c b/hw/vfio/helpers.c
>> index f68f8165d0..e2bedd15ec 100644
>> --- a/hw/vfio/helpers.c
>> +++ b/hw/vfio/helpers.c
>> @@ -116,6 +116,89 @@ bool vfio_get_info_dma_avail(struct
>> vfio_iommu_type1_info *info,
>> * we'll re-use it should another vfio device be attached before then.
>> */
>> int vfio_kvm_device_fd = -1;
>> +
>> +/*
>> + * Confidential virtual machines:
>> + * During reset of confidential vms, the kvm vm file descriptor changes.
>> + * In this case, the old vfio kvm file descriptor is
>> + * closed and a new descriptor is created against the new kvm vm file
>> + * descriptor.
>> + */
>> +
>> +typedef struct VFIODeviceFd {
>> + int fd;
>> + QLIST_ENTRY(VFIODeviceFd) node;
>> +} VFIODeviceFd;
>> +
>> +static QLIST_HEAD(, VFIODeviceFd) vfio_device_fds =
>> + QLIST_HEAD_INITIALIZER(vfio_device_fds);
>> +
>> +static void vfio_device_fd_list_add(int fd)
>> +{
>> + VFIODeviceFd *file_fd;
>> + file_fd = g_malloc0(sizeof(*file_fd));
>> + file_fd->fd = fd;
>> + QLIST_INSERT_HEAD(&vfio_device_fds, file_fd, node);
>> +}
>> +
>> +static void vfio_device_fd_list_remove(int fd)
>> +{
>> + VFIODeviceFd *file_fd, *next;
>> +
>> + QLIST_FOREACH_SAFE(file_fd, &vfio_device_fds, node, next) {
>> + if (file_fd->fd == fd) {
>> + QLIST_REMOVE(file_fd, node);
>> + g_free(file_fd);
>> + break;
>> + }
>> + }
>> +}
>> +
>> +static int vfio_device_fd_rebind(NotifierWithReturn *notifier, void *data,
>> + Error **errp)
>> +{
>> + VFIODeviceFd *file_fd;
>> + int ret = 0;
>> + struct kvm_device_attr attr = {
>> + .group = KVM_DEV_VFIO_FILE,
>> + .attr = KVM_DEV_VFIO_FILE_ADD,
>> + };
>> + struct kvm_create_device cd = {
>> + .type = KVM_DEV_TYPE_VFIO,
>> + };
>> +
>> + /* we are not interested in pre vmfd change notification */
>> + if (((VmfdChangeNotifier *)data)->pre) {
>> + return 0;
>> + }
>> +
>> + if (kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd)) {
>> + error_setg_errno(errp, errno, "Failed to create KVM VFIO device");
>> + return -errno;
>> + }
>> +
>> + if (vfio_kvm_device_fd != -1) {
>> + close(vfio_kvm_device_fd);
>> + }
>> +
>> + vfio_kvm_device_fd = cd.fd;
>> +
>> + QLIST_FOREACH(file_fd, &vfio_device_fds, node) {
>> + attr.addr = (uint64_t)(unsigned long)&file_fd->fd;
>> + if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
>> + error_setg_errno(errp, errno,
>> + "Failed to add fd %d to KVM VFIO device",
>> + file_fd->fd);
>> + ret = -errno;
>
> In case you resend, may be change this part to return -errno at first
> error. Seems best.
>
>> + }
>> + }
>> + return ret;
>
> And return 0 here. Which means 'ret' is now unused.
Yes good idea. I have just sent a v7 for this patch only which I see you have
already seen.
>
> Thanks,
>
> C.
>
>
>> +}
>> +
>> +static struct NotifierWithReturn vfio_vmfd_change_notifier = {
>> + .notify = vfio_device_fd_rebind,
>> +};
>> +
>> #endif
>> void vfio_kvm_device_close(void)
>> @@ -153,6 +236,11 @@ int vfio_kvm_device_add_fd(int fd, Error **errp)
>> }
>> vfio_kvm_device_fd = cd.fd;
>> + /*
>> + * If the vm file descriptor changes, add a notifier so that we can
>> + * re-create the vfio_kvm_device_fd.
>> + */
>> + kvm_vmfd_add_change_notifier(&vfio_vmfd_change_notifier);
>> }
>> if (ioctl(vfio_kvm_device_fd, KVM_SET_DEVICE_ATTR, &attr)) {
>> @@ -160,6 +248,8 @@ int vfio_kvm_device_add_fd(int fd, Error **errp)
>> fd);
>> return -errno;
>> }
>> +
>> + vfio_device_fd_list_add(fd);
>> #endif
>> return 0;
>> }
>> @@ -183,6 +273,8 @@ int vfio_kvm_device_del_fd(int fd, Error **errp)
>> "Failed to remove fd %d from KVM VFIO device", fd);
>> return -errno;
>> }
>> +
>> + vfio_device_fd_list_remove(fd);
>> #endif
>> return 0;
>> }
>