Skip to content

Commit

Permalink
s390x/pci: drive ISM reset from subsystem reset
Browse files Browse the repository at this point in the history
ISM devices are sensitive to manipulation of the IOMMU, so the ISM device
needs to be reset before the vfio-pci device is reset (triggering a full
UNMAP).  In order to ensure this occurs, trigger ISM device resets from
subsystem_reset before triggering the PCI bus reset (which will also
trigger vfio-pci reset).  This only needs to be done for ISM devices
which were enabled for use by the guest.
Further, ensure that AIF is disabled as part of the reset event.

Fixes: ef15359 ("s390x: do a subsystem reset before the unprotect on reboot")
Fixes: 0345195 ("s390x/pci: reset ISM passthrough devices on shutdown and system reset")
Reported-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com>
Message-ID: <20240118185151.265329-4-mjrosato@linux.ibm.com>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Cédric Le Goater <clg@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
  • Loading branch information
rosatomj authored and huth committed Jan 19, 2024
1 parent 30e3525 commit 68c691c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 9 deletions.
26 changes: 17 additions & 9 deletions hw/s390x/s390-pci-bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,20 +151,12 @@ static void s390_pci_shutdown_notifier(Notifier *n, void *opaque)
pci_device_reset(pbdev->pdev);
}

static void s390_pci_reset_cb(void *opaque)
{
S390PCIBusDevice *pbdev = opaque;

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);
qemu_unregister_reset(s390_pci_reset_cb, pbdev);
}

/* Unplug the PCI device */
Expand Down Expand Up @@ -1132,7 +1124,6 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
if (pbdev->pft == ZPCI_PFT_ISM) {
pbdev->shutdown_notifier.notify = s390_pci_shutdown_notifier;
qemu_register_shutdown_notifier(&pbdev->shutdown_notifier);
qemu_register_reset(s390_pci_reset_cb, pbdev);
}
} else {
pbdev->fh |= FH_SHM_EMUL;
Expand Down Expand Up @@ -1279,6 +1270,23 @@ static void s390_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev,
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);
Expand Down
8 changes: 8 additions & 0 deletions hw/s390x/s390-virtio-ccw.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ static void subsystem_reset(void)
DeviceState *dev;
int i;

/*
* ISM firmware is sensitive to unexpected changes to the IOMMU, which can
* occur during reset of the vfio-pci device (unmap of entire aperture).
* Ensure any passthrough ISM devices are reset now, while CPUs are paused
* but before vfio-pci cleanup occurs.
*/
s390_pci_ism_reset();

for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) {
dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL));
if (dev) {
Expand Down
1 change: 1 addition & 0 deletions include/hw/s390x/s390-pci-bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,5 +401,6 @@ S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s,
const char *target);
S390PCIBusDevice *s390_pci_find_next_avail_dev(S390pciState *s,
S390PCIBusDevice *pbdev);
void s390_pci_ism_reset(void);

#endif

0 comments on commit 68c691c

Please sign in to comment.