When VFIO opens a VF, it issues a Function Level Reset which clears PCI_COMMAND_MEMORY. This unmaps all BARs, including the migration BAR.
Add a QEMU-internal BAR type flag that keeps a memory BAR mapped regardless of PCI_COMMAND_MEMORY. This is needed for host-only control regions (e.g. migration BARs) that are accessed by a VFIO variant driver, not by the guest. Assisted-by: Claude Signed-off-by: Cédric Le Goater <[email protected]> --- include/hw/pci/pci.h | 6 ++++++ hw/pci/pci.c | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index f2448e941a0b..923c8f0e15bc 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -164,6 +164,12 @@ typedef struct PCIIORegion { MemoryRegion *address_space; } PCIIORegion; +/* + * QEMU-internal: keep this BAR mapped regardless of PCI_COMMAND_MEMORY. + * Stripped before writing to config space. + */ +#define PCI_BASE_ADDRESS_MEM_ALWAYS_ON 0x10 + #define PCI_ROM_SLOT 6 #define PCI_NUM_REGIONS 7 diff --git a/hw/pci/pci.c b/hw/pci/pci.c index d3191609e283..1394132c1472 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -1544,7 +1544,8 @@ void pci_register_bar(PCIDevice *pci_dev, int region_num, } addr = pci_bar(pci_dev, region_num); - pci_set_long(pci_dev->config + addr, type); + pci_set_long(pci_dev->config + addr, + type & ~PCI_BASE_ADDRESS_MEM_ALWAYS_ON); if (!(r->type & PCI_BASE_ADDRESS_SPACE_IO) && r->type & PCI_BASE_ADDRESS_MEM_TYPE_64) { @@ -1686,7 +1687,8 @@ pcibus_t pci_bar_address(PCIDevice *d, return new_addr; } - if (!(cmd & PCI_COMMAND_MEMORY)) { + if (!(cmd & PCI_COMMAND_MEMORY) && + !(type & PCI_BASE_ADDRESS_MEM_ALWAYS_ON)) { return PCI_BAR_UNMAPPED; } new_addr = pci_config_get_bar_addr(d, reg, type, size); -- 2.55.0
