Skip to content

Commit

Permalink
spapr_pci: map the MSI window in each PHB
Browse files Browse the repository at this point in the history
On sPAPR, virtio devices are connected to the PCI bus and use MSI-X.
Commit cc943c3 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>
(cherry picked from commit 8c46f7e)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
  • Loading branch information
gkurz authored and mdroth committed Dec 24, 2014
1 parent e4fb3de commit 490a0f8
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 33 deletions.
1 change: 0 additions & 1 deletion hw/ppc/spapr.c
Expand Up @@ -1377,7 +1377,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);
Expand Down
53 changes: 24 additions & 29 deletions hw/ppc/spapr_pci.c
Expand Up @@ -341,7 +341,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 */
Expand Down Expand Up @@ -465,34 +465,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
*/
Expand All @@ -512,6 +484,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;
Expand Down Expand Up @@ -604,6 +577,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);
Expand Down
2 changes: 1 addition & 1 deletion include/hw/pci-host/spapr.h
Expand Up @@ -70,7 +70,7 @@ struct sPAPRPHBState {

MemoryRegion memspace, iospace;
hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size;
MemoryRegion memwindow, iowindow;
MemoryRegion memwindow, iowindow, msiwindow;

uint32_t dma_liobn;
AddressSpace iommu_as;
Expand Down
2 changes: 0 additions & 2 deletions include/hw/ppc/spapr.h
Expand Up @@ -13,8 +13,6 @@ struct sPAPRNVRAM;
typedef struct sPAPREnvironment {
struct VIOsPAPRBus *vio_bus;
QLIST_HEAD(, sPAPRPHBState) phbs;
hwaddr msi_win_addr;
MemoryRegion msiwindow;
struct sPAPRNVRAM *nvram;
XICSState *icp;

Expand Down

0 comments on commit 490a0f8

Please sign in to comment.