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 "exec/cpu-common.h"
15 #include "qemu-file.h"
16 #include "migration.h"
17 #include "migration/vmstate.h"
18 #include "qemu/error-report.h"
19 #include "qemu/queue.h"
24 static int get_bool(QEMUFile
*f
, void *pv
, size_t size
,
25 const VMStateField
*field
)
28 *v
= qemu_get_byte(f
);
32 static int put_bool(QEMUFile
*f
, void *pv
, size_t size
,
33 const VMStateField
*field
, QJSON
*vmdesc
)
40 const VMStateInfo vmstate_info_bool
= {
48 static int get_int8(QEMUFile
*f
, void *pv
, size_t size
,
49 const VMStateField
*field
)
56 static int put_int8(QEMUFile
*f
, void *pv
, size_t size
,
57 const VMStateField
*field
, QJSON
*vmdesc
)
64 const VMStateInfo vmstate_info_int8
= {
72 static int get_int16(QEMUFile
*f
, void *pv
, size_t size
,
73 const VMStateField
*field
)
76 qemu_get_sbe16s(f
, v
);
80 static int put_int16(QEMUFile
*f
, void *pv
, size_t size
,
81 const VMStateField
*field
, QJSON
*vmdesc
)
84 qemu_put_sbe16s(f
, v
);
88 const VMStateInfo vmstate_info_int16
= {
96 static int get_int32(QEMUFile
*f
, void *pv
, size_t size
,
97 const VMStateField
*field
)
100 qemu_get_sbe32s(f
, v
);
104 static int put_int32(QEMUFile
*f
, void *pv
, size_t size
,
105 const VMStateField
*field
, QJSON
*vmdesc
)
108 qemu_put_sbe32s(f
, v
);
112 const VMStateInfo vmstate_info_int32
= {
118 /* 32 bit int. See that the received value is the same than the one
121 static int get_int32_equal(QEMUFile
*f
, void *pv
, size_t size
,
122 const VMStateField
*field
)
126 qemu_get_sbe32s(f
, &v2
);
131 error_report("%" PRIx32
" != %" PRIx32
, *v
, v2
);
132 if (field
->err_hint
) {
133 error_printf("%s\n", field
->err_hint
);
138 const VMStateInfo vmstate_info_int32_equal
= {
139 .name
= "int32 equal",
140 .get
= get_int32_equal
,
144 /* 32 bit int. Check that the received value is non-negative
145 * and less than or equal to the one in the field.
148 static int get_int32_le(QEMUFile
*f
, void *pv
, size_t size
,
149 const VMStateField
*field
)
153 qemu_get_sbe32s(f
, &loaded
);
155 if (loaded
>= 0 && loaded
<= *cur
) {
159 error_report("Invalid value %" PRId32
160 " expecting positive value <= %" PRId32
,
165 const VMStateInfo vmstate_info_int32_le
= {
173 static int get_int64(QEMUFile
*f
, void *pv
, size_t size
,
174 const VMStateField
*field
)
177 qemu_get_sbe64s(f
, v
);
181 static int put_int64(QEMUFile
*f
, void *pv
, size_t size
,
182 const VMStateField
*field
, QJSON
*vmdesc
)
185 qemu_put_sbe64s(f
, v
);
189 const VMStateInfo vmstate_info_int64
= {
195 /* 8 bit unsigned int */
197 static int get_uint8(QEMUFile
*f
, void *pv
, size_t size
,
198 const VMStateField
*field
)
205 static int put_uint8(QEMUFile
*f
, void *pv
, size_t size
,
206 const VMStateField
*field
, QJSON
*vmdesc
)
213 const VMStateInfo vmstate_info_uint8
= {
219 /* 16 bit unsigned int */
221 static int get_uint16(QEMUFile
*f
, void *pv
, size_t size
,
222 const VMStateField
*field
)
225 qemu_get_be16s(f
, v
);
229 static int put_uint16(QEMUFile
*f
, void *pv
, size_t size
,
230 const VMStateField
*field
, QJSON
*vmdesc
)
233 qemu_put_be16s(f
, v
);
237 const VMStateInfo vmstate_info_uint16
= {
243 /* 32 bit unsigned int */
245 static int get_uint32(QEMUFile
*f
, void *pv
, size_t size
,
246 const VMStateField
*field
)
249 qemu_get_be32s(f
, v
);
253 static int put_uint32(QEMUFile
*f
, void *pv
, size_t size
,
254 const VMStateField
*field
, QJSON
*vmdesc
)
257 qemu_put_be32s(f
, v
);
261 const VMStateInfo vmstate_info_uint32
= {
267 /* 32 bit uint. See that the received value is the same than the one
270 static int get_uint32_equal(QEMUFile
*f
, void *pv
, size_t size
,
271 const VMStateField
*field
)
275 qemu_get_be32s(f
, &v2
);
280 error_report("%" PRIx32
" != %" PRIx32
, *v
, v2
);
281 if (field
->err_hint
) {
282 error_printf("%s\n", field
->err_hint
);
287 const VMStateInfo vmstate_info_uint32_equal
= {
288 .name
= "uint32 equal",
289 .get
= get_uint32_equal
,
293 /* 64 bit unsigned int */
295 static int get_uint64(QEMUFile
*f
, void *pv
, size_t size
,
296 const VMStateField
*field
)
299 qemu_get_be64s(f
, v
);
303 static int put_uint64(QEMUFile
*f
, void *pv
, size_t size
,
304 const VMStateField
*field
, QJSON
*vmdesc
)
307 qemu_put_be64s(f
, v
);
311 const VMStateInfo vmstate_info_uint64
= {
317 static int get_nullptr(QEMUFile
*f
, void *pv
, size_t size
,
318 const VMStateField
*field
)
321 if (qemu_get_byte(f
) == VMS_NULLPTR_MARKER
) {
324 error_report("vmstate: get_nullptr expected VMS_NULLPTR_MARKER");
328 static int put_nullptr(QEMUFile
*f
, void *pv
, size_t size
,
329 const VMStateField
*field
, QJSON
*vmdesc
)
333 qemu_put_byte(f
, VMS_NULLPTR_MARKER
);
336 error_report("vmstate: put_nullptr must be called with pv == NULL");
340 const VMStateInfo vmstate_info_nullptr
= {
346 /* 64 bit unsigned int. See that the received value is the same than the one
349 static int get_uint64_equal(QEMUFile
*f
, void *pv
, size_t size
,
350 const VMStateField
*field
)
354 qemu_get_be64s(f
, &v2
);
359 error_report("%" PRIx64
" != %" PRIx64
, *v
, v2
);
360 if (field
->err_hint
) {
361 error_printf("%s\n", field
->err_hint
);
366 const VMStateInfo vmstate_info_uint64_equal
= {
367 .name
= "int64 equal",
368 .get
= get_uint64_equal
,
372 /* 8 bit int. See that the received value is the same than the one
375 static int get_uint8_equal(QEMUFile
*f
, void *pv
, size_t size
,
376 const VMStateField
*field
)
385 error_report("%x != %x", *v
, v2
);
386 if (field
->err_hint
) {
387 error_printf("%s\n", field
->err_hint
);
392 const VMStateInfo vmstate_info_uint8_equal
= {
393 .name
= "uint8 equal",
394 .get
= get_uint8_equal
,
398 /* 16 bit unsigned int int. See that the received value is the same than the one
401 static int get_uint16_equal(QEMUFile
*f
, void *pv
, size_t size
,
402 const VMStateField
*field
)
406 qemu_get_be16s(f
, &v2
);
411 error_report("%x != %x", *v
, v2
);
412 if (field
->err_hint
) {
413 error_printf("%s\n", field
->err_hint
);
418 const VMStateInfo vmstate_info_uint16_equal
= {
419 .name
= "uint16 equal",
420 .get
= get_uint16_equal
,
426 static int get_float64(QEMUFile
*f
, void *pv
, size_t size
,
427 const VMStateField
*field
)
431 *v
= make_float64(qemu_get_be64(f
));
435 static int put_float64(QEMUFile
*f
, void *pv
, size_t size
,
436 const VMStateField
*field
, QJSON
*vmdesc
)
440 qemu_put_be64(f
, float64_val(*v
));
444 const VMStateInfo vmstate_info_float64
= {
450 /* CPU_DoubleU type */
452 static int get_cpudouble(QEMUFile
*f
, void *pv
, size_t size
,
453 const VMStateField
*field
)
456 qemu_get_be32s(f
, &v
->l
.upper
);
457 qemu_get_be32s(f
, &v
->l
.lower
);
461 static int put_cpudouble(QEMUFile
*f
, void *pv
, size_t size
,
462 const VMStateField
*field
, QJSON
*vmdesc
)
465 qemu_put_be32s(f
, &v
->l
.upper
);
466 qemu_put_be32s(f
, &v
->l
.lower
);
470 const VMStateInfo vmstate_info_cpudouble
= {
471 .name
= "CPU_Double_U",
472 .get
= get_cpudouble
,
473 .put
= put_cpudouble
,
476 /* uint8_t buffers */
478 static int get_buffer(QEMUFile
*f
, void *pv
, size_t size
,
479 const VMStateField
*field
)
482 qemu_get_buffer(f
, v
, size
);
486 static int put_buffer(QEMUFile
*f
, void *pv
, size_t size
,
487 const VMStateField
*field
, QJSON
*vmdesc
)
490 qemu_put_buffer(f
, v
, size
);
494 const VMStateInfo vmstate_info_buffer
= {
500 /* unused buffers: space that was used for some fields that are
501 not useful anymore */
503 static int get_unused_buffer(QEMUFile
*f
, void *pv
, size_t size
,
504 const VMStateField
*field
)
510 block_len
= MIN(sizeof(buf
), size
);
512 qemu_get_buffer(f
, buf
, block_len
);
517 static int put_unused_buffer(QEMUFile
*f
, void *pv
, size_t size
,
518 const VMStateField
*field
, QJSON
*vmdesc
)
520 static const uint8_t buf
[1024];
524 block_len
= MIN(sizeof(buf
), size
);
526 qemu_put_buffer(f
, buf
, block_len
);
532 const VMStateInfo vmstate_info_unused_buffer
= {
533 .name
= "unused_buffer",
534 .get
= get_unused_buffer
,
535 .put
= put_unused_buffer
,
538 /* vmstate_info_tmp, see VMSTATE_WITH_TMP, the idea is that we allocate
539 * a temporary buffer and the pre_load/pre_save methods in the child vmsd
540 * copy stuff from the parent into the child and do calculations to fill
541 * in fields that don't really exist in the parent but need to be in the
544 static int get_tmp(QEMUFile
*f
, void *pv
, size_t size
,
545 const VMStateField
*field
)
548 const VMStateDescription
*vmsd
= field
->vmsd
;
549 int version_id
= field
->version_id
;
550 void *tmp
= g_malloc(size
);
552 /* Writes the parent field which is at the start of the tmp */
554 ret
= vmstate_load_state(f
, vmsd
, tmp
, version_id
);
559 static int put_tmp(QEMUFile
*f
, void *pv
, size_t size
,
560 const VMStateField
*field
, QJSON
*vmdesc
)
562 const VMStateDescription
*vmsd
= field
->vmsd
;
563 void *tmp
= g_malloc(size
);
566 /* Writes the parent field which is at the start of the tmp */
568 ret
= vmstate_save_state(f
, vmsd
, tmp
, vmdesc
);
574 const VMStateInfo vmstate_info_tmp
= {
580 /* bitmaps (as defined by bitmap.h). Note that size here is the size
581 * of the bitmap in bits. The on-the-wire format of a bitmap is 64
582 * bit words with the bits in big endian order. The in-memory format
583 * is an array of 'unsigned long', which may be either 32 or 64 bits.
585 /* This is the number of 64 bit words sent over the wire */
586 #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
587 static int get_bitmap(QEMUFile
*f
, void *pv
, size_t size
,
588 const VMStateField
*field
)
590 unsigned long *bmp
= pv
;
592 for (i
= 0; i
< BITS_TO_U64S(size
); i
++) {
593 uint64_t w
= qemu_get_be64(f
);
595 if (sizeof(unsigned long) == 4 && idx
< BITS_TO_LONGS(size
)) {
596 bmp
[idx
++] = w
>> 32;
602 static int put_bitmap(QEMUFile
*f
, void *pv
, size_t size
,
603 const VMStateField
*field
, QJSON
*vmdesc
)
605 unsigned long *bmp
= pv
;
607 for (i
= 0; i
< BITS_TO_U64S(size
); i
++) {
608 uint64_t w
= bmp
[idx
++];
609 if (sizeof(unsigned long) == 4 && idx
< BITS_TO_LONGS(size
)) {
610 w
|= ((uint64_t)bmp
[idx
++]) << 32;
618 const VMStateInfo vmstate_info_bitmap
= {
625 * meta data about the QTAILQ is encoded in a VMStateField structure
627 static int get_qtailq(QEMUFile
*f
, void *pv
, size_t unused_size
,
628 const VMStateField
*field
)
631 const VMStateDescription
*vmsd
= field
->vmsd
;
632 /* size of a QTAILQ element */
633 size_t size
= field
->size
;
634 /* offset of the QTAILQ entry in a QTAILQ element */
635 size_t entry_offset
= field
->start
;
636 int version_id
= field
->version_id
;
639 trace_get_qtailq(vmsd
->name
, version_id
);
640 if (version_id
> vmsd
->version_id
) {
641 error_report("%s %s", vmsd
->name
, "too new");
642 trace_get_qtailq_end(vmsd
->name
, "too new", -EINVAL
);
646 if (version_id
< vmsd
->minimum_version_id
) {
647 error_report("%s %s", vmsd
->name
, "too old");
648 trace_get_qtailq_end(vmsd
->name
, "too old", -EINVAL
);
652 while (qemu_get_byte(f
)) {
653 elm
= g_malloc(size
);
654 ret
= vmstate_load_state(f
, vmsd
, elm
, version_id
);
658 QTAILQ_RAW_INSERT_TAIL(pv
, elm
, entry_offset
);
661 trace_get_qtailq_end(vmsd
->name
, "end", ret
);
666 static int put_qtailq(QEMUFile
*f
, void *pv
, size_t unused_size
,
667 const VMStateField
*field
, QJSON
*vmdesc
)
669 const VMStateDescription
*vmsd
= field
->vmsd
;
670 /* offset of the QTAILQ entry in a QTAILQ element*/
671 size_t entry_offset
= field
->start
;
675 trace_put_qtailq(vmsd
->name
, vmsd
->version_id
);
677 QTAILQ_RAW_FOREACH(elm
, pv
, entry_offset
) {
678 qemu_put_byte(f
, true);
679 ret
= vmstate_save_state(f
, vmsd
, elm
, vmdesc
);
684 qemu_put_byte(f
, false);
686 trace_put_qtailq_end(vmsd
->name
, "end");
690 const VMStateInfo vmstate_info_qtailq
= {