diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-04-09 18:21:22 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-04-09 18:21:23 +0100 |
commit | 1e7e92e2ef874aa3a235d59b2be1da7a29b6fd29 (patch) | |
tree | bc26754782cb19637dde44443a690d95fca13ef2 /hw | |
parent | 915d34c5f99b0ab91517c69f54272bfdb6ca2b32 (diff) | |
parent | b3a184f51fbed3401694a9619e6842f882a64fee (diff) |
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20180409' into staging
Fixes for s390x: kvm, vfio-ccw, ipl code, bios. Includes a rebuild
of s390-ccw.img and s390-netboot.img.
# gpg: Signature made Mon 09 Apr 2018 16:08:19 BST
# gpg: using RSA key DECF6B93C6F02FAF
# gpg: Good signature from "Cornelia Huck <conny@cornelia-huck.de>"
# gpg: aka "Cornelia Huck <huckc@linux.vnet.ibm.com>"
# gpg: aka "Cornelia Huck <cornelia.huck@de.ibm.com>"
# gpg: aka "Cornelia Huck <cohuck@kernel.org>"
# gpg: aka "Cornelia Huck <cohuck@redhat.com>"
# Primary key fingerprint: C3D0 D66D C362 4FF6 A8C0 18CE DECF 6B93 C6F0 2FAF
* remotes/cohuck/tags/s390x-20180409:
s390x: load_psw() should only exchange the PSW for KVM
s390x/mmu: don't overwrite pending exception in mmu translate
vfio-ccw: fix memory leaks in vfio_ccw_realize()
pc-bios/s390: update images
s390: Do not pass inofficial IPL type to the guest
s390: Ensure IPL from SCSI works as expected
s390: Refactor IPL parameter block generation
s390x/kvm: call cpu_synchronize_state() on every kvm_arch_handle_exit()
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/s390x/ipl.c | 112 | ||||
-rw-r--r-- | hw/vfio/ccw.c | 2 |
2 files changed, 82 insertions, 32 deletions
diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c index fdeaec3a58..fb554ab156 100644 --- a/hw/s390x/ipl.c +++ b/hw/s390x/ipl.c @@ -279,44 +279,52 @@ static void s390_ipl_set_boot_menu(S390IPLState *ipl) *timeout = cpu_to_be32(splash_time); } +static CcwDevice *s390_get_ccw_device(DeviceState *dev_st) +{ + CcwDevice *ccw_dev = NULL; + + if (dev_st) { + VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *) + object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent), + TYPE_VIRTIO_CCW_DEVICE); + if (virtio_ccw_dev) { + ccw_dev = CCW_DEVICE(virtio_ccw_dev); + } else { + SCSIDevice *sd = (SCSIDevice *) + object_dynamic_cast(OBJECT(dev_st), + TYPE_SCSI_DEVICE); + if (sd) { + SCSIBus *bus = scsi_bus_from_device(sd); + VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus); + VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, + vdev); + + ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw), + TYPE_CCW_DEVICE); + } + } + } + return ccw_dev; +} + static bool s390_gen_initial_iplb(S390IPLState *ipl) { DeviceState *dev_st; + CcwDevice *ccw_dev = NULL; dev_st = get_boot_device(0); if (dev_st) { - VirtioCcwDevice *virtio_ccw_dev = (VirtioCcwDevice *) - object_dynamic_cast(OBJECT(qdev_get_parent_bus(dev_st)->parent), - TYPE_VIRTIO_CCW_DEVICE); + ccw_dev = s390_get_ccw_device(dev_st); + } + + /* + * Currently allow IPL only from CCW devices. + */ + if (ccw_dev) { SCSIDevice *sd = (SCSIDevice *) object_dynamic_cast(OBJECT(dev_st), TYPE_SCSI_DEVICE); - VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st), - TYPE_VIRTIO_NET); - - if (vn) { - ipl->netboot = true; - } - if (virtio_ccw_dev) { - CcwDevice *ccw_dev = CCW_DEVICE(virtio_ccw_dev); - - ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); - ipl->iplb.blk0_len = - cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); - ipl->iplb.pbt = S390_IPL_TYPE_CCW; - ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); - ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; - } else if (sd) { - SCSIBus *bus = scsi_bus_from_device(sd); - VirtIOSCSI *vdev = container_of(bus, VirtIOSCSI, bus); - VirtIOSCSICcw *scsi_ccw = container_of(vdev, VirtIOSCSICcw, vdev); - CcwDevice *ccw_dev; - - ccw_dev = (CcwDevice *)object_dynamic_cast(OBJECT(scsi_ccw), - TYPE_CCW_DEVICE); - if (!ccw_dev) { /* It might be a PCI device instead */ - return false; - } + if (sd) { ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN); ipl->iplb.blk0_len = cpu_to_be32(S390_IPLB_MIN_QEMU_SCSI_LEN - S390_IPLB_HEADER_LEN); @@ -327,12 +335,25 @@ static bool s390_gen_initial_iplb(S390IPLState *ipl) ipl->iplb.scsi.devno = cpu_to_be16(ccw_dev->sch->devno); ipl->iplb.scsi.ssid = ccw_dev->sch->ssid & 3; } else { - return false; /* unknown device */ + VirtIONet *vn = (VirtIONet *) object_dynamic_cast(OBJECT(dev_st), + TYPE_VIRTIO_NET); + + ipl->iplb.len = cpu_to_be32(S390_IPLB_MIN_CCW_LEN); + ipl->iplb.blk0_len = + cpu_to_be32(S390_IPLB_MIN_CCW_LEN - S390_IPLB_HEADER_LEN); + ipl->iplb.pbt = S390_IPL_TYPE_CCW; + ipl->iplb.ccw.devno = cpu_to_be16(ccw_dev->sch->devno); + ipl->iplb.ccw.ssid = ccw_dev->sch->ssid & 3; + + if (vn) { + ipl->netboot = true; + } } if (!s390_ipl_set_loadparm(ipl->iplb.loadparm)) { ipl->iplb.flags |= DIAG308_FLAGS_LP_VALID; } + return true; } @@ -406,7 +427,8 @@ unref_mr: return img_size; } -static bool is_virtio_net_device(IplParameterBlock *iplb) +static bool is_virtio_ccw_device_of_type(IplParameterBlock *iplb, + int virtio_id) { uint8_t cssid; uint8_t ssid; @@ -426,13 +448,23 @@ static bool is_virtio_net_device(IplParameterBlock *iplb) sch = css_find_subch(1, cssid, ssid, schid); if (sch && sch->devno == devno) { - return sch->id.cu_model == VIRTIO_ID_NET; + return sch->id.cu_model == virtio_id; } } } return false; } +static bool is_virtio_net_device(IplParameterBlock *iplb) +{ + return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_NET); +} + +static bool is_virtio_scsi_device(IplParameterBlock *iplb) +{ + return is_virtio_ccw_device_of_type(iplb, VIRTIO_ID_SCSI); +} + void s390_ipl_update_diag308(IplParameterBlock *iplb) { S390IPLState *ipl = get_ipl_device(); @@ -457,6 +489,22 @@ void s390_reipl_request(void) S390IPLState *ipl = get_ipl_device(); ipl->reipl_requested = true; + if (ipl->iplb_valid && + !ipl->netboot && + ipl->iplb.pbt == S390_IPL_TYPE_CCW && + is_virtio_scsi_device(&ipl->iplb)) { + CcwDevice *ccw_dev = s390_get_ccw_device(get_boot_device(0)); + + if (ccw_dev && + cpu_to_be16(ccw_dev->sch->devno) == ipl->iplb.ccw.devno && + (ccw_dev->sch->ssid & 3) == ipl->iplb.ccw.ssid) { + /* + * this is the original boot device's SCSI + * so restore IPL parameter info from it + */ + ipl->iplb_valid = s390_gen_initial_iplb(ipl); + } + } qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); } diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index 4e5855741a..fe34b50769 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -357,11 +357,13 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) if (strcmp(vbasedev->name, vcdev->vdev.name) == 0) { error_setg(&err, "vfio: subchannel %s has already been attached", vcdev->vdev.name); + g_free(vcdev->vdev.name); goto out_device_err; } } if (vfio_get_device(group, cdev->mdevid, &vcdev->vdev, &err)) { + g_free(vcdev->vdev.name); goto out_device_err; } |