aboutsummaryrefslogtreecommitdiff
path: root/hw/pci/pci_host.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/pci/pci_host.c')
-rw-r--r--hw/pci/pci_host.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c
index 7af8afdcbe..a18aa0a8d4 100644
--- a/hw/pci/pci_host.c
+++ b/hw/pci/pci_host.c
@@ -62,6 +62,17 @@ static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit)
}
}
+static bool is_pci_dev_ejected(PCIDevice *pci_dev)
+{
+ /*
+ * device unplug was requested and the guest acked it,
+ * so we stop responding config accesses even if the
+ * device is not deleted (failover flow)
+ */
+ return pci_dev && pci_dev->partially_hotplugged &&
+ !pci_dev->qdev.pending_deleted_event;
+}
+
void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
uint32_t limit, uint32_t val, uint32_t len)
{
@@ -75,7 +86,7 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
* allowing direct removal of unexposed functions.
*/
if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) ||
- !pci_dev->has_power) {
+ !pci_dev->has_power || is_pci_dev_ejected(pci_dev)) {
return;
}
@@ -100,7 +111,7 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
* allowing direct removal of unexposed functions.
*/
if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) ||
- !pci_dev->has_power) {
+ !pci_dev->has_power || is_pci_dev_ejected(pci_dev)) {
return ~0x0;
}