[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 10/10] vmstate: use visitors
From: |
Michael Roth |
Subject: |
[Qemu-devel] [PATCH v2 10/10] vmstate: use visitors |
Date: |
Thu, 27 Oct 2011 12:06:33 -0500 |
Signed-off-by: Michael Roth <address@hidden>
---
hw/eeprom93xx.c | 12 +-
hw/fw_cfg.c | 12 +-
hw/hw.h | 8 +-
hw/pci.c | 38 +++-
hw/twl92230.c | 18 +-
qemu-timer.h | 5 +
savevm.c | 521 ++++++++++++++++++++++++++++++------------------
target-alpha/machine.c | 13 +-
target-i386/machine.c | 49 +++--
9 files changed, 436 insertions(+), 240 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 5c0eb65..0e189da 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -293,8 +293,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 {
@@ -941,10 +941,14 @@ extern const VMStateDescription vmstate_hid_ptr_device;
#define VMSTATE_END_OF_LIST() \
{}
+#define VMS_LOAD true
+#define VMS_SAVE false
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, int version_id);
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque);
+int vmstate_process(Visitor *v, const VMStateDescription *vmsd,
+ void *opaque, int version_id, bool load,Error **errp);
int vmstate_register(DeviceState *dev, int instance_id,
const VMStateDescription *vmsd, void *base);
int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
diff --git a/hw/pci.c b/hw/pci.c
index e8cc1b0..a0ab0e0 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.h b/qemu-timer.h
index 67ca72e..043b1e1 100644
--- a/qemu-timer.h
+++ b/qemu-timer.h
@@ -6,6 +6,7 @@
#include "notify.h"
#include <time.h>
#include <sys/time.h>
+#include "qapi/qapi-visit-core.h"
#ifdef _WIN32
#include <windows.h>
@@ -137,7 +138,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 0b8e46f..3ce7fd3 100644
--- a/savevm.c
+++ b/savevm.c
@@ -183,19 +183,28 @@ static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs,
int is_writable)
/* 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;
-
expire_time = qemu_timer_expire_time_ns(ts);
- 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_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 {
@@ -203,19 +212,28 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
}
}
+void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
+{
+ Visitor *v = qemu_file_get_visitor(f);
+ assert(v);
+ qemu_get_timer_visitor(v, "timer", ts, NULL);
+}
+
/* 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 = {
@@ -226,17 +244,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 = {
@@ -247,17 +267,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 = {
@@ -268,17 +290,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 = {
@@ -290,13 +314,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;
}
@@ -310,11 +335,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;
@@ -329,17 +355,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 = {
@@ -350,17 +378,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 = {
@@ -371,17 +401,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 = {
@@ -392,17 +424,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 = {
@@ -414,13 +448,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;
@@ -434,17 +469,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 = {
@@ -456,13 +493,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;
}
@@ -476,13 +514,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;
}
@@ -495,17 +534,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 = {
@@ -516,17 +557,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 = {
@@ -538,29 +591,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 = {
@@ -820,34 +883,57 @@ 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_qf(QEMUFile *f, const VMStateDescription *vmsd,
+ void *opaque, int version_id, bool load, Error
**errp)
{
VMStateField *field = vmsd->fields;
int ret;
+ Visitor *v = qemu_file_get_visitor(f);
+ 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;
+ assert(v);
+ if (load) {
+ 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 {
+ if (vmsd->pre_save) {
+ vmsd->pre_save(opaque);
+ }
}
+
+ 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);
@@ -857,14 +943,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;
@@ -876,77 +976,63 @@ 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 (error_is_set(&err)) {
+ error_report("error %s state: %s", load ? "loading" : "saving",
+ error_get_pretty(err));
+ error_propagate(errp, err);
}
- if (vmsd->post_load) {
+
+ if (load) {
+ ret = vmstate_subsection_load(f, vmsd, opaque);
+ if (ret != 0) {
+ return ret;
+ }
+ } else {
+ vmstate_subsection_save(f, vmsd, opaque);
+ }
+
+ 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_qf(f, vmsd, opaque, version_id, VMS_LOAD, NULL);
+}
- 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_qf(f, vmsd, opaque, 0, VMS_SAVE, NULL);
}
static int vmstate_load(QEMUFile *f, SaveStateEntry *se, int version_id)
@@ -963,7 +1049,22 @@ 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);
+}
+
+/* This wrapper allows direct callers of vmstate_load_state/vmstate_save_state
+ * to be migrated to Visitors even though internally we still use QEMUFile
+ * for old-style LoadStateHandler/SaveStateHandler users. Once the latter users
+ * are converted we can modify the interfaces accordingly, allowing us to drop
+ * references to QEMUFile in the vmstate path. Thus, both old-style users and
+ * vmstate users are decoupled from QEMUFile, leaving only live save/load users
+ * and savevm.c, which can then be reworked without touching device code.
+ */
+int vmstate_process(Visitor *v, const VMStateDescription *vmsd,
+ void *opaque, int version_id, bool load, Error **errp)
+{
+ return vmstate_process_qf(qemu_file_from_visitor(v), vmsd, opaque,
+ version_id, load, errp);
}
#define QEMU_VM_FILE_MAGIC 0x5145564d
@@ -1199,40 +1300,60 @@ static const VMStateDescription
*vmstate_get_subsection(const VMStateSubsection
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque)
{
+ Visitor *v = qemu_file_get_visitor(f);
+ Error *err = NULL;
+
+ assert(v);
+
+ visit_start_list(v, "subsections", &err);
+ /* FIXME: unforunately there's no way around using a peek here, since
+ * when using an input visitor we *must* read to know whether or not to
+ * continue, which will misalign the rest of the stream.
+ * When we switch interfaces to be Visitor-centric and move to
+ * and non-QEMUFile-based Visitor this will need to be one of the first
+ * migration compatibility breaks.
+ */
while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
char idstr[256];
- int ret;
- uint8_t version_id, len, size;
+ int ret, i;
+ uint32_t version_id, len;
const VMStateDescription *sub_vmsd;
+ uint8_t tag;
- len = qemu_peek_byte(f, 1);
- if (len < strlen(vmsd->name) + 1) {
- /* subsection name has be be "section_name/a" */
- return 0;
- }
- size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2);
- if (size != len) {
- return 0;
- }
- idstr[size] = 0;
+ 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;
if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
- /* it don't have a valid subsection name */
+ /* doesn't have a valid subsection name */
return 0;
}
+ visit_type_uint32(v, &version_id, "version_id", &err);
+
sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
if (sub_vmsd == NULL) {
return -ENOENT;
}
- qemu_file_skip(f, 1); /* subsection */
- qemu_file_skip(f, 1); /* len */
- qemu_file_skip(f, len); /* idstr */
- version_id = qemu_get_be32(f);
ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
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;
}
@@ -1241,21 +1362,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_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 = {
--
1.7.4.1
- [Qemu-devel] [PATCH v2 00/10] do savevm/migration save/load via Visitor interface, Michael Roth, 2011/10/27
- [Qemu-devel] [PATCH v2 07/10] trace: qemu_(put|get)_(byte|buffer) events, Michael Roth, 2011/10/27
- [Qemu-devel] [PATCH v2 06/10] qemu-file: add QEMUFile<->visitor lookup routines, Michael Roth, 2011/10/27
- [Qemu-devel] [PATCH v2 04/10] savevm: move QEMUFile interfaces into qemu-file.c, Michael Roth, 2011/10/27
- [Qemu-devel] [PATCH v2 09/10] qapi: add trace statements to qapi-visit-core.c, Michael Roth, 2011/10/27
- [Qemu-devel] [PATCH v2 10/10] vmstate: use visitors,
Michael Roth <=
- [Qemu-devel] [PATCH v2 05/10] qapi: test cases for QEMUFile input/output visitors, Michael Roth, 2011/10/27
- [Qemu-devel] [PATCH v2 03/10] qapi: add QemuFileInputVisitor, Michael Roth, 2011/10/27
- [Qemu-devel] [PATCH v2 02/10] qapi: add QemuFileOutputVisitor, Michael Roth, 2011/10/27
- [Qemu-devel] [PATCH v2 01/10] qapi: add Visitor interfaces for uint*_t and int*_t, Michael Roth, 2011/10/27
- [Qemu-devel] [PATCH v2 08/10] trace: add trace statements for visitor interface, Michael Roth, 2011/10/27