diff mbox series

[04/17] ppc/pnv: add unified pnv-phb header

Message ID 20220507190624.507419-5-danielhb413@gmail.com (mailing list archive)
State New, archived
Headers show
Series powernv: introduce pnv-phb unified devices | expand

Commit Message

Daniel Henrique Barboza May 7, 2022, 7:06 p.m. UTC
This patch adds the pnv_phb.h header with the declarations we're going
to use in this soon to be added device.

It consists of an union between all attributes of PnvPHB3 and PnvPHB4
devices. This will allow for the same PnvPHB device to be used for PHB3
and PHB4 code.

Some struct definitions from PnvPHB3 had to be moved to the new header
due to scope constraints.

Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
---
 include/hw/pci-host/pnv_phb.h  | 211 +++++++++++++++++++++++++++++++++
 include/hw/pci-host/pnv_phb3.h |  65 +---------
 2 files changed, 212 insertions(+), 64 deletions(-)
 create mode 100644 include/hw/pci-host/pnv_phb.h
diff mbox series

Patch

diff --git a/include/hw/pci-host/pnv_phb.h b/include/hw/pci-host/pnv_phb.h
new file mode 100644
index 0000000000..2a8bf9a66d
--- /dev/null
+++ b/include/hw/pci-host/pnv_phb.h
@@ -0,0 +1,211 @@ 
+/*
+ * QEMU PowerPC PowerNV Unified PHB model
+ *
+ * Copyright (c) 2022, IBM Corporation.
+ *
+ * This code is licensed under the GPL version 2 or later. See the
+ * COPYING file in the top-level directory.
+ */
+
+#ifndef PCI_HOST_PNV_PHB_H
+#define PCI_HOST_PNV_PHB_H
+
+#include "hw/pci/pcie_host.h"
+#include "hw/pci/pcie_port.h"
+#include "hw/ppc/xics.h"
+#include "hw/ppc/xive.h"
+#include "qom/object.h"
+
+/* pnv_phb3.h types */
+#define PNV_PHB3_NUM_M64      16
+#define PNV_PHB3_NUM_REGS     (0x1000 >> 3)
+#define PHB3_MAX_MSI     2048
+
+typedef struct PnvPHB3 PnvPHB3;
+typedef struct PnvChip PnvChip;
+
+typedef struct Phb3MsiState {
+    ICSState ics;
+    qemu_irq *qirqs;
+
+    PnvPHB3 *phb;
+    uint64_t rba[PHB3_MAX_MSI / 64];
+    uint32_t rba_sum;
+} Phb3MsiState;
+
+typedef struct PnvPBCQState {
+    DeviceState parent;
+
+    uint32_t nest_xbase;
+    uint32_t spci_xbase;
+    uint32_t pci_xbase;
+#define PBCQ_NEST_REGS_COUNT    0x46
+#define PBCQ_PCI_REGS_COUNT     0x15
+#define PBCQ_SPCI_REGS_COUNT    0x5
+
+    uint64_t nest_regs[PBCQ_NEST_REGS_COUNT];
+    uint64_t spci_regs[PBCQ_SPCI_REGS_COUNT];
+    uint64_t pci_regs[PBCQ_PCI_REGS_COUNT];
+    MemoryRegion mmbar0;
+    MemoryRegion mmbar1;
+    MemoryRegion phbbar;
+    uint64_t mmio0_base;
+    uint64_t mmio0_size;
+    uint64_t mmio1_base;
+    uint64_t mmio1_size;
+    PnvPHB3 *phb;
+
+    MemoryRegion xscom_nest_regs;
+    MemoryRegion xscom_pci_regs;
+    MemoryRegion xscom_spci_regs;
+} PnvPBCQState;
+
+/*
+ * We have one such address space wrapper per possible device under
+ * the PHB since they need to be assigned statically at qemu device
+ * creation time. The relationship to a PE is done later dynamically.
+ * This means we can potentially create a lot of these guys. Q35
+ * stores them as some kind of radix tree but we never really need to
+ * do fast lookups so instead we simply keep a QLIST of them for now,
+ * we can add the radix if needed later on.
+ *
+ * We do cache the PE number to speed things up a bit though.
+ */
+typedef struct PnvPhb3DMASpace {
+    PCIBus *bus;
+    uint8_t devfn;
+    int pe_num;         /* Cached PE number */
+#define PHB_INVALID_PE (-1)
+    PnvPHB3 *phb;
+    AddressSpace dma_as;
+    IOMMUMemoryRegion dma_mr;
+    MemoryRegion msi32_mr;
+    MemoryRegion msi64_mr;
+    QLIST_ENTRY(PnvPhb3DMASpace) list;
+} PnvPhb3DMASpace;
+
+/* pnv_phb4.h types */
+#define PNV_PHB4_MAX_LSIs          8
+#define PNV_PHB4_MAX_INTs          4096
+#define PNV_PHB4_MAX_MIST          (PNV_PHB4_MAX_INTs >> 2)
+#define PNV_PHB4_MAX_MMIO_WINDOWS  32
+#define PNV_PHB4_MIN_MMIO_WINDOWS  16
+#define PNV_PHB4_NUM_REGS          (0x3000 >> 3)
+#define PNV_PHB4_MAX_PEs           512
+#define PNV_PHB4_MAX_TVEs          (PNV_PHB4_MAX_PEs * 2)
+#define PNV_PHB4_MAX_PEEVs         (PNV_PHB4_MAX_PEs / 64)
+#define PNV_PHB4_MAX_MBEs          (PNV_PHB4_MAX_MMIO_WINDOWS * 2)
+typedef struct PnvPhb4PecState PnvPhb4PecState;
+
+/*
+ * Unified PHB PCIe Host Bridge for PowerNV machines
+ */
+typedef struct PnvPHB PnvPHB;
+#define TYPE_PNV_PHB "pnv-phb"
+OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB, PNV_PHB)
+
+struct PnvPHB {
+    PCIExpressHost parent_obj;
+
+    uint32_t chip_id;
+    uint32_t phb_id;
+    char bus_path[8];
+    MemoryRegion pci_mmio;
+    MemoryRegion pci_io;
+    qemu_irq *qirqs;
+
+    /*
+     * PnvPHB3 attributes
+     */
+    uint64_t regs3[PNV_PHB3_NUM_REGS];
+    MemoryRegion mr_regs3;
+
+    MemoryRegion mr_m32;
+    MemoryRegion mr_m64[PNV_PHB3_NUM_M64];
+
+    uint64_t ioda2_LIST[8];
+    uint64_t ioda2_LXIVT[8];
+    uint64_t ioda2_TVT[512];
+    uint64_t ioda2_M64BT[16];
+    uint64_t ioda2_MDT[256];
+    uint64_t ioda2_PEEV[4];
+
+    uint32_t total_irq;
+    ICSState lsis;
+    Phb3MsiState msis;
+
+    PnvPBCQState pbcq;
+
+    QLIST_HEAD(, PnvPhb3DMASpace) v3_dma_spaces;
+
+    PnvChip *chip;
+
+    /*
+     * PnvPHB4 attributes
+     */
+    uint64_t version;
+
+    /* The owner PEC */
+    PnvPhb4PecState *pec;
+
+    /* Main register images */
+    uint64_t regs[PNV_PHB4_NUM_REGS];
+    MemoryRegion mr_regs;
+
+    /* Extra SCOM-only register */
+    uint64_t scom_hv_ind_addr_reg;
+
+    /*
+     * Geometry of the PHB. There are two types, small and big PHBs, a
+     * number of resources (number of PEs, windows etc...) are doubled
+     * for a big PHB
+     */
+    bool big_phb;
+
+    /* Memory regions for MMIO space */
+    MemoryRegion mr_mmio[PNV_PHB4_MAX_MMIO_WINDOWS];
+
+    /* PCI registers (excluding pass-through) */
+#define PHB4_PEC_PCI_STK_REGS_COUNT  0xf
+    uint64_t pci_regs[PHB4_PEC_PCI_STK_REGS_COUNT];
+    MemoryRegion pci_regs_mr;
+
+    /* Nest registers */
+#define PHB4_PEC_NEST_STK_REGS_COUNT  0x17
+    uint64_t nest_regs[PHB4_PEC_NEST_STK_REGS_COUNT];
+    MemoryRegion nest_regs_mr;
+
+    /* PHB pass-through XSCOM */
+    MemoryRegion phb_regs_mr;
+
+    /* Memory windows from PowerBus to PHB */
+    MemoryRegion phbbar;
+    MemoryRegion intbar;
+    MemoryRegion mmbar0;
+    MemoryRegion mmbar1;
+    uint64_t mmio0_base;
+    uint64_t mmio0_size;
+    uint64_t mmio1_base;
+    uint64_t mmio1_size;
+
+    /* On-chip IODA tables */
+    uint64_t ioda_LIST[PNV_PHB4_MAX_LSIs];
+    uint64_t ioda_MIST[PNV_PHB4_MAX_MIST];
+    uint64_t ioda_TVT[PNV_PHB4_MAX_TVEs];
+    uint64_t ioda_MBT[PNV_PHB4_MAX_MBEs];
+    uint64_t ioda_MDT[PNV_PHB4_MAX_PEs];
+    uint64_t ioda_PEEV[PNV_PHB4_MAX_PEEVs];
+
+    /*
+     * The internal PESTA/B is 2 bits per PE split into two tables, we
+     * store them in a single array here to avoid wasting space.
+     */
+    uint8_t  ioda_PEST_AB[PNV_PHB4_MAX_PEs];
+
+    /* P9 Interrupt generation */
+    XiveSource xsrc;
+
+    QLIST_HEAD(, PnvPhb4DMASpace) dma_spaces;
+};
+
+#endif /* PCI_HOST_PNV_PHB_H */
diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h
index 35483e59c3..b6b5f91684 100644
--- a/include/hw/pci-host/pnv_phb3.h
+++ b/include/hw/pci-host/pnv_phb3.h
@@ -12,6 +12,7 @@ 
 
 #include "hw/pci/pcie_host.h"
 #include "hw/pci/pcie_port.h"
