diff options
Diffstat (limited to 'qemu/hw/s390x/s390-pci-bus.c')
-rw-r--r-- | qemu/hw/s390x/s390-pci-bus.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/qemu/hw/s390x/s390-pci-bus.c b/qemu/hw/s390x/s390-pci-bus.c index 560b66a50..918b58543 100644 --- a/qemu/hw/s390x/s390-pci-bus.c +++ b/qemu/hw/s390x/s390-pci-bus.c @@ -11,6 +11,9 @@ * directory. */ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "cpu.h" #include "s390-pci-bus.h" #include <hw/pci/pci_bus.h> #include <hw/pci/msi.h> @@ -123,7 +126,6 @@ void s390_pci_sclp_configure(int configure, SCCB *sccb) } psccb->header.response_code = cpu_to_be16(rc); - return; } static uint32_t s390_pci_get_pfid(PCIDevice *pdev) @@ -308,9 +310,8 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, { uint64_t pte; uint32_t flags; - S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, mr); - S390pciState *s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev) - ->qbus.parent); + S390PCIBusDevice *pbdev = container_of(iommu, S390PCIBusDevice, iommu_mr); + S390pciState *s; IOMMUTLBEntry ret = { .target_as = &address_space_memory, .iova = 0, @@ -319,8 +320,13 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *iommu, hwaddr addr, .perm = IOMMU_NONE, }; + if (!pbdev->configured || !pbdev->pdev || !(pbdev->fh & FH_ENABLED)) { + return ret; + } + DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr); + s = S390_PCI_HOST_BRIDGE(pci_device_root_bus(pbdev->pdev)->qbus.parent); /* s390 does not have an APIC mapped to main storage so we use * a separate AddressSpace only for msix notifications */ @@ -425,6 +431,10 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, return; } + if (!(pbdev->fh & FH_ENABLED)) { + return; + } + ind_bit = pbdev->routes.adapter.ind_offset; sum_bit = pbdev->routes.adapter.summary_offset; @@ -435,8 +445,6 @@ static void s390_msi_ctrl_write(void *opaque, hwaddr addr, uint64_t data, io_int_word = (pbdev->isc << 27) | IO_INT_WORD_AI; s390_io_interrupt(0, 0, 0, io_int_word); } - - return; } static uint64_t s390_msi_ctrl_read(void *opaque, hwaddr addr, unsigned size) @@ -450,14 +458,32 @@ static const MemoryRegionOps s390_msi_ctrl_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +void s390_pcihost_iommu_configure(S390PCIBusDevice *pbdev, bool enable) +{ + pbdev->configured = false; + + if (enable) { + uint64_t size = pbdev->pal - pbdev->pba + 1; + memory_region_init_iommu(&pbdev->iommu_mr, OBJECT(&pbdev->mr), + &s390_iommu_ops, "iommu-s390", size); + memory_region_add_subregion(&pbdev->mr, pbdev->pba, &pbdev->iommu_mr); + } else { + memory_region_del_subregion(&pbdev->mr, &pbdev->iommu_mr); + } + + pbdev->configured = true; +} + static void s390_pcihost_init_as(S390pciState *s) { int i; + S390PCIBusDevice *pbdev; for (i = 0; i < PCI_SLOT_MAX; i++) { - memory_region_init_iommu(&s->pbdev[i].mr, OBJECT(s), - &s390_iommu_ops, "iommu-s390", UINT64_MAX); - address_space_init(&s->pbdev[i].as, &s->pbdev[i].mr, "iommu-pci"); + pbdev = &s->pbdev[i]; + memory_region_init(&pbdev->mr, OBJECT(s), + "iommu-root-s390", UINT64_MAX); + address_space_init(&pbdev->as, &pbdev->mr, "iommu-pci"); } memory_region_init_io(&s->msix_notify_mr, OBJECT(s), @@ -500,7 +526,7 @@ static int s390_pcihost_setup_msix(S390PCIBusDevice *pbdev) return 0; } - ctrl = pci_host_config_read_common(pbdev->pdev, pos + PCI_CAP_FLAGS, + ctrl = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_FLAGS, pci_config_size(pbdev->pdev), sizeof(ctrl)); table = pci_host_config_read_common(pbdev->pdev, pos + PCI_MSIX_TABLE, pci_config_size(pbdev->pdev), sizeof(table)); @@ -539,7 +565,6 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev, s390_pci_generate_plug_event(HP_EVENT_TO_CONFIGURED, pbdev->fh, pbdev->fid); } - return; } static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, @@ -574,7 +599,7 @@ static void s390_pcihost_class_init(ObjectClass *klass, void *data) k->init = s390_pcihost_init; hc->plug = s390_pcihost_hot_plug; hc->unplug = s390_pcihost_hot_unplug; - msi_supported = true; + msi_nonbroken = true; } static const TypeInfo s390_pcihost_info = { |