#include "hw/pci/msi.h"
#include "qemu/error-report.h"
#include "qemu/module.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
-#ifndef DEBUG_S390PCI_BUS
-#define DEBUG_S390PCI_BUS 0
-#endif
-
-#define DPRINTF(fmt, ...) \
- do { \
- if (DEBUG_S390PCI_BUS) { \
- fprintf(stderr, "S390pci-bus: " fmt, ## __VA_ARGS__); \
- } \
- } while (0)
+#include "trace.h"
S390pciState *s390_get_phb(void)
{
uint16_t rc;
if (!pbdev) {
- DPRINTF("sclp config no dev found\n");
+ trace_s390_pci_sclp_nodev("configure", be32_to_cpu(psccb->aid));
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
goto out;
}
psccb->header.response_code = cpu_to_be16(rc);
}
+static void s390_pci_shutdown_notifier(Notifier *n, void *opaque)
+{
+ S390PCIBusDevice *pbdev = container_of(n, S390PCIBusDevice,
+ shutdown_notifier);
+
+ pci_device_reset(pbdev->pdev);
+}
+
static void s390_pci_perform_unplug(S390PCIBusDevice *pbdev)
{
HotplugHandler *hotplug_ctrl;
+ if (pbdev->pft == ZPCI_PFT_ISM) {
+ notifier_remove(&pbdev->shutdown_notifier);
+ }
+
/* Unplug the PCI device */
if (pbdev->pdev) {
DeviceState *pdev = DEVICE(pbdev->pdev);
uint16_t rc;
if (!pbdev) {
- DPRINTF("sclp deconfig no dev found\n");
+ trace_s390_pci_sclp_nodev("deconfigure", be32_to_cpu(psccb->aid));
rc = SCLP_RC_ADAPTER_ID_NOT_RECOGNIZED;
goto out;
}
return ret;
}
- DPRINTF("iommu trans addr 0x%" PRIx64 "\n", addr);
+ trace_s390_pci_iommu_xlate(addr);
if (addr < iommu->pba || addr > iommu->pal) {
error = ERR_EVENT_OORANGE;
return &iommu->as;
}
+static const PCIIOMMUOps s390_iommu_ops = {
+ .get_address_space = s390_pci_dma_iommu,
+};
+
static uint8_t set_ind_atomic(uint64_t ind_loc, uint8_t to_be_set)
{
uint8_t expected, actual;
uint32_t sum_bit;
assert(pbdev);
- DPRINTF("write_msix data 0x%" PRIx64 " idx %d vec 0x%x\n", data,
- pbdev->idx, vec);
+
+ trace_s390_pci_msi_ctrl_write(data, pbdev->idx, vec);
if (pbdev->state != ZPCI_FS_ENABLED) {
return;
object_unref(OBJECT(iommu));
}
-S390PCIGroup *s390_group_create(int id)
+S390PCIGroup *s390_group_create(int id, int host_id)
{
S390PCIGroup *group;
S390pciState *s = s390_get_phb();
group = g_new0(S390PCIGroup, 1);
group->id = id;
+ group->host_id = host_id;
QTAILQ_INSERT_TAIL(&s->zpci_groups, group, link);
return group;
}
return NULL;
}
+S390PCIGroup *s390_group_find_host_sim(int host_id)
+{
+ S390PCIGroup *group;
+ S390pciState *s = s390_get_phb();
+
+ QTAILQ_FOREACH(group, &s->zpci_groups, link) {
+ if (group->id >= ZPCI_SIM_GRP_START && group->host_id == host_id) {
+ return group;
+ }
+ }
+ return NULL;
+}
+
static void s390_pci_init_default_group(void)
{
S390PCIGroup *group;
ClpRspQueryPciGrp *resgrp;
- group = s390_group_create(ZPCI_DEFAULT_FN_GRP);
+ group = s390_group_create(ZPCI_DEFAULT_FN_GRP, ZPCI_DEFAULT_FN_GRP);
resgrp = &group->zpci_group;
resgrp->fr = 1;
resgrp->dasm = 0;
PCIHostState *phb = PCI_HOST_BRIDGE(dev);
S390pciState *s = S390_PCI_HOST_BRIDGE(dev);
- DPRINTF("host_init\n");
+ trace_s390_pcihost("realize");
b = pci_register_root_bus(dev, NULL, s390_pci_set_irq, s390_pci_map_irq,
NULL, get_system_memory(), get_system_io(), 0,
64, TYPE_PCI_BUS);
- pci_setup_iommu(b, s390_pci_dma_iommu, s);
+ pci_setup_iommu(b, &s390_iommu_ops, s);
bus = BUS(b);
qbus_set_hotplug_handler(bus, OBJECT(dev));
NULL, g_free);
s->zpci_table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, NULL);
s->bus_no = 0;
+ s->next_sim_grp = ZPCI_SIM_GRP_START;
QTAILQ_INIT(&s->pending_sei);
QTAILQ_INIT(&s->zpci_devs);
QTAILQ_INIT(&s->zpci_dma_limit);
pdev = PCI_DEVICE(dev);
pci_bridge_map_irq(pb, dev->id, s390_pci_map_irq);
- pci_setup_iommu(&pb->sec_bus, s390_pci_dma_iommu, s);
+ pci_setup_iommu(&pb->sec_bus, &s390_iommu_ops, s);
qbus_set_hotplug_handler(BUS(&pb->sec_bus), OBJECT(s));
return;
}
} else {
- DPRINTF("zPCI interpretation facilities missing.\n");
+ trace_s390_pcihost("zPCI interpretation missing");
pbdev->interp = false;
pbdev->forwarding_assist = false;
}
pbdev->fh |= FH_SHM_VFIO;
pbdev->forwarding_assist = false;
}
+ /* Register shutdown notifier and reset callback for ISM devices */
+ if (pbdev->pft == ZPCI_PFT_ISM) {
+ pbdev->shutdown_notifier.notify = s390_pci_shutdown_notifier;
+ qemu_register_shutdown_notifier(&pbdev->shutdown_notifier);
+ }
} else {
pbdev->fh |= FH_SHM_EMUL;
/* Always intercept emulated devices */
pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, s->bus_no, 1);
}
+void s390_pci_ism_reset(void)
+{
+ S390pciState *s = s390_get_phb();
+
+ S390PCIBusDevice *pbdev, *next;
+
+ /* Trigger reset event for each passthrough ISM device currently in-use */
+ QTAILQ_FOREACH_SAFE(pbdev, &s->zpci_devs, link, next) {
+ if (pbdev->interp && pbdev->pft == ZPCI_PFT_ISM &&
+ pbdev->fh & FH_MASK_ENABLE) {
+ s390_pci_kvm_aif_disable(pbdev);
+
+ pci_device_reset(pbdev->pdev);
+ }
+ }
+}
+
static void s390_pcihost_reset(DeviceState *dev)
{
S390pciState *s = S390_PCI_HOST_BRIDGE(dev);