From patchwork Fri Oct 14 18:20:02 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 119901 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 967A8B7090 for ; Sat, 15 Oct 2011 05:36:02 +1100 (EST) Received: from localhost ([::1]:35369 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1REmbl-0002o0-Jo for incoming@patchwork.ozlabs.org; Fri, 14 Oct 2011 14:35:49 -0400 Received: from eggs.gnu.org ([140.186.70.92]:53595) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1REmNQ-0004Or-FY for qemu-devel@nongnu.org; Fri, 14 Oct 2011 14:21:03 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1REmNM-0005g8-H3 for qemu-devel@nongnu.org; Fri, 14 Oct 2011 14:21:00 -0400 Received: from mout.perfora.net ([74.208.4.194]:60555) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1REmNM-0005g3-15 for qemu-devel@nongnu.org; Fri, 14 Oct 2011 14:20:56 -0400 Received: from illuin.austin.ibm.com ([32.97.110.59]) by mrelay.perfora.net (node=mrus1) with ESMTP (Nemesis) id 0LlUBb-1QhdkR02ER-00ay0n; Fri, 14 Oct 2011 14:20:55 -0400 From: Michael Roth To: qemu-devel@nongnu.org Date: Fri, 14 Oct 2011 13:20:02 -0500 Message-Id: <1318616402-18474-11-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1318616402-18474-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1318616402-18474-1-git-send-email-mdroth@linux.vnet.ibm.com> X-Provags-ID: V02:K0:IbjHapiHnv06DvARM+ki512GAlKXNx/AVoL2OFLDl3l hCqhqN8mzouEaauDCgNQZ+Pi7uGNWeoKhaMmqw6avHF7v2ki5W 7fPhSRtD7eYkACg9JSX82koHvNP9G9HCfMEiE4BiCmUKMvf0b4 U5qnTBfbl+cYUIbyyctd2kWN0QNe8b8w05zT7oQGyI7zh6kzt5 Ut9ZxdPfLeceQ/tifxngWDbWOB0MP80YY81eEuaPNdKSru676H VQKfb0kdDlEovRrKY0y4hc5lLcVdsZpSUcq/8liToJ4UqVjtll 8hFm4E1gCuc/Mel7NURgRfSjI6hG0Agw4bVJwWDioW6bJZ//zr g/H22PZnplX0/2qLsZTa8jC6+mXGaXIkZihJEnKv10ehHVj2Ph 3lwRnk5DqgQgs02tgRuruVXvCwsYxgci8E= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 74.208.4.194 Cc: aliguori@us.ibm.com, mdroth@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH 10/10] vmstate: use visitors X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Michael Roth --- hw/eeprom93xx.c | 12 +- hw/fw_cfg.c | 12 +- hw/hw.h | 4 +- hw/pci.c | 38 +++-- hw/twl92230.c | 18 ++- qemu-timer.c | 24 ++- qemu-timer.h | 5 + savevm.c | 459 ++++++++++++++++++++++++++++++------------------ target-alpha/machine.c | 13 +- target-i386/machine.c | 49 ++++-- 10 files changed, 407 insertions(+), 227 deletions(-) diff --git a/hw/eeprom93xx.c b/hw/eeprom93xx.c index 4c7158d..2d6cbe7 100644 --- a/hw/eeprom93xx.c +++ b/hw/eeprom93xx.c @@ -93,14 +93,18 @@ struct _eeprom_t { This is a Big hack, but it is how the old state did it. */ -static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size) +static int get_uint16_from_uint8(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { - uint16_t *v = pv; - *v = qemu_get_ubyte(f); + uint16_t *v1 = pv; + uint8_t v2; + visit_type_uint8(v, &v2, NULL, err); + *v1 = v2; return 0; } -static void put_unused(QEMUFile *f, void *pv, size_t size) +static void put_unused(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { fprintf(stderr, "uint16_from_uint8 is used only for backwards compatibility.\n"); fprintf(stderr, "Never should be used to write a new state.\n"); diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index 8df265c..8a8033e 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -326,14 +326,18 @@ static void fw_cfg_reset(DeviceState *d) Or we broke compatibility in the state, or we can't use struct tm */ -static int get_uint32_as_uint16(QEMUFile *f, void *pv, size_t size) +static int get_uint32_as_uint16(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { - uint32_t *v = pv; - *v = qemu_get_be16(f); + uint32_t *val = pv; + uint16_t val2; + visit_type_uint16(v, &val2, name, err); + *val = val2; return 0; } -static void put_unused(QEMUFile *f, void *pv, size_t size) +static void put_unused(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { fprintf(stderr, "uint32_as_uint16 is only used for backward compatibility.\n"); fprintf(stderr, "This functions shouldn't be called.\n"); diff --git a/hw/hw.h b/hw/hw.h index e6d7c6a..f3138f2 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -303,8 +303,8 @@ typedef struct VMStateDescription VMStateDescription; struct VMStateInfo { const char *name; - int (*get)(QEMUFile *f, void *pv, size_t size); - void (*put)(QEMUFile *f, void *pv, size_t size); + int (*get)(Visitor *v, const char *name, void *pv, size_t size, Error **err); + void (*put)(Visitor *v, const char *name, void *pv, size_t size, Error **err); }; enum VMStateFlags { diff --git a/hw/pci.c b/hw/pci.c index 749e8d8..e955281 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -334,23 +334,25 @@ int pci_bus_num(PCIBus *s) return s->parent_dev->config[PCI_SECONDARY_BUS]; } -static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) +static int get_pci_config_device(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { PCIDevice *s = container_of(pv, PCIDevice, config); - uint8_t *config; + uint8_t *config = NULL; int i; assert(size == pci_config_size(s)); - config = g_malloc(size); - qemu_get_buffer(f, config, size); + visit_start_array(v, (void **)&config, name, size, 1, err); for (i = 0; i < size; ++i) { + visit_type_uint8(v, &config[i], NULL, err); if ((config[i] ^ s->config[i]) & s->cmask[i] & ~s->wmask[i] & ~s->w1cmask[i]) { g_free(config); return -EINVAL; } } + visit_end_array(v, err); memcpy(s->config, config, size); pci_update_mappings(s); @@ -360,11 +362,17 @@ static int get_pci_config_device(QEMUFile *f, void *pv, size_t size) } /* just put buffer */ -static void put_pci_config_device(QEMUFile *f, void *pv, size_t size) +static void put_pci_config_device(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { - const uint8_t **v = pv; + uint8_t *config = *(uint8_t **)pv; + int i; assert(size == pci_config_size(container_of(pv, PCIDevice, config))); - qemu_put_buffer(f, *v, size); + visit_start_array(v, (void **)&config, name, size, 1, err); + for (i = 0; i < size; i++) { + visit_type_uint8(v, &config[i], NULL, err); + } + visit_end_array(v, err); } static VMStateInfo vmstate_info_pci_config = { @@ -373,19 +381,22 @@ static VMStateInfo vmstate_info_pci_config = { .put = put_pci_config_device, }; -static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size) +static int get_pci_irq_state(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { PCIDevice *s = container_of(pv, PCIDevice, irq_state); uint32_t irq_state[PCI_NUM_PINS]; int i; + visit_start_array(v, NULL, name, PCI_NUM_PINS, 4, err); for (i = 0; i < PCI_NUM_PINS; ++i) { - irq_state[i] = qemu_get_be32(f); + visit_type_uint32(v, &irq_state[i], NULL, err); if (irq_state[i] != 0x1 && irq_state[i] != 0) { fprintf(stderr, "irq state %d: must be 0 or 1.\n", irq_state[i]); return -EINVAL; } } + visit_end_array(v, err); for (i = 0; i < PCI_NUM_PINS; ++i) { pci_set_irq_state(s, i, irq_state[i]); @@ -394,14 +405,19 @@ static int get_pci_irq_state(QEMUFile *f, void *pv, size_t size) return 0; } -static void put_pci_irq_state(QEMUFile *f, void *pv, size_t size) +static void put_pci_irq_state(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { int i; PCIDevice *s = container_of(pv, PCIDevice, irq_state); + uint32_t irq_state; + visit_start_array(v, NULL, name, PCI_NUM_PINS, 4, err); for (i = 0; i < PCI_NUM_PINS; ++i) { - qemu_put_be32(f, pci_irq_state(s, i)); + irq_state = pci_irq_state(s, i); + visit_type_uint32(v, &irq_state, NULL, err); } + visit_end_array(v, err); } static VMStateInfo vmstate_info_pci_irq_state = { diff --git a/hw/twl92230.c b/hw/twl92230.c index a75448f..732f2d6 100644 --- a/hw/twl92230.c +++ b/hw/twl92230.c @@ -742,17 +742,23 @@ static int menelaus_rx(i2c_slave *i2c) Or we broke compatibility in the state, or we can't use struct tm */ -static int get_int32_as_uint16(QEMUFile *f, void *pv, size_t size) +static int get_int32_as_uint16(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { - int *v = pv; - *v = qemu_get_be16(f); + uint32_t *val = pv; + uint16_t val2; + visit_type_uint16(v, &val2, name, err); + *val = val2; return 0; } -static void put_int32_as_uint16(QEMUFile *f, void *pv, size_t size) +static void put_int32_as_uint16(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { - int *v = pv; - qemu_put_be16(f, *v); + uint32_t *val = pv; + uint16_t val2; + visit_type_uint16(v, &val2, name, err); + *val = val2; } static const VMStateInfo vmstate_hack_int32_as_uint16 = { diff --git a/qemu-timer.c b/qemu-timer.c index ad1fc8b..ee241c3 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -629,7 +629,8 @@ void init_clocks(void) } /* save a timer */ -void qemu_put_timer(QEMUFile *f, QEMUTimer *ts) +void qemu_put_timer_visitor(Visitor *v, const char *name, QEMUTimer *ts, + Error **err) { uint64_t expire_time; @@ -638,14 +639,22 @@ void qemu_put_timer(QEMUFile *f, QEMUTimer *ts) } else { expire_time = -1; } - qemu_put_be64(f, expire_time); + visit_type_uint64(v, &expire_time, name, err); } -void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) +void qemu_put_timer(QEMUFile *f, QEMUTimer *ts) +{ + Visitor *v = qemu_file_get_output_visitor(f); + assert(v); + qemu_put_timer_visitor(v, "timer", ts, NULL); +} + +void qemu_get_timer_visitor(Visitor *v, const char *name, QEMUTimer *ts, + Error **err) { uint64_t expire_time; - expire_time = qemu_get_be64(f); + visit_type_uint64(v, &expire_time, name, err); if (expire_time != -1) { qemu_mod_timer_ns(ts, expire_time); } else { @@ -653,6 +662,13 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) } } +void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) +{ + Visitor *v = qemu_file_get_input_visitor(f); + assert(v); + qemu_get_timer_visitor(v, "timer", ts, NULL); +} + static const VMStateDescription vmstate_timers = { .name = "timer", .version_id = 2, diff --git a/qemu-timer.h b/qemu-timer.h index 0a43469..38e4343 100644 --- a/qemu-timer.h +++ b/qemu-timer.h @@ -5,6 +5,7 @@ #include "notify.h" #include #include +#include "qapi/qapi-visit-core.h" #ifdef _WIN32 #include @@ -134,7 +135,11 @@ static inline int64_t get_clock(void) #endif void qemu_get_timer(QEMUFile *f, QEMUTimer *ts); +void qemu_get_timer_visitor(Visitor *v, const char *name, QEMUTimer *ts, + Error **err); void qemu_put_timer(QEMUFile *f, QEMUTimer *ts); +void qemu_put_timer_visitor(Visitor *v, const char *name, QEMUTimer *ts, + Error **err); /* ptimer.c */ typedef struct ptimer_state ptimer_state; diff --git a/savevm.c b/savevm.c index 95135e1..d43b918 100644 --- a/savevm.c +++ b/savevm.c @@ -91,6 +91,8 @@ #define ARP_HTYPE_ETH 0x0001 #define ARP_PTYPE_IP 0x0800 #define ARP_OP_REQUEST_REV 0x3 +#define VMS_LOAD true +#define VMS_SAVE false static int announce_self_create(uint8_t *buf, uint8_t *mac_addr) @@ -182,17 +184,19 @@ static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable) /* bool */ -static int get_bool(QEMUFile *f, void *pv, size_t size) +static int get_bool(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - bool *v = pv; - *v = qemu_get_byte(f); + bool *val = pv; + visit_type_bool(v, val, name, err); return 0; } -static void put_bool(QEMUFile *f, void *pv, size_t size) +static void put_bool(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - bool *v = pv; - qemu_put_byte(f, *v); + bool *val = pv; + visit_type_bool(v, val, name, err); } const VMStateInfo vmstate_info_bool = { @@ -203,17 +207,19 @@ const VMStateInfo vmstate_info_bool = { /* 8 bit int */ -static int get_int8(QEMUFile *f, void *pv, size_t size) +static int get_int8(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - int8_t *v = pv; - qemu_get_s8s(f, v); + int8_t *val = pv; + visit_type_int8(v, val, name, err); return 0; } -static void put_int8(QEMUFile *f, void *pv, size_t size) +static void put_int8(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - int8_t *v = pv; - qemu_put_s8s(f, v); + int8_t *val = pv; + visit_type_int8(v, val, name, err); } const VMStateInfo vmstate_info_int8 = { @@ -224,17 +230,19 @@ const VMStateInfo vmstate_info_int8 = { /* 16 bit int */ -static int get_int16(QEMUFile *f, void *pv, size_t size) +static int get_int16(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - int16_t *v = pv; - qemu_get_sbe16s(f, v); + int16_t *val = pv; + visit_type_int16(v, val, name, err); return 0; } -static void put_int16(QEMUFile *f, void *pv, size_t size) +static void put_int16(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - int16_t *v = pv; - qemu_put_sbe16s(f, v); + int16_t *val = pv; + visit_type_int16(v, val, name, err); } const VMStateInfo vmstate_info_int16 = { @@ -245,17 +253,19 @@ const VMStateInfo vmstate_info_int16 = { /* 32 bit int */ -static int get_int32(QEMUFile *f, void *pv, size_t size) +static int get_int32(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - int32_t *v = pv; - qemu_get_sbe32s(f, v); + int32_t *val = pv; + visit_type_int32(v, val, name, err); return 0; } -static void put_int32(QEMUFile *f, void *pv, size_t size) +static void put_int32(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - int32_t *v = pv; - qemu_put_sbe32s(f, v); + int32_t *val = pv; + visit_type_int32(v, val, name, err); } const VMStateInfo vmstate_info_int32 = { @@ -267,13 +277,14 @@ const VMStateInfo vmstate_info_int32 = { /* 32 bit int. See that the received value is the same than the one in the field */ -static int get_int32_equal(QEMUFile *f, void *pv, size_t size) +static int get_int32_equal(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - int32_t *v = pv; + int32_t *v1 = pv; int32_t v2; - qemu_get_sbe32s(f, &v2); + visit_type_int32(v, &v2, name, err); - if (*v == v2) + if (*v1 == v2) return 0; return -EINVAL; } @@ -287,11 +298,12 @@ const VMStateInfo vmstate_info_int32_equal = { /* 32 bit int. See that the received value is the less or the same than the one in the field */ -static int get_int32_le(QEMUFile *f, void *pv, size_t size) +static int get_int32_le(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { int32_t *old = pv; int32_t new; - qemu_get_sbe32s(f, &new); + visit_type_int32(v, &new, name, err); if (*old <= new) return 0; @@ -306,17 +318,19 @@ const VMStateInfo vmstate_info_int32_le = { /* 64 bit int */ -static int get_int64(QEMUFile *f, void *pv, size_t size) +static int get_int64(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - int64_t *v = pv; - qemu_get_sbe64s(f, v); + int64_t *val = pv; + visit_type_int64(v, val, name, err); return 0; } -static void put_int64(QEMUFile *f, void *pv, size_t size) +static void put_int64(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - int64_t *v = pv; - qemu_put_sbe64s(f, v); + int64_t *val = pv; + visit_type_int64(v, val, name, err); } const VMStateInfo vmstate_info_int64 = { @@ -327,17 +341,19 @@ const VMStateInfo vmstate_info_int64 = { /* 8 bit unsigned int */ -static int get_uint8(QEMUFile *f, void *pv, size_t size) +static int get_uint8(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint8_t *v = pv; - qemu_get_8s(f, v); + uint8_t *val = pv; + visit_type_uint8(v, val, name, err); return 0; } -static void put_uint8(QEMUFile *f, void *pv, size_t size) +static void put_uint8(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint8_t *v = pv; - qemu_put_8s(f, v); + uint8_t *val = pv; + visit_type_uint8(v, val, name, err); } const VMStateInfo vmstate_info_uint8 = { @@ -348,17 +364,19 @@ const VMStateInfo vmstate_info_uint8 = { /* 16 bit unsigned int */ -static int get_uint16(QEMUFile *f, void *pv, size_t size) +static int get_uint16(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint16_t *v = pv; - qemu_get_be16s(f, v); + uint16_t *val = pv; + visit_type_uint16(v, val, name, err); return 0; } -static void put_uint16(QEMUFile *f, void *pv, size_t size) +static void put_uint16(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint16_t *v = pv; - qemu_put_be16s(f, v); + uint16_t *val = pv; + visit_type_uint16(v, val, name, err); } const VMStateInfo vmstate_info_uint16 = { @@ -369,17 +387,19 @@ const VMStateInfo vmstate_info_uint16 = { /* 32 bit unsigned int */ -static int get_uint32(QEMUFile *f, void *pv, size_t size) +static int get_uint32(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint32_t *v = pv; - qemu_get_be32s(f, v); + uint32_t *val = pv; + visit_type_uint32(v, val, name, err); return 0; } -static void put_uint32(QEMUFile *f, void *pv, size_t size) +static void put_uint32(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint32_t *v = pv; - qemu_put_be32s(f, v); + uint32_t *val = pv; + visit_type_uint32(v, val, name, err); } const VMStateInfo vmstate_info_uint32 = { @@ -391,13 +411,14 @@ const VMStateInfo vmstate_info_uint32 = { /* 32 bit uint. See that the received value is the same than the one in the field */ -static int get_uint32_equal(QEMUFile *f, void *pv, size_t size) +static int get_uint32_equal(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint32_t *v = pv; + uint32_t *v1 = pv; uint32_t v2; - qemu_get_be32s(f, &v2); + visit_type_uint32(v, &v2, name, err); - if (*v == v2) { + if (*v1 == v2) { return 0; } return -EINVAL; @@ -411,17 +432,19 @@ const VMStateInfo vmstate_info_uint32_equal = { /* 64 bit unsigned int */ -static int get_uint64(QEMUFile *f, void *pv, size_t size) +static int get_uint64(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint64_t *v = pv; - qemu_get_be64s(f, v); + uint64_t *val = pv; + visit_type_uint64(v, val, name, err); return 0; } -static void put_uint64(QEMUFile *f, void *pv, size_t size) +static void put_uint64(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint64_t *v = pv; - qemu_put_be64s(f, v); + uint64_t *val = pv; + visit_type_uint64(v, val, name, err); } const VMStateInfo vmstate_info_uint64 = { @@ -433,13 +456,14 @@ const VMStateInfo vmstate_info_uint64 = { /* 8 bit int. See that the received value is the same than the one in the field */ -static int get_uint8_equal(QEMUFile *f, void *pv, size_t size) +static int get_uint8_equal(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint8_t *v = pv; + uint8_t *v1 = pv; uint8_t v2; - qemu_get_8s(f, &v2); + visit_type_uint8(v, &v2, name, err); - if (*v == v2) + if (*v1 == v2) return 0; return -EINVAL; } @@ -453,13 +477,14 @@ const VMStateInfo vmstate_info_uint8_equal = { /* 16 bit unsigned int int. See that the received value is the same than the one in the field */ -static int get_uint16_equal(QEMUFile *f, void *pv, size_t size) +static int get_uint16_equal(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint16_t *v = pv; + uint16_t *v1 = pv; uint16_t v2; - qemu_get_be16s(f, &v2); + visit_type_uint16(v, &v2, name, err); - if (*v == v2) + if (*v1 == v2) return 0; return -EINVAL; } @@ -472,17 +497,19 @@ const VMStateInfo vmstate_info_uint16_equal = { /* timers */ -static int get_timer(QEMUFile *f, void *pv, size_t size) +static int get_timer(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - QEMUTimer *v = pv; - qemu_get_timer(f, v); + QEMUTimer *t = pv; + qemu_get_timer_visitor(v, name, t, err); return 0; } -static void put_timer(QEMUFile *f, void *pv, size_t size) +static void put_timer(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - QEMUTimer *v = pv; - qemu_put_timer(f, v); + QEMUTimer *t = pv; + qemu_put_timer_visitor(v, name, t, err); } const VMStateInfo vmstate_info_timer = { @@ -493,17 +520,29 @@ const VMStateInfo vmstate_info_timer = { /* uint8_t buffers */ -static int get_buffer(QEMUFile *f, void *pv, size_t size) +static int get_buffer(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint8_t *v = pv; - qemu_get_buffer(f, v, size); + uint8_t *val = pv; + int i; + visit_start_array(v, NULL, name, size, 1, err); + for (i = 0; i < size; i++) { + visit_type_uint8(v, &val[i], NULL, err); + } + visit_end_array(v, err); return 0; } -static void put_buffer(QEMUFile *f, void *pv, size_t size) +static void put_buffer(Visitor *v, const char *name, void *pv, size_t size, + Error **err) { - uint8_t *v = pv; - qemu_put_buffer(f, v, size); + uint8_t *val = pv; + int i; + visit_start_array(v, NULL, name, size, 1, err); + for (i = 0; i < size; i++) { + visit_type_uint8(v, &val[i], NULL, err); + } + visit_end_array(v, err); } const VMStateInfo vmstate_info_buffer = { @@ -515,29 +554,39 @@ const VMStateInfo vmstate_info_buffer = { /* unused buffers: space that was used for some fields that are not useful anymore */ -static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) +static int get_unused_buffer(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { uint8_t buf[1024]; - int block_len; + int block_len, i; + visit_start_array(v, NULL, name, size, 1, err); while (size > 0) { block_len = MIN(sizeof(buf), size); size -= block_len; - qemu_get_buffer(f, buf, block_len); + for (i = 0; i < block_len; i++) { + visit_type_uint8(v, &buf[i], NULL, err); + } } + visit_end_array(v, err); return 0; } -static void put_unused_buffer(QEMUFile *f, void *pv, size_t size) +static void put_unused_buffer(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { - static const uint8_t buf[1024]; - int block_len; + static uint8_t buf[1024]; + int block_len, i; + visit_start_array(v, NULL, name, size, 1, err); while (size > 0) { block_len = MIN(sizeof(buf), size); size -= block_len; - qemu_put_buffer(f, buf, block_len); + for (i = 0; i < block_len; i++) { + visit_type_uint8(v, &buf[i], NULL, err); + } } + visit_end_array(v, err); } const VMStateInfo vmstate_info_unused_buffer = { @@ -797,34 +846,59 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, void *opaque); -int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, - void *opaque, int version_id) +static bool vmstate_field_needed(VMStateField *field, + const VMStateDescription *vmsd, + void *opaque, int version_id, bool load) +{ + if (load) { + return ((field->field_exists && + field->field_exists(opaque, version_id)) || + (!field->field_exists && field->version_id <= version_id)); + } + return (!field->field_exists || + field->field_exists(opaque, vmsd->version_id)); +} + +static int vmstate_process(QEMUFile *f, const VMStateDescription *vmsd, + void *opaque, int version_id, bool load) { VMStateField *field = vmsd->fields; int ret; + Visitor *v; + Error *err = NULL; - if (version_id > vmsd->version_id) { - return -EINVAL; - } - if (version_id < vmsd->minimum_version_id_old) { - return -EINVAL; - } - if (version_id < vmsd->minimum_version_id) { - return vmsd->load_state_old(f, opaque, version_id); - } - if (vmsd->pre_load) { - int ret = vmsd->pre_load(opaque); - if (ret) - return ret; + if (load) { + v = qemu_file_get_input_visitor(f); + if (version_id > vmsd->version_id) { + return -EINVAL; + } + if (version_id < vmsd->minimum_version_id_old) { + return -EINVAL; + } + if (version_id < vmsd->minimum_version_id) { + return vmsd->load_state_old(f, opaque, version_id); + } + if (vmsd->pre_load) { + int ret = vmsd->pre_load(opaque); + if (ret) { + return ret; + } + } + } else { + v = qemu_file_get_output_visitor(f); + if (vmsd->pre_save) { + vmsd->pre_save(opaque); + } } + assert(v); + + visit_start_struct(v, NULL, NULL, vmsd->name, 0, &err); while(field->name) { - if ((field->field_exists && - field->field_exists(opaque, version_id)) || - (!field->field_exists && - field->version_id <= version_id)) { + if (vmstate_field_needed(field, vmsd, opaque, version_id, load)) { void *base_addr = opaque + field->offset; int i, n_elems = 1; int size = field->size; + bool is_array = false; if (field->flags & VMS_VBUFFER) { size = *(int32_t *)(opaque+field->size_offset); @@ -834,14 +908,28 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, } if (field->flags & VMS_ARRAY) { n_elems = field->num; + visit_start_array(v, NULL, field->name, n_elems, size, &err); + is_array = true; } else if (field->flags & VMS_VARRAY_INT32) { n_elems = *(int32_t *)(opaque+field->num_offset); + visit_start_array(v, NULL, field->name, n_elems, + sizeof(int32_t), &err); + is_array = true; } else if (field->flags & VMS_VARRAY_UINT32) { n_elems = *(uint32_t *)(opaque+field->num_offset); + visit_start_array(v, NULL, field->name, n_elems, + sizeof(uint32_t), &err); + is_array = true; } else if (field->flags & VMS_VARRAY_UINT16) { n_elems = *(uint16_t *)(opaque+field->num_offset); + visit_start_array(v, NULL, field->name, n_elems, + sizeof(uint16_t), &err); + is_array = true; } else if (field->flags & VMS_VARRAY_UINT8) { n_elems = *(uint8_t *)(opaque+field->num_offset); + visit_start_array(v, NULL, field->name, n_elems, + sizeof(uint8_t), &err); + is_array = true; } if (field->flags & VMS_POINTER) { base_addr = *(void **)base_addr + field->start; @@ -853,77 +941,62 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, addr = *(void **)addr; } if (field->flags & VMS_STRUCT) { - ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id); + if (load) { + ret = vmstate_load_state(f, field->vmsd, addr, + field->vmsd->version_id); + } else { + vmstate_save_state(f, field->vmsd, addr); + } } else { - ret = field->info->get(f, addr, size); - + if (load) { + ret = field->info->get(v, field->name, addr, size, &err); + } else { + field->info->put(v, field->name, addr, size, &err); + } } - if (ret < 0) { + if (load && ret < 0) { return ret; } } + if (is_array) { + visit_end_array(v, &err); + } } field++; } - ret = vmstate_subsection_load(f, vmsd, opaque); - if (ret != 0) { - return ret; + + if (load) { + if (error_is_set(&err)) { + error_report("error loading state: %s", error_get_pretty(err)); + error_free(err); + return -EINVAL; + } + ret = vmstate_subsection_load(f, vmsd, opaque); + if (ret != 0) { + return ret; + } + } else { + vmstate_subsection_save(f, vmsd, opaque); } - if (vmsd->post_load) { + + visit_end_struct(v, &err); + + if (load && vmsd->post_load) { return vmsd->post_load(opaque, version_id); } + return 0; } -void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, - void *opaque) +int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd, + void *opaque, int version_id) { - VMStateField *field = vmsd->fields; - - if (vmsd->pre_save) { - vmsd->pre_save(opaque); - } - while(field->name) { - if (!field->field_exists || - field->field_exists(opaque, vmsd->version_id)) { - void *base_addr = opaque + field->offset; - int i, n_elems = 1; - int size = field->size; - - if (field->flags & VMS_VBUFFER) { - size = *(int32_t *)(opaque+field->size_offset); - if (field->flags & VMS_MULTIPLY) { - size *= field->size; - } - } - if (field->flags & VMS_ARRAY) { - n_elems = field->num; - } else if (field->flags & VMS_VARRAY_INT32) { - n_elems = *(int32_t *)(opaque+field->num_offset); - } else if (field->flags & VMS_VARRAY_UINT16) { - n_elems = *(uint16_t *)(opaque+field->num_offset); - } else if (field->flags & VMS_VARRAY_UINT8) { - n_elems = *(uint8_t *)(opaque+field->num_offset); - } - if (field->flags & VMS_POINTER) { - base_addr = *(void **)base_addr + field->start; - } - for (i = 0; i < n_elems; i++) { - void *addr = base_addr + size * i; + return vmstate_process(f, vmsd, opaque, version_id, VMS_LOAD); +} - if (field->flags & VMS_ARRAY_OF_POINTER) { - addr = *(void **)addr; - } - if (field->flags & VMS_STRUCT) { - vmstate_save_state(f, field->vmsd, addr); - } else { - field->info->put(f, addr, size); - } - } - } - field++; - } - vmstate_subsection_save(f, vmsd, opaque); +void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, void *opaque) +{ + vmstate_process(f, vmsd, opaque, 0, VMS_SAVE); } static int vmstate_load(QEMUFile *f, SaveStateEntry *se, int version_id) @@ -940,7 +1013,7 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se) se->save_state(f, se->opaque); return; } - vmstate_save_state(f,se->vmsd, se->opaque); + vmstate_save_state(f, se->vmsd, se->opaque); } #define QEMU_VM_FILE_MAGIC 0x5145564d @@ -1173,22 +1246,34 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, void *opaque) { const VMStateSubsection *sub = vmsd->subsections; + uint8_t tag; + int i; + Visitor *v = qemu_file_get_input_visitor(f); + Error *err = NULL; + assert(v); if (!sub || !sub->needed) { return 0; } + visit_start_list(v, "subsections", &err); while (qemu_peek_byte(f) == QEMU_VM_SUBSECTION) { char idstr[256]; int ret; - uint8_t version_id, len; + uint32_t version_id, len; const VMStateDescription *sub_vmsd; - qemu_get_byte(f); /* subsection */ - len = qemu_get_byte(f); - qemu_get_buffer(f, (uint8_t *)idstr, len); + visit_start_struct(v, NULL, NULL, NULL, 0, &err); + + visit_type_uint8(v, &tag, "__SUBSECTION__", &err); + visit_type_uint8(v, (uint8_t *)&len, "len", &err); + visit_start_array(v, NULL, "name", len, 1, &err); + for (i = 0; i < len; i++) { + visit_type_uint8(v, (uint8_t *)&idstr[i], NULL, &err); + } + visit_end_array(v, &err); idstr[len] = 0; - version_id = qemu_get_be32(f); + visit_type_uint32(v, &version_id, "version_id", &err); sub_vmsd = vmstate_get_subsection(sub, idstr); if (sub_vmsd == NULL) { @@ -1199,6 +1284,15 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, if (ret) { return ret; } + + visit_end_struct(v, &err); + } + visit_end_list(v, &err); + + if (error_is_set(&err)) { + error_report("error loading subsections: %s", error_get_pretty(err)); + error_free(err); + return -EINVAL; } return 0; } @@ -1207,22 +1301,37 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, void *opaque) { const VMStateSubsection *sub = vmsd->subsections; + uint8_t tag = QEMU_VM_SUBSECTION; + int i; + Visitor *v = qemu_file_get_output_visitor(f); + Error *err = NULL; + assert(v); + visit_start_list(v, "subsections", &err); while (sub && sub->needed) { if (sub->needed(opaque)) { const VMStateDescription *vmsd = sub->vmsd; uint8_t len; - qemu_put_byte(f, QEMU_VM_SUBSECTION); + visit_start_struct(v, NULL, NULL, NULL, 0, &err); + + visit_type_uint8(v, &tag, "__SUBSECTION__", &err); len = strlen(vmsd->name); - qemu_put_byte(f, len); - qemu_put_buffer(f, (uint8_t *)vmsd->name, len); - qemu_put_be32(f, vmsd->version_id); + visit_type_uint8(v, &len, "len", &err); + visit_start_array(v, (void **)&vmsd->name, "name", len, 1, &err); + for (i = 0; i < len; i++) { + visit_type_uint8(v, (uint8_t *)&vmsd->name[i], NULL, &err); + } + visit_end_array(v, &err); + visit_type_uint32(v, (uint32_t *)&vmsd->version_id, "version_id", &err); assert(!vmsd->subsections); vmstate_save_state(f, vmsd, opaque); + + visit_end_struct(v, &err); } sub++; } + visit_end_list(v, &err); } typedef struct LoadStateEntry { diff --git a/target-alpha/machine.c b/target-alpha/machine.c index 76d70d9..4e6c549 100644 --- a/target-alpha/machine.c +++ b/target-alpha/machine.c @@ -1,17 +1,22 @@ #include "hw/hw.h" #include "hw/boards.h" -static int get_fpcr(QEMUFile *f, void *opaque, size_t size) +static int get_fpcr(Visitor *v, const char *name, void *opaque, + size_t size, Error **err) { CPUAlphaState *env = opaque; - cpu_alpha_store_fpcr(env, qemu_get_be64(f)); + uint64_t fpcr; + visit_type_uint64(v, &fpcr, name, err); + cpu_alpha_store_fpcr(env, fpcr); return 0; } -static void put_fpcr(QEMUFile *f, void *opaque, size_t size) +static void put_fpcr(Visitor *v, const char *name, void *opaque, + size_t size, Error **err) { CPUAlphaState *env = opaque; - qemu_put_be64(f, cpu_alpha_load_fpcr(env)); + uint64_t fpcr = cpu_alpha_load_fpcr(env); + visit_type_uint64(v, &fpcr, name, err); } static const VMStateInfo vmstate_fpcr = { diff --git a/target-i386/machine.c b/target-i386/machine.c index 25fa97d..1a4281c 100644 --- a/target-i386/machine.c +++ b/target-i386/machine.c @@ -78,7 +78,8 @@ static const VMStateDescription vmstate_mtrr_var = { #define VMSTATE_MTRR_VARS(_field, _state, _n, _v) \ VMSTATE_STRUCT_ARRAY(_field, _state, _n, _v, vmstate_mtrr_var, MTRRVar) -static void put_fpreg_error(QEMUFile *f, void *opaque, size_t size) +static void put_fpreg_error(Visitor *v, const char *name, void *opaque, + size_t size, Error **err) { fprintf(stderr, "call put_fpreg() with invalid arguments\n"); exit(0); @@ -106,19 +107,23 @@ static void fp64_to_fp80(union x86_longdouble *p, uint64_t temp) p->exp = e; } -static int get_fpreg(QEMUFile *f, void *opaque, size_t size) +static int get_fpreg(Visitor *v, const char *name, void *opaque, + size_t size, Error **err) { FPReg *fp_reg = opaque; uint64_t mant; uint16_t exp; - qemu_get_be64s(f, &mant); - qemu_get_be16s(f, &exp); + visit_start_struct(v, NULL, NULL, name, 0, err); + visit_type_uint64(v, &mant, "mant", err); + visit_type_uint16(v, &exp, "exp", err); + visit_end_struct(v, err); fp_reg->d = cpu_set_fp80(mant, exp); return 0; } -static void put_fpreg(QEMUFile *f, void *opaque, size_t size) +static void put_fpreg(Visitor *v, const char *name, void *opaque, + size_t size, Error **err) { FPReg *fp_reg = opaque; uint64_t mant; @@ -126,8 +131,10 @@ static void put_fpreg(QEMUFile *f, void *opaque, size_t size) /* we save the real CPU data (in case of MMX usage only 'mant' contains the MMX register */ cpu_get_fp80(&mant, &exp, fp_reg->d); - qemu_put_be64s(f, &mant); - qemu_put_be16s(f, &exp); + visit_start_struct(v, NULL, NULL, name, 0, err); + visit_type_uint64(v, &mant, "mant", err); + visit_type_uint16(v, &exp, "exp", err); + visit_end_struct(v, err); } static const VMStateInfo vmstate_fpreg = { @@ -136,12 +143,13 @@ static const VMStateInfo vmstate_fpreg = { .put = put_fpreg, }; -static int get_fpreg_1_mmx(QEMUFile *f, void *opaque, size_t size) +static int get_fpreg_1_mmx(Visitor *v, const char *name, void *opaque, + size_t size, Error **err) { union x86_longdouble *p = opaque; uint64_t mant; - qemu_get_be64s(f, &mant); + visit_type_uint64(v, &mant, name, err); p->mant = mant; p->exp = 0xffff; return 0; @@ -153,12 +161,13 @@ static const VMStateInfo vmstate_fpreg_1_mmx = { .put = put_fpreg_error, }; -static int get_fpreg_1_no_mmx(QEMUFile *f, void *opaque, size_t size) +static int get_fpreg_1_no_mmx(Visitor *v, const char *name, void *opaque, + size_t size, Error **err) { union x86_longdouble *p = opaque; uint64_t mant; - qemu_get_be64s(f, &mant); + visit_type_uint64(v, &mant, name, err); fp64_to_fp80(p, mant); return 0; } @@ -212,17 +221,23 @@ static bool less_than_7(void *opaque, int version_id) return version_id < 7; } -static int get_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) +static int get_uint64_as_uint32(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { - uint64_t *v = pv; - *v = qemu_get_be32(f); + uint64_t *val1 = pv; + uint32_t val2; + visit_type_uint32(v, &val2, name, err); + *val1 = val2; return 0; } -static void put_uint64_as_uint32(QEMUFile *f, void *pv, size_t size) +static void put_uint64_as_uint32(Visitor *v, const char *name, void *pv, + size_t size, Error **err) { - uint64_t *v = pv; - qemu_put_be32(f, *v); + uint64_t *val1 = pv; + uint32_t val2; + visit_type_uint32(v, &val2, name, err); + *val1 = val2; } static const VMStateInfo vmstate_hack_uint64_as_uint32 = {