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