aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-04-09 18:21:22 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-04-09 18:21:23 +0100
commit1e7e92e2ef874aa3a235d59b2be1da7a29b6fd29 (patch)
treebc26754782cb19637dde44443a690d95fca13ef2 /hw
parent915d34c5f99b0ab91517c69f54272bfdb6ca2b32 (diff)
parentb3a184f51fbed3401694a9619e6842f882a64fee (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.c112
-rw-r--r--hw/vfio/ccw.c2
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;
}