Patchwork [3/3] s390/migration: Add code to support SCLP live migration

login
register
mail settings
Submitter Christian Borntraeger
Date Nov. 21, 2012, 2:46 p.m.
Message ID <1353509165-26865-4-git-send-email-borntraeger@de.ibm.com>
Download mbox | patch
Permalink /patch/200788/
State New
Headers show

Comments

Christian Borntraeger - Nov. 21, 2012, 2:46 p.m.
From: Heinz Graalfs <graalfs@linux.vnet.ibm.com>

This patch adds the necessary life migration pieces to the sclp code.

Signed-off-by: Heinz Graalfs <graalfs@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 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(+)
Alexander Graf - Nov. 21, 2012, 2:58 p.m.
On 11/21/2012 03:46 PM, Christian Borntraeger wrote:
> From: Heinz Graalfs<graalfs@linux.vnet.ibm.com>
>
> This patch adds the necessary life migration pieces to the sclp code.

Juan, could you please review and note whether it's possible to use 
VMSTATE for this? :)


Alex

>
> Signed-off-by: Heinz Graalfs<graalfs@linux.vnet.ibm.com>
> Signed-off-by: Christian Borntraeger<borntraeger@de.ibm.com>
> ---
>   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 = {

Patch

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 = {