summaryrefslogtreecommitdiffstats
path: root/qemu/hw/s390x/s390-pci-bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/hw/s390x/s390-pci-bus.c')
-rw-r--r--qemu/hw/s390x/s390-pci-bus.c49
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 = {