Hardware resets clear PCI TPH registers, but core PCI driver software TPH state can become stale across device open/close and reset paths. - Call pcie_disable_tph() in vfio_pci_core_enable() to reset TPH state for new user sessions - Call pcie_disable_tph() in vfio_pci_core_disable() to revert TPH state when releasing the device - Call pcie_disable_tph() after successful VFIO_DEVICE_RESET and VFIO_DEVICE_PCI_HOT_RESET ioctls to sync software state with reset hardware Ensure core PCI TPH software state always matches actual hardware state, prevent residual TPH state leakage between user sessions and after resets. Signed-off-by: Chengwen Feng --- drivers/vfio/pci/vfio_pci_core.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index ae2e0e2252a1..c509adb76955 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -614,6 +614,8 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev) vdev->reset_works = !ret; vdev->tph_opt_in = false; + /* Reset TPH status on new user session */ + pcie_disable_tph(vdev->pdev); pci_save_state(pdev); vdev->pci_saved_state = pci_store_saved_state(pdev); if (!vdev->pci_saved_state) @@ -761,6 +763,9 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev) vfio_pci_zdev_close_device(vdev); + /* Reset TPH status on exit user session */ + pcie_disable_tph(vdev->pdev); + /* * If we have saved state, restore it. If we can reset the device, * even better. Resetting with current state seems better than @@ -1562,6 +1567,7 @@ long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd, struct vfio_pci_core_device *vdev = container_of(core_vdev, struct vfio_pci_core_device, vdev); void __user *uarg = (void __user *)arg; + int ret; switch (cmd) { case VFIO_DEVICE_GET_INFO: @@ -1573,9 +1579,15 @@ long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd, case VFIO_DEVICE_IOEVENTFD: return vfio_pci_ioctl_ioeventfd(vdev, uarg); case VFIO_DEVICE_PCI_HOT_RESET: - return vfio_pci_ioctl_pci_hot_reset(vdev, uarg); + ret = vfio_pci_ioctl_pci_hot_reset(vdev, uarg); + if (!ret) + pcie_disable_tph(vdev->pdev); + return ret; case VFIO_DEVICE_RESET: - return vfio_pci_ioctl_reset(vdev, uarg); + ret = vfio_pci_ioctl_reset(vdev, uarg); + if (!ret) + pcie_disable_tph(vdev->pdev); + return ret; case VFIO_DEVICE_SET_IRQS: return vfio_pci_ioctl_set_irqs(vdev, uarg); default: -- 2.17.1