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