spapr_pci: map the MSI window in each PHB
On sPAPR, virtio devices are connected to the PCI bus and use MSI-X.
Commit cc943c36fa
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>
This commit is contained in:
parent
22ffad31d4
commit
8c46f7ec85
@ -1441,7 +1441,6 @@ static void ppc_spapr_init(MachineState *machine)
|
|||||||
spapr_create_nvram(spapr);
|
spapr_create_nvram(spapr);
|
||||||
|
|
||||||
/* Set up PCI */
|
/* Set up PCI */
|
||||||
spapr_pci_msi_init(spapr, SPAPR_PCI_MSI_WINDOW);
|
|
||||||
spapr_pci_rtas_init();
|
spapr_pci_rtas_init();
|
||||||
|
|
||||||
phb = spapr_create_phb(spapr, 0);
|
phb = spapr_create_phb(spapr, 0);
|
||||||
|
@ -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) */
|
/* 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);
|
irq, req_num);
|
||||||
|
|
||||||
/* Add MSI device to cache */
|
/* Add MSI device to cache */
|
||||||
@ -469,34 +469,6 @@ static const MemoryRegionOps spapr_msi_ops = {
|
|||||||
.endianness = DEVICE_LITTLE_ENDIAN
|
.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
|
* PHB PCI device
|
||||||
*/
|
*/
|
||||||
@ -516,6 +488,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
|
|||||||
char *namebuf;
|
char *namebuf;
|
||||||
int i;
|
int i;
|
||||||
PCIBus *bus;
|
PCIBus *bus;
|
||||||
|
uint64_t msi_window_size = 4096;
|
||||||
|
|
||||||
if (sphb->index != -1) {
|
if (sphb->index != -1) {
|
||||||
hwaddr windows_base;
|
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,
|
address_space_init(&sphb->iommu_as, &sphb->iommu_root,
|
||||||
sphb->dtbusname);
|
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_setup_iommu(bus, spapr_pci_dma_iommu, sphb);
|
||||||
|
|
||||||
pci_bus_set_route_irq_fn(bus, spapr_route_intx_pin_to_irq);
|
pci_bus_set_route_irq_fn(bus, spapr_route_intx_pin_to_irq);
|
||||||
|
@ -70,7 +70,7 @@ struct sPAPRPHBState {
|
|||||||
|
|
||||||
MemoryRegion memspace, iospace;
|
MemoryRegion memspace, iospace;
|
||||||
hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size;
|
hwaddr mem_win_addr, mem_win_size, io_win_addr, io_win_size;
|
||||||
MemoryRegion memwindow, iowindow;
|
MemoryRegion memwindow, iowindow, msiwindow;
|
||||||
|
|
||||||
uint32_t dma_liobn;
|
uint32_t dma_liobn;
|
||||||
AddressSpace iommu_as;
|
AddressSpace iommu_as;
|
||||||
|
@ -13,8 +13,6 @@ struct sPAPRNVRAM;
|
|||||||
typedef struct sPAPREnvironment {
|
typedef struct sPAPREnvironment {
|
||||||
struct VIOsPAPRBus *vio_bus;
|
struct VIOsPAPRBus *vio_bus;
|
||||||
QLIST_HEAD(, sPAPRPHBState) phbs;
|
QLIST_HEAD(, sPAPRPHBState) phbs;
|
||||||
hwaddr msi_win_addr;
|
|
||||||
MemoryRegion msiwindow;
|
|
||||||
struct sPAPRNVRAM *nvram;
|
struct sPAPRNVRAM *nvram;
|
||||||
XICSState *icp;
|
XICSState *icp;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user