Add recovery flags, a sequence number, a saved PCI_COMMAND value and an eventfd for recovery notifications. Initialize the per-open state at open and clear it at close. Track the host transaction separately from the userspace session. The host-active flag survives close so a later patch can reject reopen until the outstanding recovery completes. Signed-off-by: Shameer Kolothum --- include/linux/vfio_pci_core.h | 19 ++++++++++++++++++- drivers/vfio/pci/vfio_pci_core.c | 11 +++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h index 1dc9630dc740..61d21c3f8089 100644 --- a/include/linux/vfio_pci_core.h +++ b/include/linux/vfio_pci_core.h @@ -96,6 +96,11 @@ static inline int vfio_pci_core_get_dmabuf_phys( } #endif +#define VFIO_PCI_RECOVERY_IN_PROGRESS BIT(0) +#define VFIO_PCI_RECOVERY_FROZEN BIT(1) +#define VFIO_PCI_RECOVERY_RESET BIT(2) +#define VFIO_PCI_RECOVERY_FAILED BIT(3) + struct vfio_pci_core_device { struct vfio_device vdev; struct pci_dev *pdev; @@ -143,6 +148,7 @@ struct vfio_pci_core_device { int ioeventfds_nr; struct vfio_pci_eventfd __rcu *err_trigger; struct vfio_pci_eventfd __rcu *req_trigger; + struct vfio_pci_eventfd __rcu *pci_recovery_trigger; struct eventfd_ctx *pm_wake_eventfd_ctx; struct list_head dummy_resources_list; struct mutex ioeventfds_lock; @@ -168,7 +174,18 @@ struct vfio_pci_core_device { bool access_blocked; /* Set after open completes, cleared before close tears down state. */ bool device_open; - struct mutex access_lock; /* gate flag writers */ + struct mutex access_lock; /* gate and recovery state writers */ + u32 pci_recovery_flags; + u64 pci_recovery_sequence; + /* Saved PCI_COMMAND, valid when pci_recovery_command_valid is set. */ + u16 pci_recovery_command; + bool pci_recovery_enabled; + bool pci_recovery_command_valid; + /* + * Host recovery in progress, protected by access_lock. Unlike the + * per-open recovery flags, this is preserved across close. + */ + bool pci_recovery_host_active; struct list_head dmabufs; }; diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index 92497224f471..667c5813f6c7 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -845,8 +845,11 @@ void vfio_pci_core_close_device(struct vfio_device *core_vdev) if (vdev->pci_recovery_supported) { scoped_guard(mutex, &vdev->access_lock) { + WRITE_ONCE(vdev->pci_recovery_enabled, false); + vdev->pci_recovery_command_valid = false; WRITE_ONCE(vdev->access_blocked, false); WRITE_ONCE(vdev->device_open, false); + WRITE_ONCE(vdev->pci_recovery_flags, 0); } } @@ -866,6 +869,10 @@ void vfio_pci_core_close_device(struct vfio_device *core_vdev) mutex_lock(&vdev->igate); vfio_pci_eventfd_replace_locked(vdev, &vdev->err_trigger, NULL); vfio_pci_eventfd_replace_locked(vdev, &vdev->req_trigger, NULL); + if (vdev->pci_recovery_supported) + vfio_pci_eventfd_replace_locked(vdev, + &vdev->pci_recovery_trigger, + NULL); mutex_unlock(&vdev->igate); } EXPORT_SYMBOL_GPL(vfio_pci_core_close_device); @@ -885,6 +892,10 @@ void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev) if (vdev->pci_recovery_supported) { guard(mutex)(&vdev->access_lock); + WRITE_ONCE(vdev->pci_recovery_flags, 0); + vdev->pci_recovery_sequence = 0; + vdev->pci_recovery_command_valid = false; + WRITE_ONCE(vdev->pci_recovery_enabled, false); WRITE_ONCE(vdev->access_blocked, false); WRITE_ONCE(vdev->device_open, true); } -- 2.43.0