Skip to content

Commit 2b2c651

Browse files
abhsahuawilliam
authored andcommitted
vfio/pci: Invalidate mmaps and block the access in D3hot power state
According to [PCIe v5 5.3.1.4.1] for D3hot state "Configuration and Message requests are the only TLPs accepted by a Function in the D3Hot state. All other received Requests must be handled as Unsupported Requests, and all received Completions may optionally be handled as Unexpected Completions." Currently, if the vfio PCI device has been put into D3hot state and if user makes non-config related read/write request in D3hot state, these requests will be forwarded to the host and this access may cause issues on a few systems. This patch leverages the memory-disable support added in commit 'abafbc551fdd ("vfio-pci: Invalidate mmaps and block MMIO access on disabled memory")' to generate page fault on mmap access and return error for the direct read/write. If the device is D3hot state, then the error will be returned for MMIO access. The IO access generally does not make the system unresponsive so the IO access can still happen in D3hot state. The default value should be returned in this case without bringing down the complete system. Also, the power related structure fields need to be protected so we can use the same 'memory_lock' to protect these fields also. This protection is mainly needed when user changes the PCI power state by writing into PCI_PM_CTRL register. vfio_lock_and_set_power_state() wrapper function will take the required locks and then it will invoke the vfio_pci_set_power_state(). Signed-off-by: Abhishek Sahu <abhsahu@nvidia.com> Link: https://lore.kernel.org/r/20220518111612.16985-2-abhsahu@nvidia.com Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
1 parent 3ca5470 commit 2b2c651

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

drivers/vfio/pci/vfio_pci_config.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,11 +402,14 @@ bool __vfio_pci_memory_enabled(struct vfio_pci_core_device *vdev)
402402
u16 cmd = le16_to_cpu(*(__le16 *)&vdev->vconfig[PCI_COMMAND]);
403403

404404
/*
405+
* Memory region cannot be accessed if device power state is D3.
406+
*
405407
* SR-IOV VF memory enable is handled by the MSE bit in the
406408
* PF SR-IOV capability, there's therefore no need to trigger
407409
* faults based on the virtual value.
408410
*/
409-
return pdev->no_command_memory || (cmd & PCI_COMMAND_MEMORY);
411+
return pdev->current_state < PCI_D3hot &&
412+
(pdev->no_command_memory || (cmd & PCI_COMMAND_MEMORY));
410413
}
411414

412415
/*
@@ -692,6 +695,22 @@ static int __init init_pci_cap_basic_perm(struct perm_bits *perm)
692695
return 0;
693696
}
694697

698+
/*
699+
* It takes all the required locks to protect the access of power related
700+
* variables and then invokes vfio_pci_set_power_state().
701+
*/
702+
static void vfio_lock_and_set_power_state(struct vfio_pci_core_device *vdev,
703+
pci_power_t state)
704+
{
705+
if (state >= PCI_D3hot)
706+
vfio_pci_zap_and_down_write_memory_lock(vdev);
707+
else
708+
down_write(&vdev->memory_lock);
709+
710+
vfio_pci_set_power_state(vdev, state);
711+
up_write(&vdev->memory_lock);
712+
}
713+
695714
static int vfio_pm_config_write(struct vfio_pci_core_device *vdev, int pos,
696715
int count, struct perm_bits *perm,
697716
int offset, __le32 val)
@@ -718,7 +737,7 @@ static int vfio_pm_config_write(struct vfio_pci_core_device *vdev, int pos,
718737
break;
719738
}
720739

721-
vfio_pci_set_power_state(vdev, state);
740+
vfio_lock_and_set_power_state(vdev, state);
722741
}
723742

724743
return count;

0 commit comments

Comments
 (0)