2 * VMStateInfo's for basic typse
4 * Copyright (c) 2009-2017 Red Hat Inc
7 * Juan Quintela <quintela@redhat.com>
9 * This work is licensed under the terms of the GNU GPL, version 2 or later.
10 * See the COPYING file in the top-level directory.
13 #include "qemu/osdep.h"
14 #include "qemu-common.h"
15 #include "exec/cpu-common.h"
16 #include "qemu-file.h"
17 #include "migration.h"
18 #include "migration/vmstate.h"
19 #include "qemu/error-report.h"
20 #include "qemu/queue.h"
25 static int get_bool(QEMUFile
*f
, void *pv
, size_t size
,
26 const VMStateField
*field
)
29 *v
= qemu_get_byte(f
);
33 static int put_bool(QEMUFile
*f
, void *pv
, size_t size
,
34 const VMStateField
*field
, QJSON
*vmdesc
)
41 const VMStateInfo vmstate_info_bool
= {
49 static int get_int8(QEMUFile
*f
, void *pv
, size_t size
,
50 const VMStateField
*field
)
57 static int put_int8(QEMUFile
*f
, void *pv
, size_t size
,
58 const VMStateField
*field
, QJSON
*vmdesc
)
65 const VMStateInfo vmstate_info_int8
= {
73 static int get_int16(QEMUFile
*f
, void *pv
, size_t size
,
74 const VMStateField
*field
)
77 qemu_get_sbe16s(f
, v
);
81 static int put_int16(QEMUFile
*f
, void *pv
, size_t size
,
82 const VMStateField
*field
, QJSON
*vmdesc
)
85 qemu_put_sbe16s(f
, v
);
89 const VMStateInfo vmstate_info_int16
= {
97 static int get_int32(QEMUFile
*f
, void *pv
, size_t size
,
98 const VMStateField
*field
)
101 qemu_get_sbe32s(f
, v
);
105 static int put_int32(QEMUFile
*f
, void *pv
, size_t size
,
106 const VMStateField
*field
, QJSON
*vmdesc
)
109 qemu_put_sbe32s(f
, v
);
113 const VMStateInfo vmstate_info_int32
= {
119 /* 32 bit int. See that the received value is the same than the one
122 static int get_int32_equal(QEMUFile
*f
, void *pv
, size_t size
,
123 const VMStateField
*field
)
127 qemu_get_sbe32s(f
, &v2
);
132 error_report("%" PRIx32
" != %" PRIx32
, *v
, v2
);
133 if (field
->err_hint
) {
134 error_printf("%s\n", field
->err_hint
);
139 const VMStateInfo vmstate_info_int32_equal
= {
140 .name
= "int32 equal",
141 .get
= get_int32_equal
,
145 /* 32 bit int. Check that the received value is non-negative
146 * and less than or equal to the one in the field.
149 static int get_int32_le(QEMUFile
*f
, void *pv
, size_t size
,
150 const VMStateField
*field
)
154 qemu_get_sbe32s(f
, &loaded
);
156 if (loaded
>= 0 && loaded
<= *cur
) {
160 error_report("Invalid value %" PRId32
161 " expecting positive value <= %" PRId32
,
166 const VMStateInfo vmstate_info_int32_le
= {
174 static int get_int64(QEMUFile
*f
, void *pv
, size_t size
,
175 const VMStateField
*field
)
178 qemu_get_sbe64s(f
, v
);
182 static int put_int64(QEMUFile
*f
, void *pv
, size_t size
,
183 const VMStateField
*field
, QJSON
*vmdesc
)
186 qemu_put_sbe64s(f
, v
);
190 const VMStateInfo vmstate_info_int64
= {
196 /* 8 bit unsigned int */
198 static int get_uint8(QEMUFile
*f
, void *pv
, size_t size
,
199 const VMStateField
*field
)
206 static int put_uint8(QEMUFile
*f
, void *pv
, size_t size
,
207 const VMStateField
*field
, QJSON
*vmdesc
)
214 const VMStateInfo vmstate_info_uint8
= {
220 /* 16 bit unsigned int */
222 static int get_uint16(QEMUFile
*f
, void *pv
, size_t size
,
223 const VMStateField
*field
)
226 qemu_get_be16s(f
, v
);
230 static int put_uint16(QEMUFile
*f
, void *pv
, size_t size
,
231 const VMStateField
*field
, QJSON
*vmdesc
)
234 qemu_put_be16s(f
, v
);
238 const VMStateInfo vmstate_info_uint16
= {
244 /* 32 bit unsigned int */
246 static int get_uint32(QEMUFile
*f
, void *pv
, size_t size
,
247 const VMStateField
*field
)
250 qemu_get_be32s(f
, v
);
254 static int put_uint32(QEMUFile
*f
, void *pv
, size_t size
,
255 const VMStateField
*field
, QJSON
*vmdesc
)
258 qemu_put_be32s(f
, v
);
262 const VMStateInfo vmstate_info_uint32
= {
268 /* 32 bit uint. See that the received value is the same than the one
271 static int get_uint32_equal(QEMUFile
*f
, void *pv
, size_t size
,
272 const VMStateField
*field
)
276 qemu_get_be32s(f
, &v2
);
281 error_report("%" PRIx32
" != %" PRIx32
, *v
, v2
);
282 if (field
->err_hint
) {
283 error_printf("%s\n", field
->err_hint
);
288 const VMStateInfo vmstate_info_uint32_equal
= {
289 .name
= "uint32 equal",
290 .get
= get_uint32_equal
,
294 /* 64 bit unsigned int */
296 static int get_uint64(QEMUFile
*f
, void *pv
, size_t size
,
297 const VMStateField
*field
)
300 qemu_get_be64s(f
, v
);
304 static int put_uint64(QEMUFile
*f
, void *pv
, size_t size
,
305 const VMStateField
*field
, QJSON
*vmdesc
)
308 qemu_put_be64s(f
, v
);
312 const VMStateInfo vmstate_info_uint64
= {
318 static int get_nullptr(QEMUFile
*f
, void *pv
, size_t size
,
319 const VMStateField
*field
)
322 if (qemu_get_byte(f
) == VMS_NULLPTR_MARKER
) {
325 error_report("vmstate: get_nullptr expected VMS_NULLPTR_MARKER");
329 static int put_nullptr(QEMUFile
*f
, void *pv
, size_t size
,
330 const VMStateField
*field
, QJSON
*vmdesc
)
334 qemu_put_byte(f
, VMS_NULLPTR_MARKER
);
337 error_report("vmstate: put_nullptr must be called with pv == NULL");
341 const VMStateInfo vmstate_info_nullptr
= {
347 /* 64 bit unsigned int. See that the received value is the same than the one
350 static int get_uint64_equal(QEMUFile
*f
, void *pv
, size_t size
,
351 const VMStateField
*field
)
355 qemu_get_be64s(f
, &v2
);
360 error_report("%" PRIx64
" != %" PRIx64
, *v
, v2
);
361 if (field
->err_hint
) {
362 error_printf("%s\n", field
->err_hint
);
367 const VMStateInfo vmstate_info_uint64_equal
= {
368 .name
= "int64 equal",
369 .get
= get_uint64_equal
,
373 /* 8 bit int. See that the received value is the same than the one
376 static int get_uint8_equal(QEMUFile
*f
, void *pv
, size_t size
,
377 const VMStateField
*field
)
386 error_report("%x != %x", *v
, v2
);
387 if (field
->err_hint
) {
388 error_printf("%s\n", field
->err_hint
);
393 const VMStateInfo vmstate_info_uint8_equal
= {
394 .name
= "uint8 equal",
395 .get
= get_uint8_equal
,
399 /* 16 bit unsigned int int. See that the received value is the same than the one
402 static int get_uint16_equal(QEMUFile
*f
, void *pv
, size_t size
,
403 const VMStateField
*field
)
407 qemu_get_be16s(f
, &v2
);
412 error_report("%x != %x", *v
, v2
);
413 if (field
->err_hint
) {
414 error_printf("%s\n", field
->err_hint
);
419 const VMStateInfo vmstate_info_uint16_equal
= {
420 .name
= "uint16 equal",
421 .get
= get_uint16_equal
,
427 static int get_float64(QEMUFile
*f
, void *pv
, size_t size
,
428 const VMStateField
*field
)
432 *v
= make_float64(qemu_get_be64(f
));
436 static int put_float64(QEMUFile
*f
, void *pv
, size_t size
,
437 const VMStateField
*field
, QJSON
*vmdesc
)
441 qemu_put_be64(f
, float64_val(*v
));
445 const VMStateInfo vmstate_info_float64
= {
451 /* CPU_DoubleU type */
453 static int get_cpudouble(QEMUFile
*f
, void *pv
, size_t size
,
454 const VMStateField
*field
)
457 qemu_get_be32s(f
, &v
->l
.upper
);
458 qemu_get_be32s(f
, &v
->l
.lower
);
462 static int put_cpudouble(QEMUFile
*f
, void *pv
, size_t size
,
463 const VMStateField
*field
, QJSON
*vmdesc
)
466 qemu_put_be32s(f
, &v
->l
.upper
);
467 qemu_put_be32s(f
, &v
->l
.lower
);
471 const VMStateInfo vmstate_info_cpudouble
= {
472 .name
= "CPU_Double_U",
473 .get
= get_cpudouble
,
474 .put
= put_cpudouble
,
477 /* uint8_t buffers */
479 static int get_buffer(QEMUFile
*f
, void *pv
, size_t size
,
480 const VMStateField
*field
)
483 qemu_get_buffer(f
, v
, size
);
487 static int put_buffer(QEMUFile
*f
, void *pv
, size_t size
,
488 const VMStateField
*field
, QJSON
*vmdesc
)
491 qemu_put_buffer(f
, v
, size
);
495 const VMStateInfo vmstate_info_buffer
= {
501 /* unused buffers: space that was used for some fields that are
502 not useful anymore */
504 static int get_unused_buffer(QEMUFile
*f
, void *pv
, size_t size
,
505 const VMStateField
*field
)
511 block_len
= MIN(sizeof(buf
), size
);
513 qemu_get_buffer(f
, buf
, block_len
);
518 static int put_unused_buffer(QEMUFile
*f
, void *pv
, size_t size
,
519 const VMStateField
*field
, QJSON
*vmdesc
)
521 static const uint8_t buf
[1024];
525 block_len
= MIN(sizeof(buf
), size
);
527 qemu_put_buffer(f
, buf
, block_len
);
533 const VMStateInfo vmstate_info_unused_buffer
= {
534 .name
= "unused_buffer",
535 .get
= get_unused_buffer
,
536 .put
= put_unused_buffer
,
539 /* vmstate_info_tmp, see VMSTATE_WITH_TMP, the idea is that we allocate
540 * a temporary buffer and the pre_load/pre_save methods in the child vmsd
541 * copy stuff from the parent into the child and do calculations to fill
542 * in fields that don't really exist in the parent but need to be in the
545 static int get_tmp(QEMUFile
*f
, void *pv
, size_t size
,
546 const VMStateField
*field
)
549 const VMStateDescription
*vmsd
= field
->vmsd
;
550 int version_id
= field
->version_id
;
551 void *tmp
= g_malloc(size
);
553 /* Writes the parent field which is at the start of the tmp */
555 ret
= vmstate_load_state(f
, vmsd
, tmp
, version_id
);
560 static int put_tmp(QEMUFile
*f
, void *pv
, size_t size
,
561 const VMStateField
*field
, QJSON
*vmdesc
)
563 const VMStateDescription
*vmsd
= field
->vmsd
;
564 void *tmp
= g_malloc(size
);
567 /* Writes the parent field which is at the start of the tmp */
569 ret
= vmstate_save_state(f
, vmsd
, tmp
, vmdesc
);
575 const VMStateInfo vmstate_info_tmp
= {
581 /* bitmaps (as defined by bitmap.h). Note that size here is the size
582 * of the bitmap in bits. The on-the-wire format of a bitmap is 64
583 * bit words with the bits in big endian order. The in-memory format
584 * is an array of 'unsigned long', which may be either 32 or 64 bits.
586 /* This is the number of 64 bit words sent over the wire */
587 #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
588 static int get_bitmap(QEMUFile
*f
, void *pv
, size_t size
,
589 const VMStateField
*field
)
591 unsigned long *bmp
= pv
;
593 for (i
= 0; i
< BITS_TO_U64S(size
); i
++) {
594 uint64_t w
= qemu_get_be64(f
);
596 if (sizeof(unsigned long) == 4 && idx
< BITS_TO_LONGS(size
)) {
597 bmp
[idx
++] = w
>> 32;
603 static int put_bitmap(QEMUFile
*f
, void *pv
, size_t size
,
604 const VMStateField
*field
, QJSON
*vmdesc
)
606 unsigned long *bmp
= pv
;
608 for (i
= 0; i
< BITS_TO_U64S(size
); i
++) {
609 uint64_t w
= bmp
[idx
++];
610 if (sizeof(unsigned long) == 4 && idx
< BITS_TO_LONGS(size
)) {
611 w
|= ((uint64_t)bmp
[idx
++]) << 32;
619 const VMStateInfo vmstate_info_bitmap
= {
626 * meta data about the QTAILQ is encoded in a VMStateField structure
628 static int get_qtailq(QEMUFile
*f
, void *pv
, size_t unused_size
,
629 const VMStateField
*field
)
632 const VMStateDescription
*vmsd
= field
->vmsd
;
633 /* size of a QTAILQ element */
634 size_t size
= field
->size
;
635 /* offset of the QTAILQ entry in a QTAILQ element */
636 size_t entry_offset
= field
->start
;
637 int version_id
= field
->version_id
;
640 trace_get_qtailq(vmsd
->name
, version_id
);
641 if (version_id
> vmsd
->version_id
) {
642 error_report("%s %s", vmsd
->name
, "too new");
643 trace_get_qtailq_end(vmsd
->name
, "too new", -EINVAL
);
647 if (version_id
< vmsd
->minimum_version_id
) {
648 error_report("%s %s", vmsd
->name
, "too old");
649 trace_get_qtailq_end(vmsd
->name
, "too old", -EINVAL
);
653 while (qemu_get_byte(f
)) {
654 elm
= g_malloc(size
);
655 ret
= vmstate_load_state(f
, vmsd
, elm
, version_id
);
659 QTAILQ_RAW_INSERT_TAIL(pv
, elm
, entry_offset
);
662 trace_get_qtailq_end(vmsd
->name
, "end", ret
);
667 static int put_qtailq(QEMUFile
*f
, void *pv
, size_t unused_size
,
668 const VMStateField
*field
, QJSON
*vmdesc
)
670 const VMStateDescription
*vmsd
= field
->vmsd
;
671 /* offset of the QTAILQ entry in a QTAILQ element*/
672 size_t entry_offset
= field
->start
;
676 trace_put_qtailq(vmsd
->name
, vmsd
->version_id
);
678 QTAILQ_RAW_FOREACH(elm
, pv
, entry_offset
) {
679 qemu_put_byte(f
, true);
680 ret
= vmstate_save_state(f
, vmsd
, elm
, vmdesc
);
685 qemu_put_byte(f
, false);
687 trace_put_qtailq_end(vmsd
->name
, "end");
691 const VMStateInfo vmstate_info_qtailq
= {