qemu-e2k/include/hw/pci-host/pnv_phb3.h
Cédric Le Goater 9ae1329ee2 ppc/pnv: Add models for POWER8 PHB3 PCIe Host bridge
This is a model of the PCIe Host Bridge (PHB3) found on a POWER8
processor. It includes the PowerBus logic interface (PBCQ), IOMMU
support, a single PCIe Gen.3 Root Complex, and support for MSI and LSI
interrupt sources as found on a POWER8 system using the XICS interrupt
controller.

The POWER8 processor comes in different flavors: Venice, Murano,
Naple, each having a different number of PHBs. To make things simpler,
the models provides 3 PHB3 per chip. Some platforms, like the
Firestone, can also couple PHBs on the first chip to provide more
bandwidth but this is too specific to model in QEMU.

XICS requires some adjustment to support the PHB3 MSI. The changes are
provided here but they could be decoupled in prereq patches.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Cédric Le Goater <clg@kaod.org>
Message-Id: <20200127144506.11132-3-clg@kaod.org>
[dwg: Use device_class_set_props()]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
2020-02-02 14:07:57 +11:00

165 lines
4.2 KiB
C

/*
* QEMU PowerPC PowerNV (POWER8) PHB3 model
*
* Copyright (c) 2014-2020, 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_PHB3_H
#define PCI_HOST_PNV_PHB3_H
#include "hw/pci/pcie_host.h"
#include "hw/pci/pcie_port.h"
#include "hw/ppc/xics.h"
typedef struct PnvPHB3 PnvPHB3;
/*
* PHB3 XICS Source for MSIs
*/
#define TYPE_PHB3_MSI "phb3-msi"
#define PHB3_MSI(obj) OBJECT_CHECK(Phb3MsiState, (obj), TYPE_PHB3_MSI)
#define PHB3_MAX_MSI 2048
typedef struct Phb3MsiState {
ICSState ics;
qemu_irq *qirqs;
PnvPHB3 *phb;
uint64_t rba[PHB3_MAX_MSI / 64];
uint32_t rba_sum;
} Phb3MsiState;
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,
int32_t dev_pe);
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"
#define PNV_PBCQ(obj) OBJECT_CHECK(PnvPBCQState, (obj), TYPE_PNV_PBCQ)
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;
/*
* PHB3 PCIe Root port
*/
#define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root-bus"
#define TYPE_PNV_PHB3_ROOT_PORT "pnv-phb3-root-port"
typedef struct PnvPHB3RootPort {
PCIESlot parent_obj;
} PnvPHB3RootPort;
/*
* PHB3 PCIe Host Bridge for PowerNV machines (POWER8)
*/
#define TYPE_PNV_PHB3 "pnv-phb3"
#define PNV_PHB3(obj) OBJECT_CHECK(PnvPHB3, (obj), TYPE_PNV_PHB3)
#define PNV_PHB3_NUM_M64 16
#define PNV_PHB3_NUM_REGS (0x1000 >> 3)
#define PNV_PHB3_NUM_LSI 8
#define PNV_PHB3_NUM_PE 256
#define PCI_MMIO_TOTAL_SIZE (0x1ull << 60)
struct PnvPHB3 {
PCIExpressHost parent_obj;
uint32_t chip_id;
uint32_t phb_id;
char bus_path[8];
uint64_t regs[PNV_PHB3_NUM_REGS];
MemoryRegion mr_regs;
MemoryRegion mr_m32;
MemoryRegion mr_m64[PNV_PHB3_NUM_M64];
MemoryRegion pci_mmio;
MemoryRegion pci_io;
uint64_t ioda_LIST[8];
uint64_t ioda_LXIVT[8];
uint64_t ioda_TVT[512];
uint64_t ioda_M64BT[16];
uint64_t ioda_MDT[256];
uint64_t ioda_PEEV[4];
uint32_t total_irq;
ICSState lsis;
qemu_irq *qirqs;
Phb3MsiState msis;
PnvPBCQState pbcq;
PnvPHB3RootPort root;
QLIST_HEAD(, PnvPhb3DMASpace) dma_spaces;
};
uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, unsigned size);
void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size);
void pnv_phb3_update_regions(PnvPHB3 *phb);
void pnv_phb3_remap_irqs(PnvPHB3 *phb);
#endif /* PCI_HOST_PNV_PHB3_H */