The MemoryRegions assigned with this ops shall "intercept" the accesses to unassigned pci address space and the associated callback will set MASTER ABORT bit in the STATUS register of the device that initiated the transaction as defined in PCI spec.
Note: This implementation assumes that all the reads/writes to the pci address space are done by the cpu. Signed-off-by: Marcel Apfelbaum <marce...@redhat.com> --- hw/pci/pci.c | 18 ++++++++++++++++++ include/hw/pci/pci.h | 3 +++ 2 files changed, 21 insertions(+) diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 4c004f5..f0289fc 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -2229,6 +2229,24 @@ MemoryRegion *pci_address_space_io(PCIDevice *dev) return dev->bus->address_space_io; } +static bool pci_unassigned_mem_accepts(void *opaque, hwaddr addr, + unsigned size, bool is_write) +{ + PCIDevice *d = opaque; + + /* FIXME assumption: the cpu initiated the pci transaction + * and not another pci device */ + pci_word_test_and_set_mask(d->config + PCI_STATUS, + PCI_STATUS_REC_MASTER_ABORT); + + return false; +} + +const MemoryRegionOps pci_unassigned_mem_ops = { + .valid.accepts = pci_unassigned_mem_accepts, + .endianness = DEVICE_NATIVE_ENDIAN, +}; + static void pci_device_class_init(ObjectClass *klass, void *data) { DeviceClass *k = DEVICE_CLASS(klass); diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index ccec2ba..854681c 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -329,6 +329,9 @@ int pci_device_load(PCIDevice *s, QEMUFile *f); MemoryRegion *pci_address_space(PCIDevice *dev); MemoryRegion *pci_address_space_io(PCIDevice *dev); +#define PCI_UNASSIGNED_MEM_PRIORITY -1 +extern const MemoryRegionOps pci_unassigned_mem_ops; + typedef void (*pci_set_irq_fn)(void *opaque, int irq_num, int level); typedef int (*pci_map_irq_fn)(PCIDevice *pci_dev, int irq_num); typedef PCIINTxRoute (*pci_route_irq_fn)(void *opaque, int pin); -- 1.8.3.1