diff options
author | Greg Kurz <gkurz@linux.vnet.ibm.com> | 2014-08-27 18:17:12 +0200 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-09-08 12:50:53 +0200 |
commit | 8c46f7ec85a4dd9663489b2fa2b425cd7b3653e1 (patch) | |
tree | ea8faab4745c48705c2fa530bcc2524c4a727cf1 /hw/ppc | |
parent | 22ffad31d453a82aa290bf196f904580198e8e66 (diff) |
spapr_pci: map the MSI window in each PHB
On sPAPR, virtio devices are connected to the PCI bus and use MSI-X.
Commit cc943c36faa192cd4b32af8fe5edb31894017d35 has modified MSI-X
so that writes are made using the bus master address space and follow
the IOMMU path.
Unfortunately, the IOMMU address space address space does not have an
MSI window: the notification is silently dropped in unassigned_mem_write
instead of reaching the guest... The most visible effect is that all
virtio devices are non-functional on sPAPR since then. :(
This patch does the following:
1) map the MSI window into the IOMMU address space for each PHB
- since each PHB instantiates its own IOMMU address space, we
can safely map the window at a fixed address (SPAPR_PCI_MSI_WINDOW)
- no real need to keep the MSI window setup in a separate function,
the spapr_pci_msi_init() code moves to spapr_phb_realize().
2) kill the global MSI window as it is not needed in the end
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'hw/ppc')
-rw-r--r-- | hw/ppc/spapr.c | 1 | ||||
-rw-r--r-- | hw/ppc/spapr_pci.c | 53 |
2 files changed, 24 insertions, 30 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 555a007e38..65b28ace82 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1441,7 +1441,6 @@ static void ppc_spapr_init(MachineState *machine) spapr_create_nvram(spapr); /* Set up PCI */ - spapr_pci_msi_init(spapr, SPAPR_PCI_MSI_WINDOW); spapr_pci_rtas_init(); phb = spapr_create_phb(spapr, 0); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index e894f07f84..ad0da7fdc4 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -345,7 +345,7 @@ static void rtas_ibm_change_msi(PowerPCCPU *cpu, sPAPREnvironment *spapr, } /* Setup MSI/MSIX vectors in the device (via cfgspace or MSIX BAR) */ - spapr_msi_setmsg(pdev, spapr->msi_win_addr, ret_intr_type == RTAS_TYPE_MSIX, + spapr_msi_setmsg(pdev, SPAPR_PCI_MSI_WINDOW, ret_intr_type == RTAS_TYPE_MSIX, irq, req_num); /* Add MSI device to cache */ @@ -469,34 +469,6 @@ static const MemoryRegionOps spapr_msi_ops = { .endianness = DEVICE_LITTLE_ENDIAN }; -void spapr_pci_msi_init(sPAPREnvironment *spapr, hwaddr addr) -{ - uint64_t window_size = 4096; - - /* - * As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors, - * we need to allocate some memory to catch those writes coming - * from msi_notify()/msix_notify(). - * As MSIMessage:addr is going to be the same and MSIMessage:data - * is going to be a VIRQ number, 4 bytes of the MSI MR will only - * be used. - * - * For KVM we want to ensure that this memory is a full page so that - * our memory slot is of page size granularity. - */ -#ifdef CONFIG_KVM - if (kvm_enabled()) { - window_size = getpagesize(); - } -#endif - - spapr->msi_win_addr = addr; - memory_region_init_io(&spapr->msiwindow, NULL, &spapr_msi_ops, spapr, - "msi", window_size); - memory_region_add_subregion(get_system_memory(), spapr->msi_win_addr, - &spapr->msiwindow); -} - /* * PHB PCI device */ @@ -516,6 +488,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) char *namebuf; int i; PCIBus *bus; + uint64_t msi_window_size = 4096; if (sphb->index != -1) { hwaddr windows_base; @@ -608,6 +581,28 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) address_space_init(&sphb->iommu_as, &sphb->iommu_root, sphb->dtbusname); + /* + * As MSI/MSIX interrupts trigger by writing at MSI/MSIX vectors, + * we need to allocate some memory to catch those writes coming + * from msi_notify()/msix_notify(). + * As MSIMessage:addr is going to be the same and MSIMessage:data + * is going to be a VIRQ number, 4 bytes of the MSI MR will only + * be used. + * + * For KVM we want to ensure that this memory is a full page so that + * our memory slot is of page size granularity. + */ +#ifdef CONFIG_KVM + if (kvm_enabled()) { + msi_window_size = getpagesize(); + } +#endif + + memory_region_init_io(&sphb->msiwindow, NULL, &spapr_msi_ops, spapr, + "msi", msi_window_size); + memory_region_add_subregion(&sphb->iommu_root, SPAPR_PCI_MSI_WINDOW, + &sphb->msiwindow); + pci_setup_iommu(bus, spapr_pci_dma_iommu, sphb); pci_bus_set_route_irq_fn(bus, spapr_route_intx_pin_to_irq); |