From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:60067) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZUGok-0002E1-KW for qemu-devel@nongnu.org; Tue, 25 Aug 2015 12:11:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZUGoh-0001wb-6m for qemu-devel@nongnu.org; Tue, 25 Aug 2015 12:11:22 -0400 Received: from e06smtp12.uk.ibm.com ([195.75.94.108]:59896) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZUGog-0001vU-Sm for qemu-devel@nongnu.org; Tue, 25 Aug 2015 12:11:19 -0400 Received: from /spool/local by e06smtp12.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 25 Aug 2015 17:11:17 +0100 Received: from b06cxnps3075.portsmouth.uk.ibm.com (d06relay10.portsmouth.uk.ibm.com [9.149.109.195]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id 5BB4017D8066 for ; Tue, 25 Aug 2015 17:12:53 +0100 (BST) Received: from d06av12.portsmouth.uk.ibm.com (d06av12.portsmouth.uk.ibm.com [9.149.37.247]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t7PGBEiC13303868 for ; Tue, 25 Aug 2015 16:11:14 GMT Received: from d06av12.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av12.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t7PGB4Sx017713 for ; Tue, 25 Aug 2015 10:11:05 -0600 From: Cornelia Huck Date: Tue, 25 Aug 2015 18:10:49 +0200 Message-Id: <1440519050-17986-8-git-send-email-cornelia.huck@de.ibm.com> In-Reply-To: <1440519050-17986-1-git-send-email-cornelia.huck@de.ibm.com> References: <1440519050-17986-1-git-send-email-cornelia.huck@de.ibm.com> Subject: [Qemu-devel] [PATCH v2 7/8] s390x: Migrate guest storage keys (initial memory only) List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Cornelia Huck , borntraeger@de.ibm.com, jfrei@linux.vnet.ibm.com, agraf@suse.de, jjherne@linux.vnet.ibm.com From: "Jason J. Herne" Routines to save/load guest storage keys are provided. register_savevm is called to register them as migration handlers. We prepare the protocol to support more complex parameters. So we will later be able to support standby memory (having empty holes), compression and "state live migration" like done for ram. Reviewed-by: David Hildenbrand Signed-off-by: Jason J. Herne Signed-off-by: Cornelia Huck --- hw/s390x/s390-skeys.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c index 0b13d77..9d4a79d 100644 --- a/hw/s390x/s390-skeys.c +++ b/hw/s390x/s390-skeys.c @@ -11,10 +11,14 @@ #include "hw/boards.h" #include "qmp-commands.h" +#include "migration/qemu-file.h" #include "hw/s390x/storage-keys.h" #include "qemu/error-report.h" #define S390_SKEYS_BUFFER_SIZE 131072 /* Room for 128k storage keys */ +#define S390_SKEYS_SAVE_FLAG_EOS 0x01 +#define S390_SKEYS_SAVE_FLAG_SKEYS 0x02 +#define S390_SKEYS_SAVE_FLAG_ERROR 0x04 S390SKeysState *s390_get_skeys_device(void) { @@ -247,6 +251,126 @@ static const TypeInfo qemu_s390_skeys_info = { .instance_size = sizeof(S390SKeysClass), }; +static void s390_storage_keys_save(QEMUFile *f, void *opaque) +{ + S390SKeysState *ss = S390_SKEYS(opaque); + S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); + uint64_t pages_left = ram_size / TARGET_PAGE_SIZE; + uint64_t read_count, eos = S390_SKEYS_SAVE_FLAG_EOS; + vaddr cur_gfn = 0; + int error = 0; + uint8_t *buf; + + if (!skeyclass->skeys_enabled(ss)) { + goto end_stream; + } + + buf = g_try_malloc(S390_SKEYS_BUFFER_SIZE); + if (!buf) { + error_report("storage key save could not allocate memory\n"); + goto end_stream; + } + + /* We only support initial memory. Standby memory is not handled yet. */ + qemu_put_be64(f, (cur_gfn * TARGET_PAGE_SIZE) | S390_SKEYS_SAVE_FLAG_SKEYS); + qemu_put_be64(f, pages_left); + + while (pages_left) { + read_count = MIN(pages_left, S390_SKEYS_BUFFER_SIZE); + + if (!error) { + error = skeyclass->get_skeys(ss, cur_gfn, read_count, buf); + if (error) { + /* + * If error: we want to fill the stream with valid data instead + * of stopping early so we pad the stream with 0x00 values and + * use S390_SKEYS_SAVE_FLAG_ERROR to indicate failure to the + * reading side. + */ + error_report("S390_GET_KEYS error %d\n", error); + memset(buf, 0, S390_SKEYS_BUFFER_SIZE); + eos = S390_SKEYS_SAVE_FLAG_ERROR; + } + } + + qemu_put_buffer(f, buf, read_count); + cur_gfn += read_count; + pages_left -= read_count; + } + + g_free(buf); +end_stream: + qemu_put_be64(f, eos); +} + +static int s390_storage_keys_load(QEMUFile *f, void *opaque, int version_id) +{ + S390SKeysState *ss = S390_SKEYS(opaque); + S390SKeysClass *skeyclass = S390_SKEYS_GET_CLASS(ss); + int ret = 0; + + while (!ret) { + ram_addr_t addr; + int flags; + + addr = qemu_get_be64(f); + flags = addr & ~TARGET_PAGE_MASK; + addr &= TARGET_PAGE_MASK; + + switch (flags) { + case S390_SKEYS_SAVE_FLAG_SKEYS: { + const uint64_t total_count = qemu_get_be64(f); + uint64_t handled_count = 0, cur_count; + uint64_t cur_gfn = addr / TARGET_PAGE_SIZE; + uint8_t *buf = g_try_malloc(S390_SKEYS_BUFFER_SIZE); + + if (!buf) { + error_report("storage key load could not allocate memory\n"); + ret = -ENOMEM; + break; + } + + while (handled_count < total_count) { + cur_count = MIN(total_count - handled_count, + S390_SKEYS_BUFFER_SIZE); + qemu_get_buffer(f, buf, cur_count); + + ret = skeyclass->set_skeys(ss, cur_gfn, cur_count, buf); + if (ret < 0) { + error_report("S390_SET_KEYS error %d\n", ret); + break; + } + handled_count += cur_count; + cur_gfn += cur_count; + } + g_free(buf); + break; + } + case S390_SKEYS_SAVE_FLAG_ERROR: { + error_report("Storage key data is incomplete."); + ret = -EINVAL; + break; + } + case S390_SKEYS_SAVE_FLAG_EOS: + /* normal exit */ + return 0; + default: + error_report("Unexpected storage key flag data: %#x", flags); + ret = -EINVAL; + } + } + + return ret; +} + +static void s390_skeys_instance_init(Object *obj) +{ + S390SKeysState *ss = S390_SKEYS(obj); + + register_savevm(NULL, TYPE_S390_SKEYS, 0, 1, s390_storage_keys_save, + s390_storage_keys_load, ss); +} + static void s390_skeys_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); @@ -258,6 +382,7 @@ static void s390_skeys_class_init(ObjectClass *oc, void *data) static const TypeInfo s390_skeys_info = { .name = TYPE_S390_SKEYS, .parent = TYPE_DEVICE, + .instance_init = s390_skeys_instance_init, .instance_size = sizeof(S390SKeysState), .class_init = s390_skeys_class_init, .class_size = sizeof(S390SKeysClass), -- 2.5.0