aboutsummaryrefslogtreecommitdiff
path: root/hw/s390x
diff options
context:
space:
mode:
Diffstat (limited to 'hw/s390x')
-rw-r--r--hw/s390x/css.c19
-rw-r--r--hw/s390x/virtio-ccw.c6
2 files changed, 24 insertions, 1 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 1e2f26b65a..599805d275 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -15,6 +15,7 @@
#include "hw/qdev.h"
#include "qemu/error-report.h"
#include "qemu/bitops.h"
+#include "qemu/error-report.h"
#include "exec/address-spaces.h"
#include "cpu.h"
#include "hw/s390x/ioinst.h"
@@ -432,6 +433,11 @@ static int css_interpret_ccw(SubchDev *sch, hwaddr ccw_addr,
return -EINVAL;
}
+ /* We don't support MIDA. */
+ if (ccw.flags & CCW_FLAG_MIDA) {
+ return -EINVAL;
+ }
+
if (ccw.flags & CCW_FLAG_SUSPEND) {
return suspend_allowed ? -EINPROGRESS : -EINVAL;
}
@@ -1800,13 +1806,26 @@ void subch_device_save(SubchDev *s, QEMUFile *f)
int subch_device_load(SubchDev *s, QEMUFile *f)
{
SubchDev *old_s;
+ Error *err = NULL;
uint16_t old_schid = s->schid;
+ uint16_t old_devno = s->devno;
int i;
s->cssid = qemu_get_byte(f);
s->ssid = qemu_get_byte(f);
s->schid = qemu_get_be16(f);
s->devno = qemu_get_be16(f);
+ if (s->devno != old_devno) {
+ /* Only possible if machine < 2.7 (no css_dev_path) */
+
+ error_setg(&err, "%x != %x", old_devno, s->devno);
+ error_append_hint(&err, "Devno mismatch, tried to load wrong section!"
+ " Likely reason: some sequences of plug and unplug"
+ " can break migration for machine versions prior to"
+ " 2.7 (known design flaw).\n");
+ error_report_err(err);
+ return -EINVAL;
+ }
/* Re-assign subch. */
if (old_schid != s->schid) {
old_s = channel_subsys.css[s->cssid]->sch_set[s->ssid]->sch[old_schid];
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index e6a6f74be3..90d37cb9ff 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -1279,9 +1279,13 @@ static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
SubchDev *s = ccw_dev->sch;
VirtIODevice *vdev = virtio_ccw_get_vdev(s);
int len;
+ int ret;
s->driver_data = dev;
- subch_device_load(s, f);
+ ret = subch_device_load(s, f);
+ if (ret) {
+ return ret;
+ }
/* Re-fill subch_id after loading the subchannel states.*/
if (ck->refill_ids) {
ck->refill_ids(ccw_dev);