#ifndef HW_S390_PCI_BUS_H
#define HW_S390_PCI_BUS_H
-#include <hw/pci/pci.h>
-#include <hw/pci/pci_host.h>
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
#include "hw/s390x/sclp.h"
#include "hw/s390x/s390_flic.h"
#include "hw/s390x/css.h"
#define TYPE_S390_PCI_HOST_BRIDGE "s390-pcihost"
#define TYPE_S390_PCI_BUS "s390-pcibus"
#define TYPE_S390_PCI_DEVICE "zpci"
+#define TYPE_S390_PCI_IOMMU "s390-pci-iommu"
#define FH_MASK_ENABLE 0x80000000
#define FH_MASK_INSTANCE 0x7f000000
#define FH_MASK_SHM 0x00ff0000
-#define FH_MASK_INDEX 0x0000001f
+#define FH_MASK_INDEX 0x0000ffff
#define FH_SHM_VFIO 0x00010000
#define FH_SHM_EMUL 0x00020000
#define S390_PCIPT_ADAPTER 2
#define ZPCI_MAX_FID 0xffffffff
#define ZPCI_MAX_UID 0xffff
#define UID_UNDEFINED 0
+#define UID_CHECKING_ENABLED 0x01
+#define HOT_UNPLUG_TIMEOUT (NANOSECONDS_PER_SECOND * 60 * 5)
#define S390_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(S390pciState, (obj), TYPE_S390_PCI_HOST_BRIDGE)
OBJECT_CHECK(S390PCIBus, (obj), TYPE_S390_PCI_BUS)
#define S390_PCI_DEVICE(obj) \
OBJECT_CHECK(S390PCIBusDevice, (obj), TYPE_S390_PCI_DEVICE)
+#define S390_PCI_IOMMU(obj) \
+ OBJECT_CHECK(S390PCIIOMMU, (obj), TYPE_S390_PCI_IOMMU)
#define HP_EVENT_TO_CONFIGURED 0x0301
#define HP_EVENT_RESERVED_TO_STANDBY 0x0302
+#define HP_EVENT_DECONFIGURE_REQUEST 0x0303
#define HP_EVENT_CONFIGURED_TO_STBRES 0x0304
#define HP_EVENT_STANDBY_TO_RESERVED 0x0308
#define ZPCI_EDMA_ADDR 0x1ffffffffffffffULL
#define PAGE_SHIFT 12
+#define PAGE_SIZE (1 << PAGE_SHIFT)
#define PAGE_MASK (~(PAGE_SIZE-1))
#define PAGE_DEFAULT_ACC 0
#define PAGE_DEFAULT_KEY (PAGE_DEFAULT_ACC << 4)
* may enter an error state
* blocked: ignore all DMA and interrupts; transition back to enabled or from
* error state via mpcifc
- * error: an error occured; transition back to enabled via mpcifc
- * permanent error: an unrecoverable error occured; transition to standby via
+ * error: an error occurred; transition back to enabled via mpcifc
+ * permanent error: an unrecoverable error occurred; transition to standby via
* sclp deconfigure
*/
typedef enum {
uint32_t pba_offset;
} S390MsixInfo;
+typedef struct S390PCIBusDevice S390PCIBusDevice;
typedef struct S390PCIIOMMU {
+ Object parent_obj;
+ S390PCIBusDevice *pbdev;
AddressSpace as;
MemoryRegion mr;
+ MemoryRegion iommu_mr;
+ bool enabled;
+ uint64_t g_iota;
+ uint64_t pba;
+ uint64_t pal;
} S390PCIIOMMU;
-typedef struct S390PCIBusDevice {
+typedef struct S390PCIIOMMUTable {
+ uint64_t key;
+ S390PCIIOMMU *iommu[PCI_SLOT_MAX];
+} S390PCIIOMMUTable;
+
+struct S390PCIBusDevice {
DeviceState qdev;
PCIDevice *pdev;
ZpciState state;
- bool iommu_enabled;
char *target;
uint16_t uid;
+ uint32_t idx;
uint32_t fh;
uint32_t fid;
bool fid_defined;
- uint64_t g_iota;
- uint64_t pba;
- uint64_t pal;
uint64_t fmb_addr;
uint8_t isc;
uint16_t noi;
S390MsixInfo msix;
AdapterRoutes routes;
S390PCIIOMMU *iommu;
- MemoryRegion iommu_mr;
+ MemoryRegion msix_notify_mr;
IndAddr *summary_ind;
IndAddr *indicator;
-} S390PCIBusDevice;
+ QEMUTimer *release_timer;
+ QTAILQ_ENTRY(S390PCIBusDevice) link;
+};
typedef struct S390PCIBus {
BusState qbus;
typedef struct S390pciState {
PCIHostState parent_obj;
+ uint32_t next_idx;
+ int bus_no;
S390PCIBus *bus;
- S390PCIBusDevice *pbdev[PCI_SLOT_MAX];
- S390PCIIOMMU *iommu[PCI_SLOT_MAX];
- AddressSpace msix_notify_as;
- MemoryRegion msix_notify_mr;
+ GHashTable *iommu_table;
+ GHashTable *zpci_table;
QTAILQ_HEAD(, SeiContainer) pending_sei;
+ QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs;
} S390pciState;
+S390pciState *s390_get_phb(void);
int chsc_sei_nt2_get_event(void *res);
int chsc_sei_nt2_have_event(void);
void s390_pci_sclp_configure(SCCB *sccb);
void s390_pci_sclp_deconfigure(SCCB *sccb);
-void s390_pci_iommu_enable(S390PCIBusDevice *pbdev);
-void s390_pci_iommu_disable(S390PCIBusDevice *pbdev);
+void s390_pci_iommu_enable(S390PCIIOMMU *iommu);
+void s390_pci_iommu_disable(S390PCIIOMMU *iommu);
void s390_pci_generate_error_event(uint16_t pec, uint32_t fh, uint32_t fid,
uint64_t faddr, uint32_t e);
-S390PCIBusDevice *s390_pci_find_dev_by_idx(uint32_t idx);
-S390PCIBusDevice *s390_pci_find_dev_by_fh(uint32_t fh);
-S390PCIBusDevice *s390_pci_find_dev_by_fid(uint32_t fid);
+S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx);
+S390PCIBusDevice *s390_pci_find_dev_by_fh(S390pciState *s, uint32_t fh);
+S390PCIBusDevice *s390_pci_find_dev_by_fid(S390pciState *s, uint32_t fid);
+S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s,
+ S390PCIBusDevice *pbdev);
#endif