Signed-off-by: Heinz Graalfs<address@hidden>
Signed-off-by: Christian Borntraeger<address@hidden>
---
hw/s390x/event-facility.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
hw/s390x/event-facility.h | 3 +++
hw/s390x/sclpconsole.c | 46 +++++++++++++++++++++++++++++++++++++++++++++
hw/s390x/sclpquiesce.c | 18 ++++++++++++++++++
4 files changed, 113 insertions(+)
diff --git a/hw/s390x/event-facility.c b/hw/s390x/event-facility.c
index 9367660..47a1bab 100644
--- a/hw/s390x/event-facility.c
+++ b/hw/s390x/event-facility.c
@@ -312,6 +312,49 @@ static void command_handler(SCLPEventFacility *ef, SCCB
*sccb, uint64_t code)
}
}
+static void event_facility_save(QEMUFile *f, void *opaque)
+{
+ S390SCLPDevice *sdev = opaque;
+ BusChild *kid;
+ SCLPEvent *event;
+ SCLPEventClass *event_class;
+
+ qemu_put_be32(f, sdev->ef->receive_mask);
+
+ QTAILQ_FOREACH(kid,&sdev->ef->sbus.qbus.children, sibling) {
+ DeviceState *qdev = kid->child;
+ event = DO_UPCAST(SCLPEvent, qdev, qdev);
+ event_class = SCLP_EVENT_GET_CLASS(event);
+ if (event_class->save) {
+ event_class->save(f, event);
+ }
+ }
+}
+
+static int event_facility_load(QEMUFile *f, void *opaque, int version_id)
+{
+ S390SCLPDevice *sdev = opaque;
+ int rc = 0;
+ BusChild *kid;
+ SCLPEvent *event;
+ SCLPEventClass *event_class;
+
+ sdev->ef->receive_mask = qemu_get_be32(f);
+
+ QTAILQ_FOREACH(kid,&sdev->ef->sbus.qbus.children, sibling) {
+ DeviceState *qdev = kid->child;
+ event = DO_UPCAST(SCLPEvent, qdev, qdev);
+ event_class = SCLP_EVENT_GET_CLASS(event);
+ if (event_class->load) {
+ rc = event_class->load(f, event, version_id);
+ if (rc) {
+ break;
+ }
+ }
+ }
+ return rc;
+}
+
static int init_event_facility(S390SCLPDevice *sdev)
{
SCLPEventFacility *event_facility;
@@ -334,6 +377,9 @@ static int init_event_facility(S390SCLPDevice *sdev)
}
qdev_init_nofail(quiesce);
+ register_savevm(&sdev->busdev.qdev, "event-facility", -1, 0,
+ event_facility_save, event_facility_load, sdev);
+
return 0;
}
diff --git a/hw/s390x/event-facility.h b/hw/s390x/event-facility.h
index 30af0a7..4405022 100644
--- a/hw/s390x/event-facility.h
+++ b/hw/s390x/event-facility.h
@@ -91,6 +91,9 @@ typedef struct SCLPEventClass {
/* returns the supported event type */
int (*event_type)(void);
+ /* live migration */
+ int (*load)(QEMUFile *f, void *opaque, int version_id);
+ void (*save)(QEMUFile *f, void *opaque);
} SCLPEventClass;
#endif
diff --git a/hw/s390x/sclpconsole.c b/hw/s390x/sclpconsole.c
index 0ec5623..96168a1 100644
--- a/hw/s390x/sclpconsole.c
+++ b/hw/s390x/sclpconsole.c
@@ -243,6 +243,50 @@ static void trigger_ascii_console_data(void *env, int n,
int level)
/* qemu object creation and initialization functions */
/* tell character layer our call-back functions */
+
+static void console_save(QEMUFile *f, void *opaque)
+{
+ SCLPConsole *scon = opaque;
+
+ if (!scon->iov) {
+ return;
+ }
+
+ qemu_put_be16(f, scon->event.event_pending ? 1 : 0);
+ qemu_put_be32(f, scon->iov_data_len);
+ qemu_put_be32(f, scon->iov_sclp_rest);
+ qemu_put_be32(f, scon->iov_sclp - scon->iov);
+ qemu_put_be32(f, scon->iov_bs - scon->iov);
+ if (scon->event.event_pending) {
+ qemu_put_buffer(f, scon->iov, SIZE_BUFFER_VT220);
+ }
+}
+
+static int console_load(QEMUFile *f, void *opaque, int version_id)
+{
+ SCLPConsole *scon = opaque;
+ int l;
+
+ if (!scon->iov) {
+ scon->iov = g_malloc0(SIZE_BUFFER_VT220);
+ }
+
+ scon->event.event_pending = qemu_get_be16(f) ? true : false;
+ scon->iov_data_len = qemu_get_be32(f);
+ scon->iov_sclp_rest = qemu_get_be32(f);
+ scon->iov_bs = scon->iov + qemu_get_be32(f);
+ scon->iov_sclp = scon->iov + qemu_get_be32(f);
+ if (scon->event.event_pending) {
+ l = qemu_get_buffer(f, scon->iov, SIZE_BUFFER_VT220);
+ if (l != SIZE_BUFFER_VT220) {
+ error_report("Failed to restore SCLP console buffer.");
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
static int console_init(SCLPEvent *event)
{
static bool console_available;
@@ -288,6 +332,8 @@ static void console_class_init(ObjectClass *klass, void
*data)
ec->event_type = event_type;
ec->read_event_data = read_event_data;
ec->write_event_data = write_event_data;
+ ec->load = console_load;
+ ec->save = console_save;
}
static TypeInfo sclp_console_info = {
diff --git a/hw/s390x/sclpquiesce.c b/hw/s390x/sclpquiesce.c
index 9a773b8..e12fb7c 100644
--- a/hw/s390x/sclpquiesce.c
+++ b/hw/s390x/sclpquiesce.c
@@ -65,6 +65,22 @@ static int read_event_data(SCLPEvent *event,
EventBufferHeader *evt_buf_hdr,
return 1;
}
+static void quiesce_save(QEMUFile *f, void *opaque)
+{
+ SCLPEvent *event = opaque;
+
+ qemu_put_be16(f, event->event_pending ? 1 : 0);
+}
+
+static int quiesce_load(QEMUFile *f, void *opaque, int version_id)
+{
+ SCLPEvent *event = opaque;
+
+ event->event_pending = qemu_get_be16(f) ? true : false;
+
+ return 0;
+}
+
typedef struct QuiesceNotifier QuiesceNotifier;
static struct QuiesceNotifier {
@@ -105,6 +121,8 @@ static void quiesce_class_init(ObjectClass *klass, void
*data)
k->event_type = event_type;
k->read_event_data = read_event_data;
k->write_event_data = NULL;
+ k->load = quiesce_load;
+ k->save = quiesce_save;
}
static TypeInfo sclp_quiesce_info = {