Skip to content
Browse files

New VMstate save/load infrastructure

This patch introduces VMState infrastructure, to convert the save/load
functions of devices to a table approach.  This new approach has the
following advantages:
- it is type-safe
- you can't have load/save functions out of sync
- will allows us to have new interesting commands, like dump <device>, that
  shows all its internal state.
- Just now, the only added type is arrays, but we can add structures.
- Uses old load_state() function for loading old state.

Signed-off-by: Juan Quintela <>
Signed-off-by: Anthony Liguori <>
  • Loading branch information
juanquintela authored and Anthony Liguori committed Aug 28, 2009
1 parent 4082be4 commit 9ed7d6ae0fe7abb444c65caaadb5ef307df82c60
Showing with 370 additions and 5 deletions.
  1. +102 −0 hw/hw.h
  2. +268 −5 savevm.c
102 hw/hw.h
@@ -270,4 +270,106 @@ typedef int QEMUBootSetHandler(void *opaque, const char *boot_devices);
void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque);
int qemu_boot_set(const char *boot_devices);

typedef struct VMStateInfo VMStateInfo;
typedef struct VMStateDescription VMStateDescription;

struct VMStateInfo {
const char *name;
int (*get)(QEMUFile *f, void *pv, size_t size);
void (*put)(QEMUFile *f, const void *pv, size_t size);

enum VMStateFlags {
VMS_SINGLE = 0x001,

typedef struct {
const char *name;
size_t offset;
size_t size;
const VMStateInfo *info;
enum VMStateFlags flags;
int version_id;
} VMStateField;

struct VMStateDescription {
const char *name;
int version_id;
int minimum_version_id;
int minimum_version_id_old;
LoadStateHandler *load_state_old;
VMStateField *fields;

extern const VMStateInfo vmstate_info_int8;
extern const VMStateInfo vmstate_info_int16;
extern const VMStateInfo vmstate_info_int32;
extern const VMStateInfo vmstate_info_int64;

extern const VMStateInfo vmstate_info_uint8;
extern const VMStateInfo vmstate_info_uint16;
extern const VMStateInfo vmstate_info_uint32;
extern const VMStateInfo vmstate_info_uint64;

#define VMSTATE_SINGLE(_field, _state, _version, _info, _type) { \
.name = (stringify(_field)), \
.version_id = (_version), \
.size = sizeof(_type), \
.info = &(_info), \
.flags = VMS_SINGLE, \
.offset = offsetof(_state, _field) \
+ type_check(_type,typeof_field(_state, _field)) \

/* _f : field name
_s : struct state name
_v : version

#define VMSTATE_INT8_V(_f, _s, _v) \
VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int8, int8_t)
#define VMSTATE_INT16_V(_f, _s, _v) \
VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int16, int16_t)
#define VMSTATE_INT32_V(_f, _s, _v) \
VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int32, int32_t)
#define VMSTATE_INT64_V(_f, _s, _v) \
VMSTATE_SINGLE(_f, _s, _v, vmstate_info_int64, int64_t)

#define VMSTATE_UINT8_V(_f, _s, _v) \
VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint8, uint8_t)
#define VMSTATE_UINT16_V(_f, _s, _v) \
VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint16, uint16_t)
#define VMSTATE_UINT32_V(_f, _s, _v) \
VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint32, uint32_t)
#define VMSTATE_UINT64_V(_f, _s, _v) \
VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64, uint64_t)

#define VMSTATE_INT8(_f, _s) \
VMSTATE_INT8_V(_f, _s, 0)
#define VMSTATE_INT16(_f, _s) \
VMSTATE_INT16_V(_f, _s, 0)
#define VMSTATE_INT32(_f, _s) \
VMSTATE_INT32_V(_f, _s, 0)
#define VMSTATE_INT64(_f, _s) \
VMSTATE_INT64_V(_f, _s, 0)

#define VMSTATE_UINT8(_f, _s) \
VMSTATE_UINT8_V(_f, _s, 0)
#define VMSTATE_UINT16(_f, _s) \
VMSTATE_UINT16_V(_f, _s, 0)
#define VMSTATE_UINT32(_f, _s) \
VMSTATE_UINT32_V(_f, _s, 0)
#define VMSTATE_UINT64(_f, _s) \
VMSTATE_UINT64_V(_f, _s, 0)


extern int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque, int version_id);
extern void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
const void *opaque);
extern int vmstate_register(int instance_id, const VMStateDescription *vmsd,
void *base);
extern void vmstate_unregister(const char *idstr, void *opaque);

0 comments on commit 9ed7d6a

Please sign in to comment.