+#include "hw/pci-host/pnv_phb.h"
 #include "hw/ppc/xics.h"
 #include "qom/object.h"
 
@@ -22,21 +23,9 @@  typedef struct PnvChip PnvChip;
  * PHB3 XICS Source for MSIs
  */
 #define TYPE_PHB3_MSI "phb3-msi"
-typedef struct Phb3MsiState Phb3MsiState;
 DECLARE_INSTANCE_CHECKER(Phb3MsiState, PHB3_MSI,
                          TYPE_PHB3_MSI)
 
-#define PHB3_MAX_MSI     2048
-
-struct Phb3MsiState {
-    ICSState ics;
-    qemu_irq *qirqs;
-
-    PnvPHB3 *phb;
-    uint64_t rba[PHB3_MAX_MSI / 64];
-    uint32_t rba_sum;
-};
-
 void pnv_phb3_msi_update_config(Phb3MsiState *msis, uint32_t base,
                                 uint32_t count);
 void pnv_phb3_msi_send(Phb3MsiState *msis, uint64_t addr, uint16_t data,
@@ -44,64 +33,12 @@  void pnv_phb3_msi_send(Phb3MsiState *msis, uint64_t addr, uint16_t data,
 void pnv_phb3_msi_ffi(Phb3MsiState *msis, uint64_t val);
 void pnv_phb3_msi_pic_print_info(Phb3MsiState *msis, Monitor *mon);
 
-
-/*
- * We have one such address space wrapper per possible device under
- * the PHB since they need to be assigned statically at qemu device
- * creation time. The relationship to a PE is done later dynamically.
- * This means we can potentially create a lot of these guys. Q35
- * stores them as some kind of radix tree but we never really need to
- * do fast lookups so instead we simply keep a QLIST of them for now,
- * we can add the radix if needed later on.
- *
- * We do cache the PE number to speed things up a bit though.
- */
-typedef struct PnvPhb3DMASpace {
-    PCIBus *bus;
-    uint8_t devfn;
-    int pe_num;         /* Cached PE number */
-#define PHB_INVALID_PE (-1)
-    PnvPHB3 *phb;
-    AddressSpace dma_as;
-    IOMMUMemoryRegion dma_mr;
-    MemoryRegion msi32_mr;
-    MemoryRegion msi64_mr;
-    QLIST_ENTRY(PnvPhb3DMASpace) list;
-} PnvPhb3DMASpace;
-
 /*
  * PHB3 Power Bus Common Queue
  */
 #define TYPE_PNV_PBCQ "pnv-pbcq"
 OBJECT_DECLARE_SIMPLE_TYPE(PnvPBCQState, PNV_PBCQ)
 
-struct PnvPBCQState {
-    DeviceState parent;
-
-    uint32_t nest_xbase;
-    uint32_t spci_xbase;
-    uint32_t pci_xbase;
-#define PBCQ_NEST_REGS_COUNT    0x46
-#define PBCQ_PCI_REGS_COUNT     0x15
-#define PBCQ_SPCI_REGS_COUNT    0x5
-
-    uint64_t nest_regs[PBCQ_NEST_REGS_COUNT];
-    uint64_t spci_regs[PBCQ_SPCI_REGS_COUNT];
-    uint64_t pci_regs[PBCQ_PCI_REGS_COUNT];
-    MemoryRegion mmbar0;
-    MemoryRegion mmbar1;
-    MemoryRegion phbbar;
-    uint64_t mmio0_base;
-    uint64_t mmio0_size;
-    uint64_t mmio1_base;
-    uint64_t mmio1_size;
-    PnvPHB3 *phb;
-
-    MemoryRegion xscom_nest_regs;
-    MemoryRegion xscom_pci_regs;
-    MemoryRegion xscom_spci_regs;
-};
-
 /*
  * PHB3 PCIe Root port
  */