]> git.proxmox.com Git - qemu.git/blobdiff - hw/spapr_pci.c
hw: include hw header files with full paths
[qemu.git] / hw / spapr_pci.c
index b92583a99124e501c137709ddebf1ae71cb8d85e..36adbc5592428db42ec9e7524ced3e3925c6ee92 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE.
  */
-#include "hw.h"
-#include "pci.h"
-#include "msi.h"
-#include "msix.h"
-#include "pci_host.h"
+#include "hw/hw.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+#include "hw/pci/pci_host.h"
 #include "hw/spapr.h"
 #include "hw/spapr_pci.h"
-#include "exec-memory.h"
+#include "exec/address-spaces.h"
 #include <libfdt.h>
 #include "trace.h"
 
-#include "hw/pci_internals.h"
+#include "hw/pci/pci_bus.h"
 
 /* Copied from the kernel arch/powerpc/platforms/pseries/msi.c */
 #define RTAS_QUERY_FN           0
 
 static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid)
 {
-    sPAPRPHBState *phb;
+    sPAPRPHBState *sphb;
 
-    QLIST_FOREACH(phb, &spapr->phbs, list) {
-        if (phb->buid != buid) {
+    QLIST_FOREACH(sphb, &spapr->phbs, list) {
+        if (sphb->buid != buid) {
             continue;
         }
-        return phb;
+        return sphb;
     }
 
     return NULL;
@@ -63,7 +63,9 @@ static sPAPRPHBState *find_phb(sPAPREnvironment *spapr, uint64_t buid)
 static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid,
                            uint32_t config_addr)
 {
-    sPAPRPHBState *phb = find_phb(spapr, buid);
+    sPAPRPHBState *sphb = find_phb(spapr, buid);
+    PCIHostState *phb = PCI_HOST_BRIDGE(sphb);
+    BusState *bus = BUS(phb->bus);
     BusChild *kid;
     int devfn = (config_addr >> 8) & 0xFF;
 
@@ -71,7 +73,7 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr, uint64_t buid,
         return NULL;
     }
 
-    QTAILQ_FOREACH(kid, &phb->host_state.bus->qbus.children, sibling) {
+    QTAILQ_FOREACH(kid, &bus->children, sibling) {
         PCIDevice *dev = (PCIDevice *)kid->child;
         if (dev->devfn == devfn) {
             return dev;
@@ -256,7 +258,7 @@ static int spapr_msicfg_find(sPAPRPHBState *phb, uint32_t config_addr,
  * This is required for msi_notify()/msix_notify() which
  * will write at the addresses via spapr_msi_write().
  */
-static void spapr_msi_setmsg(PCIDevice *pdev, target_phys_addr_t addr,
+static void spapr_msi_setmsg(PCIDevice *pdev, hwaddr addr,
                              bool msix, unsigned req_num)
 {
     unsigned i;
@@ -349,7 +351,7 @@ static void rtas_ibm_change_msi(sPAPREnvironment *spapr,
 
     /* There is no cached config, allocate MSIs */
     if (!phb->msi_table[ndev].nvec) {
-        irq = spapr_allocate_irq_block(req_num, XICS_MSI);
+        irq = spapr_allocate_irq_block(req_num, false);
         if (irq < 0) {
             fprintf(stderr, "Cannot allocate MSIs for device#%d", ndev);
             rtas_st(rets, 0, -1); /* Hardware error */
@@ -433,11 +435,11 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
      */
     sPAPRPHBState *phb = opaque;
 
-    trace_spapr_pci_lsi_set(phb->busname, irq_num, phb->lsi_table[irq_num].irq);
+    trace_spapr_pci_lsi_set(phb->dtbusname, irq_num, phb->lsi_table[irq_num].irq);
     qemu_set_irq(spapr_phb_lsi_qirq(phb, irq_num), level);
 }
 
-static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr,
+static uint64_t spapr_io_read(void *opaque, hwaddr addr,
                               unsigned size)
 {
     switch (size) {
@@ -451,7 +453,7 @@ static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr,
     assert(0);
 }
 
-static void spapr_io_write(void *opaque, target_phys_addr_t addr,
+static void spapr_io_write(void *opaque, hwaddr addr,
                            uint64_t data, unsigned size)
 {
     switch (size) {
@@ -481,7 +483,7 @@ static const MemoryRegionOps spapr_io_ops = {
  * data is set to 0.
  * For MSI, the vector number is encoded in least bits in data.
  */
-static void spapr_msi_write(void *opaque, target_phys_addr_t addr,
+static void spapr_msi_write(void *opaque, hwaddr addr,
                             uint64_t data, unsigned size)
 {
     sPAPRPHBState *phb = opaque;
@@ -514,23 +516,80 @@ static DMAContext *spapr_pci_dma_context_fn(PCIBus *bus, void *opaque,
 
 static int spapr_phb_init(SysBusDevice *s)
 {
-    sPAPRPHBState *phb = DO_UPCAST(sPAPRPHBState, host_state.busdev, s);
+    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
+    PCIHostState *phb = PCI_HOST_BRIDGE(s);
     char *namebuf;
     int i;
     PCIBus *bus;
 
-    phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid);
-    namebuf = alloca(strlen(phb->dtbusname) + 32);
+    if (sphb->index != -1) {
+        hwaddr windows_base;
+
+        if ((sphb->buid != -1) || (sphb->dma_liobn != -1)
+            || (sphb->mem_win_addr != -1)
+            || (sphb->io_win_addr != -1)
+            || (sphb->msi_win_addr != -1)) {
+            fprintf(stderr, "Either \"index\" or other parameters must"
+                    " be specified for PAPR PHB, not both\n");
+            return -1;
+        }
+
+        sphb->buid = SPAPR_PCI_BASE_BUID + sphb->index;
+        sphb->dma_liobn = SPAPR_PCI_BASE_LIOBN + sphb->index;
+
+        windows_base = SPAPR_PCI_WINDOW_BASE
+            + sphb->index * SPAPR_PCI_WINDOW_SPACING;
+        sphb->mem_win_addr = windows_base + SPAPR_PCI_MMIO_WIN_OFF;
+        sphb->io_win_addr = windows_base + SPAPR_PCI_IO_WIN_OFF;
+        sphb->msi_win_addr = windows_base + SPAPR_PCI_MSI_WIN_OFF;
+    }
+
+    if (sphb->buid == -1) {
+        fprintf(stderr, "BUID not specified for PHB\n");
+        return -1;
+    }
+
+    if (sphb->dma_liobn == -1) {
+        fprintf(stderr, "LIOBN not specified for PHB\n");
+        return -1;
+    }
+
+    if (sphb->mem_win_addr == -1) {
+        fprintf(stderr, "Memory window address not specified for PHB\n");
+        return -1;
+    }
+
+    if (sphb->io_win_addr == -1) {
+        fprintf(stderr, "IO window address not specified for PHB\n");
+        return -1;
+    }
+
+    if (sphb->msi_win_addr == -1) {
+        fprintf(stderr, "MSI window address not specified for PHB\n");
+        return -1;
+    }
+
+    if (find_phb(spapr, sphb->buid)) {
+        fprintf(stderr, "PCI host bridges must have unique BUIDs\n");
+        return -1;
+    }
+
+    sphb->dtbusname = g_strdup_printf("pci@%" PRIx64, sphb->buid);
+    if (!sphb->busname) {
+        sphb->busname = sphb->dtbusname;
+    }
+
+    namebuf = alloca(strlen(sphb->dtbusname) + 32);
 
     /* Initialize memory regions */
-    sprintf(namebuf, "%s.mmio", phb->dtbusname);
-    memory_region_init(&phb->memspace, namebuf, INT64_MAX);
+    sprintf(namebuf, "%s.mmio", sphb->dtbusname);
+    memory_region_init(&sphb->memspace, namebuf, INT64_MAX);
 
-    sprintf(namebuf, "%s.mmio-alias", phb->dtbusname);
-    memory_region_init_alias(&phb->memwindow, namebuf, &phb->memspace,
-                             SPAPR_PCI_MEM_WIN_BUS_OFFSET, phb->mem_win_size);
-    memory_region_add_subregion(get_system_memory(), phb->mem_win_addr,
-                                &phb->memwindow);
+    sprintf(namebuf, "%s.mmio-alias", sphb->dtbusname);
+    memory_region_init_alias(&sphb->memwindow, namebuf, &sphb->memspace,
+                             SPAPR_PCI_MEM_WIN_BUS_OFFSET, sphb->mem_win_size);
+    memory_region_add_subregion(get_system_memory(), sphb->mem_win_addr,
+                                &sphb->memwindow);
 
     /* On ppc, we only have MMIO no specific IO space from the CPU
      * perspective.  In theory we ought to be able to embed the PCI IO
@@ -540,42 +599,44 @@ static int spapr_phb_init(SysBusDevice *s)
      * system io address space.  This hack to bounce things via
      * system_io works around the problem until all the users of
      * old_portion are updated */
-    sprintf(namebuf, "%s.io", phb->dtbusname);
-    memory_region_init(&phb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
+    sprintf(namebuf, "%s.io", sphb->dtbusname);
+    memory_region_init(&sphb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
     /* FIXME: fix to support multiple PHBs */
-    memory_region_add_subregion(get_system_io(), 0, &phb->iospace);
+    memory_region_add_subregion(get_system_io(), 0, &sphb->iospace);
 
-    sprintf(namebuf, "%s.io-alias", phb->dtbusname);
-    memory_region_init_io(&phb->iowindow, &spapr_io_ops, phb,
+    sprintf(namebuf, "%s.io-alias", sphb->dtbusname);
+    memory_region_init_io(&sphb->iowindow, &spapr_io_ops, sphb,
                           namebuf, SPAPR_PCI_IO_WIN_SIZE);
-    memory_region_add_subregion(get_system_memory(), phb->io_win_addr,
-                                &phb->iowindow);
+    memory_region_add_subregion(get_system_memory(), sphb->io_win_addr,
+                                &sphb->iowindow);
 
     /* 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() */
     if (msi_supported) {
-        sprintf(namebuf, "%s.msi", phb->dtbusname);
-        memory_region_init_io(&phb->msiwindow, &spapr_msi_ops, phb,
+        sprintf(namebuf, "%s.msi", sphb->dtbusname);
+        memory_region_init_io(&sphb->msiwindow, &spapr_msi_ops, sphb,
                               namebuf, SPAPR_MSIX_MAX_DEVS * 0x10000);
-        memory_region_add_subregion(get_system_memory(), phb->msi_win_addr,
-                                    &phb->msiwindow);
+        memory_region_add_subregion(get_system_memory(), sphb->msi_win_addr,
+                                    &sphb->msiwindow);
     }
 
-    bus = pci_register_bus(&phb->host_state.busdev.qdev,
-                           phb->busname ? phb->busname : phb->dtbusname,
-                           pci_spapr_set_irq, pci_spapr_map_irq, phb,
-                           &phb->memspace, &phb->iospace,
+    bus = pci_register_bus(DEVICE(s), sphb->busname,
+                           pci_spapr_set_irq, pci_spapr_map_irq, sphb,
+                           &sphb->memspace, &sphb->iospace,
                            PCI_DEVFN(0, 0), PCI_NUM_PINS);
-    phb->host_state.bus = bus;
+    phb->bus = bus;
 
-    phb->dma_liobn = SPAPR_PCI_BASE_LIOBN | (pci_find_domain(bus) << 16);
-    phb->dma_window_start = 0;
-    phb->dma_window_size = 0x40000000;
-    phb->dma = spapr_tce_new_dma_context(phb->dma_liobn, phb->dma_window_size);
-    pci_setup_iommu(bus, spapr_pci_dma_context_fn, phb);
+    sphb->dma_window_start = 0;
+    sphb->dma_window_size = 0x40000000;
+    sphb->dma = spapr_tce_new_dma_context(sphb->dma_liobn, sphb->dma_window_size);
+    if (!sphb->dma) {
+        fprintf(stderr, "Unable to create TCE table for %s\n", sphb->dtbusname);
+        return -1;
+    }
+    pci_setup_iommu(bus, spapr_pci_dma_context_fn, sphb);
 
-    QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
+    QLIST_INSERT_HEAD(&spapr->phbs, sphb, list);
 
     /* Initialize the LSI table */
     for (i = 0; i < PCI_NUM_PINS; i++) {
@@ -586,20 +647,33 @@ static int spapr_phb_init(SysBusDevice *s)
             return -1;
         }
 
-        phb->lsi_table[i].irq = irq;
+        sphb->lsi_table[i].irq = irq;
     }
 
     return 0;
 }
 
+static void spapr_phb_reset(DeviceState *qdev)
+{
+    SysBusDevice *s = SYS_BUS_DEVICE(qdev);
+    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(s);
+
+    /* Reset the IOMMU state */
+    spapr_tce_reset(sphb->dma);
+}
+
 static Property spapr_phb_properties[] = {
-    DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, 0),
     DEFINE_PROP_STRING("busname", sPAPRPHBState, busname),
-    DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, 0),
-    DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, 0x20000000),
-    DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, 0),
-    DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, 0x10000),
-    DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, 0),
+    DEFINE_PROP_INT32("index", sPAPRPHBState, index, -1),
+    DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, -1),
+    DEFINE_PROP_HEX32("liobn", sPAPRPHBState, dma_liobn, -1),
+    DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, -1),
+    DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size,
+                      SPAPR_PCI_MMIO_WIN_SIZE),
+    DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, -1),
+    DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size,
+                      SPAPR_PCI_IO_WIN_SIZE),
+    DEFINE_PROP_HEX64("msi_win_addr", sPAPRPHBState, msi_win_addr, -1),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -610,34 +684,27 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
 
     sdc->init = spapr_phb_init;
     dc->props = spapr_phb_properties;
+    dc->reset = spapr_phb_reset;
 }
 
-static TypeInfo spapr_phb_info = {
-    .name          = "spapr-pci-host-bridge",
-    .parent        = TYPE_SYS_BUS_DEVICE,
+static const TypeInfo spapr_phb_info = {
+    .name          = TYPE_SPAPR_PCI_HOST_BRIDGE,
+    .parent        = TYPE_PCI_HOST_BRIDGE,
     .instance_size = sizeof(sPAPRPHBState),
     .class_init    = spapr_phb_class_init,
 };
 
-void spapr_create_phb(sPAPREnvironment *spapr,
-                      const char *busname, uint64_t buid,
-                      uint64_t mem_win_addr, uint64_t mem_win_size,
-                      uint64_t io_win_addr, uint64_t msi_win_addr)
+PCIHostState *spapr_create_phb(sPAPREnvironment *spapr, int index,
+                               const char *busname)
 {
     DeviceState *dev;
 
-    dev = qdev_create(NULL, spapr_phb_info.name);
-
-    if (busname) {
-        qdev_prop_set_string(dev, "busname", g_strdup(busname));
-    }
-    qdev_prop_set_uint64(dev, "buid", buid);
-    qdev_prop_set_uint64(dev, "mem_win_addr", mem_win_addr);
-    qdev_prop_set_uint64(dev, "mem_win_size", mem_win_size);
-    qdev_prop_set_uint64(dev, "io_win_addr", io_win_addr);
-    qdev_prop_set_uint64(dev, "msi_win_addr", msi_win_addr);
-
+    dev = qdev_create(NULL, TYPE_SPAPR_PCI_HOST_BRIDGE);
+    qdev_prop_set_uint32(dev, "index", index);
+    qdev_prop_set_string(dev, "busname", busname);
     qdev_init_nofail(dev);
+
+    return PCI_HOST_BRIDGE(dev);
 }
 
 /* Macros to operate with address in OF binding to PCI */
@@ -750,8 +817,9 @@ void spapr_pci_rtas_init(void)
     }
 }
 
-static void register_types(void)
+static void spapr_pci_register_types(void)
 {
     type_register_static(&spapr_phb_info);
 }
-type_init(register_types)
+
+type_init(spapr_pci_register_types)