xref: /openbmc/qemu/migration/vmstate.c (revision 0ec7b3e7)
1 #include "qemu/osdep.h"
2 #include "qemu-common.h"
3 #include "migration/migration.h"
4 #include "migration/qemu-file.h"
5 #include "migration/vmstate.h"
6 #include "qemu/bitops.h"
7 #include "qemu/error-report.h"
8 #include "qemu/queue.h"
9 #include "trace.h"
10 #include "migration/qjson.h"
11 
12 static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
13                                     void *opaque, QJSON *vmdesc);
14 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
15                                    void *opaque);
16 
17 static int vmstate_n_elems(void *opaque, VMStateField *field)
18 {
19     int n_elems = 1;
20 
21     if (field->flags & VMS_ARRAY) {
22         n_elems = field->num;
23     } else if (field->flags & VMS_VARRAY_INT32) {
24         n_elems = *(int32_t *)(opaque+field->num_offset);
25     } else if (field->flags & VMS_VARRAY_UINT32) {
26         n_elems = *(uint32_t *)(opaque+field->num_offset);
27     } else if (field->flags & VMS_VARRAY_UINT16) {
28         n_elems = *(uint16_t *)(opaque+field->num_offset);
29     } else if (field->flags & VMS_VARRAY_UINT8) {
30         n_elems = *(uint8_t *)(opaque+field->num_offset);
31     }
32 
33     if (field->flags & VMS_MULTIPLY_ELEMENTS) {
34         n_elems *= field->num;
35     }
36 
37     trace_vmstate_n_elems(field->name, n_elems);
38     return n_elems;
39 }
40 
41 static int vmstate_size(void *opaque, VMStateField *field)
42 {
43     int size = field->size;
44 
45     if (field->flags & VMS_VBUFFER) {
46         size = *(int32_t *)(opaque+field->size_offset);
47         if (field->flags & VMS_MULTIPLY) {
48             size *= field->size;
49         }
50     }
51 
52     return size;
53 }
54 
55 static void *vmstate_base_addr(void *opaque, VMStateField *field, bool alloc)
56 {
57     void *base_addr = opaque + field->offset;
58 
59     if (field->flags & VMS_POINTER) {
60         if (alloc && (field->flags & VMS_ALLOC)) {
61             gsize size = 0;
62             if (field->flags & VMS_VBUFFER) {
63                 size = vmstate_size(opaque, field);
64             } else {
65                 int n_elems = vmstate_n_elems(opaque, field);
66                 if (n_elems) {
67                     size = n_elems * field->size;
68                 }
69             }
70             if (size) {
71                 *((void **)base_addr + field->start) = g_malloc(size);
72             }
73         }
74         base_addr = *(void **)base_addr + field->start;
75     }
76 
77     return base_addr;
78 }
79 
80 int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
81                        void *opaque, int version_id)
82 {
83     VMStateField *field = vmsd->fields;
84     int ret = 0;
85 
86     trace_vmstate_load_state(vmsd->name, version_id);
87     if (version_id > vmsd->version_id) {
88         error_report("%s: incoming version_id %d is too new "
89                      "for local version_id %d",
90                      vmsd->name, version_id, vmsd->version_id);
91         trace_vmstate_load_state_end(vmsd->name, "too new", -EINVAL);
92         return -EINVAL;
93     }
94     if  (version_id < vmsd->minimum_version_id) {
95         if (vmsd->load_state_old &&
96             version_id >= vmsd->minimum_version_id_old) {
97             ret = vmsd->load_state_old(f, opaque, version_id);
98             trace_vmstate_load_state_end(vmsd->name, "old path", ret);
99             return ret;
100         }
101         error_report("%s: incoming version_id %d is too old "
102                      "for local minimum version_id  %d",
103                      vmsd->name, version_id, vmsd->minimum_version_id);
104         trace_vmstate_load_state_end(vmsd->name, "too old", -EINVAL);
105         return -EINVAL;
106     }
107     if (vmsd->pre_load) {
108         int ret = vmsd->pre_load(opaque);
109         if (ret) {
110             return ret;
111         }
112     }
113     while (field->name) {
114         trace_vmstate_load_state_field(vmsd->name, field->name);
115         if ((field->field_exists &&
116              field->field_exists(opaque, version_id)) ||
117             (!field->field_exists &&
118              field->version_id <= version_id)) {
119             void *base_addr = vmstate_base_addr(opaque, field, true);
120             int i, n_elems = vmstate_n_elems(opaque, field);
121             int size = vmstate_size(opaque, field);
122 
123             for (i = 0; i < n_elems; i++) {
124                 void *addr = base_addr + size * i;
125 
126                 if (field->flags & VMS_ARRAY_OF_POINTER) {
127                     addr = *(void **)addr;
128                 }
129                 if (field->flags & VMS_STRUCT) {
130                     ret = vmstate_load_state(f, field->vmsd, addr,
131                                              field->vmsd->version_id);
132                 } else {
133                    ret = field->info->get(f, addr, size, field);
134                 }
135                 if (ret >= 0) {
136                     ret = qemu_file_get_error(f);
137                 }
138                 if (ret < 0) {
139                     qemu_file_set_error(f, ret);
140                     error_report("Failed to load %s:%s", vmsd->name,
141                                  field->name);
142                     trace_vmstate_load_field_error(field->name, ret);
143                     return ret;
144                 }
145             }
146         } else if (field->flags & VMS_MUST_EXIST) {
147             error_report("Input validation failed: %s/%s",
148                          vmsd->name, field->name);
149             return -1;
150         }
151         field++;
152     }
153     ret = vmstate_subsection_load(f, vmsd, opaque);
154     if (ret != 0) {
155         return ret;
156     }
157     if (vmsd->post_load) {
158         ret = vmsd->post_load(opaque, version_id);
159     }
160     trace_vmstate_load_state_end(vmsd->name, "end", ret);
161     return ret;
162 }
163 
164 static int vmfield_name_num(VMStateField *start, VMStateField *search)
165 {
166     VMStateField *field;
167     int found = 0;
168 
169     for (field = start; field->name; field++) {
170         if (!strcmp(field->name, search->name)) {
171             if (field == search) {
172                 return found;
173             }
174             found++;
175         }
176     }
177 
178     return -1;
179 }
180 
181 static bool vmfield_name_is_unique(VMStateField *start, VMStateField *search)
182 {
183     VMStateField *field;
184     int found = 0;
185 
186     for (field = start; field->name; field++) {
187         if (!strcmp(field->name, search->name)) {
188             found++;
189             /* name found more than once, so it's not unique */
190             if (found > 1) {
191                 return false;
192             }
193         }
194     }
195 
196     return true;
197 }
198 
199 static const char *vmfield_get_type_name(VMStateField *field)
200 {
201     const char *type = "unknown";
202 
203     if (field->flags & VMS_STRUCT) {
204         type = "struct";
205     } else if (field->info->name) {
206         type = field->info->name;
207     }
208 
209     return type;
210 }
211 
212 static bool vmsd_can_compress(VMStateField *field)
213 {
214     if (field->field_exists) {
215         /* Dynamically existing fields mess up compression */
216         return false;
217     }
218 
219     if (field->flags & VMS_STRUCT) {
220         VMStateField *sfield = field->vmsd->fields;
221         while (sfield->name) {
222             if (!vmsd_can_compress(sfield)) {
223                 /* Child elements can't compress, so can't we */
224                 return false;
225             }
226             sfield++;
227         }
228 
229         if (field->vmsd->subsections) {
230             /* Subsections may come and go, better don't compress */
231             return false;
232         }
233     }
234 
235     return true;
236 }
237 
238 static void vmsd_desc_field_start(const VMStateDescription *vmsd, QJSON *vmdesc,
239                                   VMStateField *field, int i, int max)
240 {
241     char *name, *old_name;
242     bool is_array = max > 1;
243     bool can_compress = vmsd_can_compress(field);
244 
245     if (!vmdesc) {
246         return;
247     }
248 
249     name = g_strdup(field->name);
250 
251     /* Field name is not unique, need to make it unique */
252     if (!vmfield_name_is_unique(vmsd->fields, field)) {
253         int num = vmfield_name_num(vmsd->fields, field);
254         old_name = name;
255         name = g_strdup_printf("%s[%d]", name, num);
256         g_free(old_name);
257     }
258 
259     json_start_object(vmdesc, NULL);
260     json_prop_str(vmdesc, "name", name);
261     if (is_array) {
262         if (can_compress) {
263             json_prop_int(vmdesc, "array_len", max);
264         } else {
265             json_prop_int(vmdesc, "index", i);
266         }
267     }
268     json_prop_str(vmdesc, "type", vmfield_get_type_name(field));
269 
270     if (field->flags & VMS_STRUCT) {
271         json_start_object(vmdesc, "struct");
272     }
273 
274     g_free(name);
275 }
276 
277 static void vmsd_desc_field_end(const VMStateDescription *vmsd, QJSON *vmdesc,
278                                 VMStateField *field, size_t size, int i)
279 {
280     if (!vmdesc) {
281         return;
282     }
283 
284     if (field->flags & VMS_STRUCT) {
285         /* We printed a struct in between, close its child object */
286         json_end_object(vmdesc);
287     }
288 
289     json_prop_int(vmdesc, "size", size);
290     json_end_object(vmdesc);
291 }
292 
293 
294 bool vmstate_save_needed(const VMStateDescription *vmsd, void *opaque)
295 {
296     if (vmsd->needed && !vmsd->needed(opaque)) {
297         /* optional section not needed */
298         return false;
299     }
300     return true;
301 }
302 
303 
304 void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
305                         void *opaque, QJSON *vmdesc)
306 {
307     VMStateField *field = vmsd->fields;
308 
309     trace_vmstate_save_state_top(vmsd->name);
310 
311     if (vmsd->pre_save) {
312         vmsd->pre_save(opaque);
313     }
314 
315     if (vmdesc) {
316         json_prop_str(vmdesc, "vmsd_name", vmsd->name);
317         json_prop_int(vmdesc, "version", vmsd->version_id);
318         json_start_array(vmdesc, "fields");
319     }
320 
321     while (field->name) {
322         if (!field->field_exists ||
323             field->field_exists(opaque, vmsd->version_id)) {
324             void *base_addr = vmstate_base_addr(opaque, field, false);
325             int i, n_elems = vmstate_n_elems(opaque, field);
326             int size = vmstate_size(opaque, field);
327             int64_t old_offset, written_bytes;
328             QJSON *vmdesc_loop = vmdesc;
329 
330             trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems);
331             for (i = 0; i < n_elems; i++) {
332                 void *addr = base_addr + size * i;
333 
334                 vmsd_desc_field_start(vmsd, vmdesc_loop, field, i, n_elems);
335                 old_offset = qemu_ftell_fast(f);
336 
337                 if (field->flags & VMS_ARRAY_OF_POINTER) {
338                     addr = *(void **)addr;
339                 }
340                 if (field->flags & VMS_STRUCT) {
341                     vmstate_save_state(f, field->vmsd, addr, vmdesc_loop);
342                 } else {
343                     field->info->put(f, addr, size, field, vmdesc_loop);
344                 }
345 
346                 written_bytes = qemu_ftell_fast(f) - old_offset;
347                 vmsd_desc_field_end(vmsd, vmdesc_loop, field, written_bytes, i);
348 
349                 /* Compressed arrays only care about the first element */
350                 if (vmdesc_loop && vmsd_can_compress(field)) {
351                     vmdesc_loop = NULL;
352                 }
353             }
354         } else {
355             if (field->flags & VMS_MUST_EXIST) {
356                 error_report("Output state validation failed: %s/%s",
357                         vmsd->name, field->name);
358                 assert(!(field->flags & VMS_MUST_EXIST));
359             }
360         }
361         field++;
362     }
363 
364     if (vmdesc) {
365         json_end_array(vmdesc);
366     }
367 
368     vmstate_subsection_save(f, vmsd, opaque, vmdesc);
369 }
370 
371 static const VMStateDescription *
372 vmstate_get_subsection(const VMStateDescription **sub, char *idstr)
373 {
374     while (sub && *sub && (*sub)->needed) {
375         if (strcmp(idstr, (*sub)->name) == 0) {
376             return *sub;
377         }
378         sub++;
379     }
380     return NULL;
381 }
382 
383 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
384                                    void *opaque)
385 {
386     trace_vmstate_subsection_load(vmsd->name);
387 
388     while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
389         char idstr[256], *idstr_ret;
390         int ret;
391         uint8_t version_id, len, size;
392         const VMStateDescription *sub_vmsd;
393 
394         len = qemu_peek_byte(f, 1);
395         if (len < strlen(vmsd->name) + 1) {
396             /* subsection name has be be "section_name/a" */
397             trace_vmstate_subsection_load_bad(vmsd->name, "(short)", "");
398             return 0;
399         }
400         size = qemu_peek_buffer(f, (uint8_t **)&idstr_ret, len, 2);
401         if (size != len) {
402             trace_vmstate_subsection_load_bad(vmsd->name, "(peek fail)", "");
403             return 0;
404         }
405         memcpy(idstr, idstr_ret, size);
406         idstr[size] = 0;
407 
408         if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
409             trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(prefix)");
410             /* it doesn't have a valid subsection name */
411             return 0;
412         }
413         sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
414         if (sub_vmsd == NULL) {
415             trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(lookup)");
416             return -ENOENT;
417         }
418         qemu_file_skip(f, 1); /* subsection */
419         qemu_file_skip(f, 1); /* len */
420         qemu_file_skip(f, len); /* idstr */
421         version_id = qemu_get_be32(f);
422 
423         ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
424         if (ret) {
425             trace_vmstate_subsection_load_bad(vmsd->name, idstr, "(child)");
426             return ret;
427         }
428     }
429 
430     trace_vmstate_subsection_load_good(vmsd->name);
431     return 0;
432 }
433 
434 static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
435                                     void *opaque, QJSON *vmdesc)
436 {
437     const VMStateDescription **sub = vmsd->subsections;
438     bool subsection_found = false;
439 
440     trace_vmstate_subsection_save_top(vmsd->name);
441     while (sub && *sub && (*sub)->needed) {
442         if ((*sub)->needed(opaque)) {
443             const VMStateDescription *vmsdsub = *sub;
444             uint8_t len;
445 
446             trace_vmstate_subsection_save_loop(vmsd->name, vmsdsub->name);
447             if (vmdesc) {
448                 /* Only create subsection array when we have any */
449                 if (!subsection_found) {
450                     json_start_array(vmdesc, "subsections");
451                     subsection_found = true;
452                 }
453 
454                 json_start_object(vmdesc, NULL);
455             }
456 
457             qemu_put_byte(f, QEMU_VM_SUBSECTION);
458             len = strlen(vmsdsub->name);
459             qemu_put_byte(f, len);
460             qemu_put_buffer(f, (uint8_t *)vmsdsub->name, len);
461             qemu_put_be32(f, vmsdsub->version_id);
462             vmstate_save_state(f, vmsdsub, opaque, vmdesc);
463 
464             if (vmdesc) {
465                 json_end_object(vmdesc);
466             }
467         }
468         sub++;
469     }
470 
471     if (vmdesc && subsection_found) {
472         json_end_array(vmdesc);
473     }
474 }
475 
476 /* bool */
477 
478 static int get_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field)
479 {
480     bool *v = pv;
481     *v = qemu_get_byte(f);
482     return 0;
483 }
484 
485 static int put_bool(QEMUFile *f, void *pv, size_t size, VMStateField *field,
486                     QJSON *vmdesc)
487 {
488     bool *v = pv;
489     qemu_put_byte(f, *v);
490     return 0;
491 }
492 
493 const VMStateInfo vmstate_info_bool = {
494     .name = "bool",
495     .get  = get_bool,
496     .put  = put_bool,
497 };
498 
499 /* 8 bit int */
500 
501 static int get_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
502 {
503     int8_t *v = pv;
504     qemu_get_s8s(f, v);
505     return 0;
506 }
507 
508 static int put_int8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
509                      QJSON *vmdesc)
510 {
511     int8_t *v = pv;
512     qemu_put_s8s(f, v);
513     return 0;
514 }
515 
516 const VMStateInfo vmstate_info_int8 = {
517     .name = "int8",
518     .get  = get_int8,
519     .put  = put_int8,
520 };
521 
522 /* 16 bit int */
523 
524 static int get_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
525 {
526     int16_t *v = pv;
527     qemu_get_sbe16s(f, v);
528     return 0;
529 }
530 
531 static int put_int16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
532                      QJSON *vmdesc)
533 {
534     int16_t *v = pv;
535     qemu_put_sbe16s(f, v);
536     return 0;
537 }
538 
539 const VMStateInfo vmstate_info_int16 = {
540     .name = "int16",
541     .get  = get_int16,
542     .put  = put_int16,
543 };
544 
545 /* 32 bit int */
546 
547 static int get_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
548 {
549     int32_t *v = pv;
550     qemu_get_sbe32s(f, v);
551     return 0;
552 }
553 
554 static int put_int32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
555                      QJSON *vmdesc)
556 {
557     int32_t *v = pv;
558     qemu_put_sbe32s(f, v);
559     return 0;
560 }
561 
562 const VMStateInfo vmstate_info_int32 = {
563     .name = "int32",
564     .get  = get_int32,
565     .put  = put_int32,
566 };
567 
568 /* 32 bit int. See that the received value is the same than the one
569    in the field */
570 
571 static int get_int32_equal(QEMUFile *f, void *pv, size_t size,
572                            VMStateField *field)
573 {
574     int32_t *v = pv;
575     int32_t v2;
576     qemu_get_sbe32s(f, &v2);
577 
578     if (*v == v2) {
579         return 0;
580     }
581     error_report("%" PRIx32 " != %" PRIx32, *v, v2);
582     return -EINVAL;
583 }
584 
585 const VMStateInfo vmstate_info_int32_equal = {
586     .name = "int32 equal",
587     .get  = get_int32_equal,
588     .put  = put_int32,
589 };
590 
591 /* 32 bit int. Check that the received value is non-negative
592  * and less than or equal to the one in the field.
593  */
594 
595 static int get_int32_le(QEMUFile *f, void *pv, size_t size, VMStateField *field)
596 {
597     int32_t *cur = pv;
598     int32_t loaded;
599     qemu_get_sbe32s(f, &loaded);
600 
601     if (loaded >= 0 && loaded <= *cur) {
602         *cur = loaded;
603         return 0;
604     }
605     error_report("Invalid value %" PRId32
606                  " expecting positive value <= %" PRId32,
607                  loaded, *cur);
608     return -EINVAL;
609 }
610 
611 const VMStateInfo vmstate_info_int32_le = {
612     .name = "int32 le",
613     .get  = get_int32_le,
614     .put  = put_int32,
615 };
616 
617 /* 64 bit int */
618 
619 static int get_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
620 {
621     int64_t *v = pv;
622     qemu_get_sbe64s(f, v);
623     return 0;
624 }
625 
626 static int put_int64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
627                       QJSON *vmdesc)
628 {
629     int64_t *v = pv;
630     qemu_put_sbe64s(f, v);
631     return 0;
632 }
633 
634 const VMStateInfo vmstate_info_int64 = {
635     .name = "int64",
636     .get  = get_int64,
637     .put  = put_int64,
638 };
639 
640 /* 8 bit unsigned int */
641 
642 static int get_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field)
643 {
644     uint8_t *v = pv;
645     qemu_get_8s(f, v);
646     return 0;
647 }
648 
649 static int put_uint8(QEMUFile *f, void *pv, size_t size, VMStateField *field,
650                      QJSON *vmdesc)
651 {
652     uint8_t *v = pv;
653     qemu_put_8s(f, v);
654     return 0;
655 }
656 
657 const VMStateInfo vmstate_info_uint8 = {
658     .name = "uint8",
659     .get  = get_uint8,
660     .put  = put_uint8,
661 };
662 
663 /* 16 bit unsigned int */
664 
665 static int get_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field)
666 {
667     uint16_t *v = pv;
668     qemu_get_be16s(f, v);
669     return 0;
670 }
671 
672 static int put_uint16(QEMUFile *f, void *pv, size_t size, VMStateField *field,
673                       QJSON *vmdesc)
674 {
675     uint16_t *v = pv;
676     qemu_put_be16s(f, v);
677     return 0;
678 }
679 
680 const VMStateInfo vmstate_info_uint16 = {
681     .name = "uint16",
682     .get  = get_uint16,
683     .put  = put_uint16,
684 };
685 
686 /* 32 bit unsigned int */
687 
688 static int get_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field)
689 {
690     uint32_t *v = pv;
691     qemu_get_be32s(f, v);
692     return 0;
693 }
694 
695 static int put_uint32(QEMUFile *f, void *pv, size_t size, VMStateField *field,
696                       QJSON *vmdesc)
697 {
698     uint32_t *v = pv;
699     qemu_put_be32s(f, v);
700     return 0;
701 }
702 
703 const VMStateInfo vmstate_info_uint32 = {
704     .name = "uint32",
705     .get  = get_uint32,
706     .put  = put_uint32,
707 };
708 
709 /* 32 bit uint. See that the received value is the same than the one
710    in the field */
711 
712 static int get_uint32_equal(QEMUFile *f, void *pv, size_t size,
713                             VMStateField *field)
714 {
715     uint32_t *v = pv;
716     uint32_t v2;
717     qemu_get_be32s(f, &v2);
718 
719     if (*v == v2) {
720         return 0;
721     }
722     error_report("%" PRIx32 " != %" PRIx32, *v, v2);
723     return -EINVAL;
724 }
725 
726 const VMStateInfo vmstate_info_uint32_equal = {
727     .name = "uint32 equal",
728     .get  = get_uint32_equal,
729     .put  = put_uint32,
730 };
731 
732 /* 64 bit unsigned int */
733 
734 static int get_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field)
735 {
736     uint64_t *v = pv;
737     qemu_get_be64s(f, v);
738     return 0;
739 }
740 
741 static int put_uint64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
742                       QJSON *vmdesc)
743 {
744     uint64_t *v = pv;
745     qemu_put_be64s(f, v);
746     return 0;
747 }
748 
749 const VMStateInfo vmstate_info_uint64 = {
750     .name = "uint64",
751     .get  = get_uint64,
752     .put  = put_uint64,
753 };
754 
755 /* 64 bit unsigned int. See that the received value is the same than the one
756    in the field */
757 
758 static int get_uint64_equal(QEMUFile *f, void *pv, size_t size,
759                             VMStateField *field)
760 {
761     uint64_t *v = pv;
762     uint64_t v2;
763     qemu_get_be64s(f, &v2);
764 
765     if (*v == v2) {
766         return 0;
767     }
768     error_report("%" PRIx64 " != %" PRIx64, *v, v2);
769     return -EINVAL;
770 }
771 
772 const VMStateInfo vmstate_info_uint64_equal = {
773     .name = "int64 equal",
774     .get  = get_uint64_equal,
775     .put  = put_uint64,
776 };
777 
778 /* 8 bit int. See that the received value is the same than the one
779    in the field */
780 
781 static int get_uint8_equal(QEMUFile *f, void *pv, size_t size,
782                            VMStateField *field)
783 {
784     uint8_t *v = pv;
785     uint8_t v2;
786     qemu_get_8s(f, &v2);
787 
788     if (*v == v2) {
789         return 0;
790     }
791     error_report("%x != %x", *v, v2);
792     return -EINVAL;
793 }
794 
795 const VMStateInfo vmstate_info_uint8_equal = {
796     .name = "uint8 equal",
797     .get  = get_uint8_equal,
798     .put  = put_uint8,
799 };
800 
801 /* 16 bit unsigned int int. See that the received value is the same than the one
802    in the field */
803 
804 static int get_uint16_equal(QEMUFile *f, void *pv, size_t size,
805                             VMStateField *field)
806 {
807     uint16_t *v = pv;
808     uint16_t v2;
809     qemu_get_be16s(f, &v2);
810 
811     if (*v == v2) {
812         return 0;
813     }
814     error_report("%x != %x", *v, v2);
815     return -EINVAL;
816 }
817 
818 const VMStateInfo vmstate_info_uint16_equal = {
819     .name = "uint16 equal",
820     .get  = get_uint16_equal,
821     .put  = put_uint16,
822 };
823 
824 /* floating point */
825 
826 static int get_float64(QEMUFile *f, void *pv, size_t size,
827                        VMStateField *field)
828 {
829     float64 *v = pv;
830 
831     *v = make_float64(qemu_get_be64(f));
832     return 0;
833 }
834 
835 static int put_float64(QEMUFile *f, void *pv, size_t size, VMStateField *field,
836                        QJSON *vmdesc)
837 {
838     uint64_t *v = pv;
839 
840     qemu_put_be64(f, float64_val(*v));
841     return 0;
842 }
843 
844 const VMStateInfo vmstate_info_float64 = {
845     .name = "float64",
846     .get  = get_float64,
847     .put  = put_float64,
848 };
849 
850 /* CPU_DoubleU type */
851 
852 static int get_cpudouble(QEMUFile *f, void *pv, size_t size,
853                          VMStateField *field)
854 {
855     CPU_DoubleU *v = pv;
856     qemu_get_be32s(f, &v->l.upper);
857     qemu_get_be32s(f, &v->l.lower);
858     return 0;
859 }
860 
861 static int put_cpudouble(QEMUFile *f, void *pv, size_t size,
862                          VMStateField *field, QJSON *vmdesc)
863 {
864     CPU_DoubleU *v = pv;
865     qemu_put_be32s(f, &v->l.upper);
866     qemu_put_be32s(f, &v->l.lower);
867     return 0;
868 }
869 
870 const VMStateInfo vmstate_info_cpudouble = {
871     .name = "CPU_Double_U",
872     .get  = get_cpudouble,
873     .put  = put_cpudouble,
874 };
875 
876 /* uint8_t buffers */
877 
878 static int get_buffer(QEMUFile *f, void *pv, size_t size,
879                       VMStateField *field)
880 {
881     uint8_t *v = pv;
882     qemu_get_buffer(f, v, size);
883     return 0;
884 }
885 
886 static int put_buffer(QEMUFile *f, void *pv, size_t size, VMStateField *field,
887                       QJSON *vmdesc)
888 {
889     uint8_t *v = pv;
890     qemu_put_buffer(f, v, size);
891     return 0;
892 }
893 
894 const VMStateInfo vmstate_info_buffer = {
895     .name = "buffer",
896     .get  = get_buffer,
897     .put  = put_buffer,
898 };
899 
900 /* unused buffers: space that was used for some fields that are
901    not useful anymore */
902 
903 static int get_unused_buffer(QEMUFile *f, void *pv, size_t size,
904                              VMStateField *field)
905 {
906     uint8_t buf[1024];
907     int block_len;
908 
909     while (size > 0) {
910         block_len = MIN(sizeof(buf), size);
911         size -= block_len;
912         qemu_get_buffer(f, buf, block_len);
913     }
914    return 0;
915 }
916 
917 static int put_unused_buffer(QEMUFile *f, void *pv, size_t size,
918                              VMStateField *field, QJSON *vmdesc)
919 {
920     static const uint8_t buf[1024];
921     int block_len;
922 
923     while (size > 0) {
924         block_len = MIN(sizeof(buf), size);
925         size -= block_len;
926         qemu_put_buffer(f, buf, block_len);
927     }
928 
929     return 0;
930 }
931 
932 const VMStateInfo vmstate_info_unused_buffer = {
933     .name = "unused_buffer",
934     .get  = get_unused_buffer,
935     .put  = put_unused_buffer,
936 };
937 
938 /* bitmaps (as defined by bitmap.h). Note that size here is the size
939  * of the bitmap in bits. The on-the-wire format of a bitmap is 64
940  * bit words with the bits in big endian order. The in-memory format
941  * is an array of 'unsigned long', which may be either 32 or 64 bits.
942  */
943 /* This is the number of 64 bit words sent over the wire */
944 #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
945 static int get_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field)
946 {
947     unsigned long *bmp = pv;
948     int i, idx = 0;
949     for (i = 0; i < BITS_TO_U64S(size); i++) {
950         uint64_t w = qemu_get_be64(f);
951         bmp[idx++] = w;
952         if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
953             bmp[idx++] = w >> 32;
954         }
955     }
956     return 0;
957 }
958 
959 static int put_bitmap(QEMUFile *f, void *pv, size_t size, VMStateField *field,
960                       QJSON *vmdesc)
961 {
962     unsigned long *bmp = pv;
963     int i, idx = 0;
964     for (i = 0; i < BITS_TO_U64S(size); i++) {
965         uint64_t w = bmp[idx++];
966         if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
967             w |= ((uint64_t)bmp[idx++]) << 32;
968         }
969         qemu_put_be64(f, w);
970     }
971 
972     return 0;
973 }
974 
975 const VMStateInfo vmstate_info_bitmap = {
976     .name = "bitmap",
977     .get = get_bitmap,
978     .put = put_bitmap,
979 };
980 
981 /* get for QTAILQ
982  * meta data about the QTAILQ is encoded in a VMStateField structure
983  */
984 static int get_qtailq(QEMUFile *f, void *pv, size_t unused_size,
985                       VMStateField *field)
986 {
987     int ret = 0;
988     const VMStateDescription *vmsd = field->vmsd;
989     /* size of a QTAILQ element */
990     size_t size = field->size;
991     /* offset of the QTAILQ entry in a QTAILQ element */
992     size_t entry_offset = field->start;
993     int version_id = field->version_id;
994     void *elm;
995 
996     trace_get_qtailq(vmsd->name, version_id);
997     if (version_id > vmsd->version_id) {
998         error_report("%s %s",  vmsd->name, "too new");
999         trace_get_qtailq_end(vmsd->name, "too new", -EINVAL);
1000 
1001         return -EINVAL;
1002     }
1003     if (version_id < vmsd->minimum_version_id) {
1004         error_report("%s %s",  vmsd->name, "too old");
1005         trace_get_qtailq_end(vmsd->name, "too old", -EINVAL);
1006         return -EINVAL;
1007     }
1008 
1009     while (qemu_get_byte(f)) {
1010         elm = g_malloc(size);
1011         ret = vmstate_load_state(f, vmsd, elm, version_id);
1012         if (ret) {
1013             return ret;
1014         }
1015         QTAILQ_RAW_INSERT_TAIL(pv, elm, entry_offset);
1016     }
1017 
1018     trace_get_qtailq_end(vmsd->name, "end", ret);
1019     return ret;
1020 }
1021 
1022 /* put for QTAILQ */
1023 static int put_qtailq(QEMUFile *f, void *pv, size_t unused_size,
1024                       VMStateField *field, QJSON *vmdesc)
1025 {
1026     const VMStateDescription *vmsd = field->vmsd;
1027     /* offset of the QTAILQ entry in a QTAILQ element*/
1028     size_t entry_offset = field->start;
1029     void *elm;
1030 
1031     trace_put_qtailq(vmsd->name, vmsd->version_id);
1032 
1033     QTAILQ_RAW_FOREACH(elm, pv, entry_offset) {
1034         qemu_put_byte(f, true);
1035         vmstate_save_state(f, vmsd, elm, vmdesc);
1036     }
1037     qemu_put_byte(f, false);
1038 
1039     trace_put_qtailq_end(vmsd->name, "end");
1040 
1041     return 0;
1042 }
1043 const VMStateInfo vmstate_info_qtailq = {
1044     .name = "qtailq",
1045     .get  = get_qtailq,
1046     .put  = put_qtailq,
1047 };
1048