Merge remote-tracking branch 'qemu-kvm/uq/master' into staging
[sdk/emulator/qemu.git] / vmstate.c
1 #include "qemu-common.h"
2 #include "migration/migration.h"
3 #include "migration/qemu-file.h"
4 #include "migration/vmstate.h"
5 #include "qemu/bitops.h"
6
7 static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
8                                     void *opaque);
9 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
10                                    void *opaque);
11
12 int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
13                        void *opaque, int version_id)
14 {
15     VMStateField *field = vmsd->fields;
16     int ret;
17
18     if (version_id > vmsd->version_id) {
19         return -EINVAL;
20     }
21     if (version_id < vmsd->minimum_version_id_old) {
22         return -EINVAL;
23     }
24     if  (version_id < vmsd->minimum_version_id) {
25         return vmsd->load_state_old(f, opaque, version_id);
26     }
27     if (vmsd->pre_load) {
28         int ret = vmsd->pre_load(opaque);
29         if (ret) {
30             return ret;
31         }
32     }
33     while (field->name) {
34         if ((field->field_exists &&
35              field->field_exists(opaque, version_id)) ||
36             (!field->field_exists &&
37              field->version_id <= version_id)) {
38             void *base_addr = opaque + field->offset;
39             int i, n_elems = 1;
40             int size = field->size;
41
42             if (field->flags & VMS_VBUFFER) {
43                 size = *(int32_t *)(opaque+field->size_offset);
44                 if (field->flags & VMS_MULTIPLY) {
45                     size *= field->size;
46                 }
47             }
48             if (field->flags & VMS_ARRAY) {
49                 n_elems = field->num;
50             } else if (field->flags & VMS_VARRAY_INT32) {
51                 n_elems = *(int32_t *)(opaque+field->num_offset);
52             } else if (field->flags & VMS_VARRAY_UINT32) {
53                 n_elems = *(uint32_t *)(opaque+field->num_offset);
54             } else if (field->flags & VMS_VARRAY_UINT16) {
55                 n_elems = *(uint16_t *)(opaque+field->num_offset);
56             } else if (field->flags & VMS_VARRAY_UINT8) {
57                 n_elems = *(uint8_t *)(opaque+field->num_offset);
58             }
59             if (field->flags & VMS_POINTER) {
60                 base_addr = *(void **)base_addr + field->start;
61             }
62             for (i = 0; i < n_elems; i++) {
63                 void *addr = base_addr + size * i;
64
65                 if (field->flags & VMS_ARRAY_OF_POINTER) {
66                     addr = *(void **)addr;
67                 }
68                 if (field->flags & VMS_STRUCT) {
69                     ret = vmstate_load_state(f, field->vmsd, addr,
70                                              field->vmsd->version_id);
71                 } else {
72                     ret = field->info->get(f, addr, size);
73
74                 }
75                 if (ret < 0) {
76                     return ret;
77                 }
78             }
79         }
80         field++;
81     }
82     ret = vmstate_subsection_load(f, vmsd, opaque);
83     if (ret != 0) {
84         return ret;
85     }
86     if (vmsd->post_load) {
87         return vmsd->post_load(opaque, version_id);
88     }
89     return 0;
90 }
91
92 void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
93                         void *opaque)
94 {
95     VMStateField *field = vmsd->fields;
96
97     if (vmsd->pre_save) {
98         vmsd->pre_save(opaque);
99     }
100     while (field->name) {
101         if (!field->field_exists ||
102             field->field_exists(opaque, vmsd->version_id)) {
103             void *base_addr = opaque + field->offset;
104             int i, n_elems = 1;
105             int size = field->size;
106
107             if (field->flags & VMS_VBUFFER) {
108                 size = *(int32_t *)(opaque+field->size_offset);
109                 if (field->flags & VMS_MULTIPLY) {
110                     size *= field->size;
111                 }
112             }
113             if (field->flags & VMS_ARRAY) {
114                 n_elems = field->num;
115             } else if (field->flags & VMS_VARRAY_INT32) {
116                 n_elems = *(int32_t *)(opaque+field->num_offset);
117             } else if (field->flags & VMS_VARRAY_UINT32) {
118                 n_elems = *(uint32_t *)(opaque+field->num_offset);
119             } else if (field->flags & VMS_VARRAY_UINT16) {
120                 n_elems = *(uint16_t *)(opaque+field->num_offset);
121             } else if (field->flags & VMS_VARRAY_UINT8) {
122                 n_elems = *(uint8_t *)(opaque+field->num_offset);
123             }
124             if (field->flags & VMS_POINTER) {
125                 base_addr = *(void **)base_addr + field->start;
126             }
127             for (i = 0; i < n_elems; i++) {
128                 void *addr = base_addr + size * i;
129
130                 if (field->flags & VMS_ARRAY_OF_POINTER) {
131                     addr = *(void **)addr;
132                 }
133                 if (field->flags & VMS_STRUCT) {
134                     vmstate_save_state(f, field->vmsd, addr);
135                 } else {
136                     field->info->put(f, addr, size);
137                 }
138             }
139         }
140         field++;
141     }
142     vmstate_subsection_save(f, vmsd, opaque);
143 }
144
145 static const VMStateDescription *
146     vmstate_get_subsection(const VMStateSubsection *sub, char *idstr)
147 {
148     while (sub && sub->needed) {
149         if (strcmp(idstr, sub->vmsd->name) == 0) {
150             return sub->vmsd;
151         }
152         sub++;
153     }
154     return NULL;
155 }
156
157 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
158                                    void *opaque)
159 {
160     while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
161         char idstr[256];
162         int ret;
163         uint8_t version_id, len, size;
164         const VMStateDescription *sub_vmsd;
165
166         len = qemu_peek_byte(f, 1);
167         if (len < strlen(vmsd->name) + 1) {
168             /* subsection name has be be "section_name/a" */
169             return 0;
170         }
171         size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2);
172         if (size != len) {
173             return 0;
174         }
175         idstr[size] = 0;
176
177         if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
178             /* it don't have a valid subsection name */
179             return 0;
180         }
181         sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
182         if (sub_vmsd == NULL) {
183             return -ENOENT;
184         }
185         qemu_file_skip(f, 1); /* subsection */
186         qemu_file_skip(f, 1); /* len */
187         qemu_file_skip(f, len); /* idstr */
188         version_id = qemu_get_be32(f);
189
190         ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
191         if (ret) {
192             return ret;
193         }
194     }
195     return 0;
196 }
197
198 static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
199                                     void *opaque)
200 {
201     const VMStateSubsection *sub = vmsd->subsections;
202
203     while (sub && sub->needed) {
204         if (sub->needed(opaque)) {
205             const VMStateDescription *vmsd = sub->vmsd;
206             uint8_t len;
207
208             qemu_put_byte(f, QEMU_VM_SUBSECTION);
209             len = strlen(vmsd->name);
210             qemu_put_byte(f, len);
211             qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
212             qemu_put_be32(f, vmsd->version_id);
213             vmstate_save_state(f, vmsd, opaque);
214         }
215         sub++;
216     }
217 }
218
219 /* bool */
220
221 static int get_bool(QEMUFile *f, void *pv, size_t size)
222 {
223     bool *v = pv;
224     *v = qemu_get_byte(f);
225     return 0;
226 }
227
228 static void put_bool(QEMUFile *f, void *pv, size_t size)
229 {
230     bool *v = pv;
231     qemu_put_byte(f, *v);
232 }
233
234 const VMStateInfo vmstate_info_bool = {
235     .name = "bool",
236     .get  = get_bool,
237     .put  = put_bool,
238 };
239
240 /* 8 bit int */
241
242 static int get_int8(QEMUFile *f, void *pv, size_t size)
243 {
244     int8_t *v = pv;
245     qemu_get_s8s(f, v);
246     return 0;
247 }
248
249 static void put_int8(QEMUFile *f, void *pv, size_t size)
250 {
251     int8_t *v = pv;
252     qemu_put_s8s(f, v);
253 }
254
255 const VMStateInfo vmstate_info_int8 = {
256     .name = "int8",
257     .get  = get_int8,
258     .put  = put_int8,
259 };
260
261 /* 16 bit int */
262
263 static int get_int16(QEMUFile *f, void *pv, size_t size)
264 {
265     int16_t *v = pv;
266     qemu_get_sbe16s(f, v);
267     return 0;
268 }
269
270 static void put_int16(QEMUFile *f, void *pv, size_t size)
271 {
272     int16_t *v = pv;
273     qemu_put_sbe16s(f, v);
274 }
275
276 const VMStateInfo vmstate_info_int16 = {
277     .name = "int16",
278     .get  = get_int16,
279     .put  = put_int16,
280 };
281
282 /* 32 bit int */
283
284 static int get_int32(QEMUFile *f, void *pv, size_t size)
285 {
286     int32_t *v = pv;
287     qemu_get_sbe32s(f, v);
288     return 0;
289 }
290
291 static void put_int32(QEMUFile *f, void *pv, size_t size)
292 {
293     int32_t *v = pv;
294     qemu_put_sbe32s(f, v);
295 }
296
297 const VMStateInfo vmstate_info_int32 = {
298     .name = "int32",
299     .get  = get_int32,
300     .put  = put_int32,
301 };
302
303 /* 32 bit int. See that the received value is the same than the one
304    in the field */
305
306 static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
307 {
308     int32_t *v = pv;
309     int32_t v2;
310     qemu_get_sbe32s(f, &v2);
311
312     if (*v == v2) {
313         return 0;
314     }
315     return -EINVAL;
316 }
317
318 const VMStateInfo vmstate_info_int32_equal = {
319     .name = "int32 equal",
320     .get  = get_int32_equal,
321     .put  = put_int32,
322 };
323
324 /* 32 bit int. See that the received value is the less or the same
325    than the one in the field */
326
327 static int get_int32_le(QEMUFile *f, void *pv, size_t size)
328 {
329     int32_t *old = pv;
330     int32_t new;
331     qemu_get_sbe32s(f, &new);
332
333     if (*old <= new) {
334         return 0;
335     }
336     return -EINVAL;
337 }
338
339 const VMStateInfo vmstate_info_int32_le = {
340     .name = "int32 equal",
341     .get  = get_int32_le,
342     .put  = put_int32,
343 };
344
345 /* 64 bit int */
346
347 static int get_int64(QEMUFile *f, void *pv, size_t size)
348 {
349     int64_t *v = pv;
350     qemu_get_sbe64s(f, v);
351     return 0;
352 }
353
354 static void put_int64(QEMUFile *f, void *pv, size_t size)
355 {
356     int64_t *v = pv;
357     qemu_put_sbe64s(f, v);
358 }
359
360 const VMStateInfo vmstate_info_int64 = {
361     .name = "int64",
362     .get  = get_int64,
363     .put  = put_int64,
364 };
365
366 /* 8 bit unsigned int */
367
368 static int get_uint8(QEMUFile *f, void *pv, size_t size)
369 {
370     uint8_t *v = pv;
371     qemu_get_8s(f, v);
372     return 0;
373 }
374
375 static void put_uint8(QEMUFile *f, void *pv, size_t size)
376 {
377     uint8_t *v = pv;
378     qemu_put_8s(f, v);
379 }
380
381 const VMStateInfo vmstate_info_uint8 = {
382     .name = "uint8",
383     .get  = get_uint8,
384     .put  = put_uint8,
385 };
386
387 /* 16 bit unsigned int */
388
389 static int get_uint16(QEMUFile *f, void *pv, size_t size)
390 {
391     uint16_t *v = pv;
392     qemu_get_be16s(f, v);
393     return 0;
394 }
395
396 static void put_uint16(QEMUFile *f, void *pv, size_t size)
397 {
398     uint16_t *v = pv;
399     qemu_put_be16s(f, v);
400 }
401
402 const VMStateInfo vmstate_info_uint16 = {
403     .name = "uint16",
404     .get  = get_uint16,
405     .put  = put_uint16,
406 };
407
408 /* 32 bit unsigned int */
409
410 static int get_uint32(QEMUFile *f, void *pv, size_t size)
411 {
412     uint32_t *v = pv;
413     qemu_get_be32s(f, v);
414     return 0;
415 }
416
417 static void put_uint32(QEMUFile *f, void *pv, size_t size)
418 {
419     uint32_t *v = pv;
420     qemu_put_be32s(f, v);
421 }
422
423 const VMStateInfo vmstate_info_uint32 = {
424     .name = "uint32",
425     .get  = get_uint32,
426     .put  = put_uint32,
427 };
428
429 /* 32 bit uint. See that the received value is the same than the one
430    in the field */
431
432 static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
433 {
434     uint32_t *v = pv;
435     uint32_t v2;
436     qemu_get_be32s(f, &v2);
437
438     if (*v == v2) {
439         return 0;
440     }
441     return -EINVAL;
442 }
443
444 const VMStateInfo vmstate_info_uint32_equal = {
445     .name = "uint32 equal",
446     .get  = get_uint32_equal,
447     .put  = put_uint32,
448 };
449
450 /* 64 bit unsigned int */
451
452 static int get_uint64(QEMUFile *f, void *pv, size_t size)
453 {
454     uint64_t *v = pv;
455     qemu_get_be64s(f, v);
456     return 0;
457 }
458
459 static void put_uint64(QEMUFile *f, void *pv, size_t size)
460 {
461     uint64_t *v = pv;
462     qemu_put_be64s(f, v);
463 }
464
465 const VMStateInfo vmstate_info_uint64 = {
466     .name = "uint64",
467     .get  = get_uint64,
468     .put  = put_uint64,
469 };
470
471 /* 64 bit unsigned int. See that the received value is the same than the one
472    in the field */
473
474 static int get_uint64_equal(QEMUFile *f, void *pv, size_t size)
475 {
476     uint64_t *v = pv;
477     uint64_t v2;
478     qemu_get_be64s(f, &v2);
479
480     if (*v == v2) {
481         return 0;
482     }
483     return -EINVAL;
484 }
485
486 const VMStateInfo vmstate_info_uint64_equal = {
487     .name = "int64 equal",
488     .get  = get_uint64_equal,
489     .put  = put_uint64,
490 };
491
492 /* 8 bit int. See that the received value is the same than the one
493    in the field */
494
495 static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
496 {
497     uint8_t *v = pv;
498     uint8_t v2;
499     qemu_get_8s(f, &v2);
500
501     if (*v == v2) {
502         return 0;
503     }
504     return -EINVAL;
505 }
506
507 const VMStateInfo vmstate_info_uint8_equal = {
508     .name = "uint8 equal",
509     .get  = get_uint8_equal,
510     .put  = put_uint8,
511 };
512
513 /* 16 bit unsigned int int. See that the received value is the same than the one
514    in the field */
515
516 static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
517 {
518     uint16_t *v = pv;
519     uint16_t v2;
520     qemu_get_be16s(f, &v2);
521
522     if (*v == v2) {
523         return 0;
524     }
525     return -EINVAL;
526 }
527
528 const VMStateInfo vmstate_info_uint16_equal = {
529     .name = "uint16 equal",
530     .get  = get_uint16_equal,
531     .put  = put_uint16,
532 };
533
534 /* floating point */
535
536 static int get_float64(QEMUFile *f, void *pv, size_t size)
537 {
538     float64 *v = pv;
539
540     *v = make_float64(qemu_get_be64(f));
541     return 0;
542 }
543
544 static void put_float64(QEMUFile *f, void *pv, size_t size)
545 {
546     uint64_t *v = pv;
547
548     qemu_put_be64(f, float64_val(*v));
549 }
550
551 const VMStateInfo vmstate_info_float64 = {
552     .name = "float64",
553     .get  = get_float64,
554     .put  = put_float64,
555 };
556
557 /* uint8_t buffers */
558
559 static int get_buffer(QEMUFile *f, void *pv, size_t size)
560 {
561     uint8_t *v = pv;
562     qemu_get_buffer(f, v, size);
563     return 0;
564 }
565
566 static void put_buffer(QEMUFile *f, void *pv, size_t size)
567 {
568     uint8_t *v = pv;
569     qemu_put_buffer(f, v, size);
570 }
571
572 const VMStateInfo vmstate_info_buffer = {
573     .name = "buffer",
574     .get  = get_buffer,
575     .put  = put_buffer,
576 };
577
578 /* unused buffers: space that was used for some fields that are
579    not useful anymore */
580
581 static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
582 {
583     uint8_t buf[1024];
584     int block_len;
585
586     while (size > 0) {
587         block_len = MIN(sizeof(buf), size);
588         size -= block_len;
589         qemu_get_buffer(f, buf, block_len);
590     }
591    return 0;
592 }
593
594 static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
595 {
596     static const uint8_t buf[1024];
597     int block_len;
598
599     while (size > 0) {
600         block_len = MIN(sizeof(buf), size);
601         size -= block_len;
602         qemu_put_buffer(f, buf, block_len);
603     }
604 }
605
606 const VMStateInfo vmstate_info_unused_buffer = {
607     .name = "unused_buffer",
608     .get  = get_unused_buffer,
609     .put  = put_unused_buffer,
610 };
611
612 /* bitmaps (as defined by bitmap.h). Note that size here is the size
613  * of the bitmap in bits. The on-the-wire format of a bitmap is 64
614  * bit words with the bits in big endian order. The in-memory format
615  * is an array of 'unsigned long', which may be either 32 or 64 bits.
616  */
617 /* This is the number of 64 bit words sent over the wire */
618 #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64)
619 static int get_bitmap(QEMUFile *f, void *pv, size_t size)
620 {
621     unsigned long *bmp = pv;
622     int i, idx = 0;
623     for (i = 0; i < BITS_TO_U64S(size); i++) {
624         uint64_t w = qemu_get_be64(f);
625         bmp[idx++] = w;
626         if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
627             bmp[idx++] = w >> 32;
628         }
629     }
630     return 0;
631 }
632
633 static void put_bitmap(QEMUFile *f, void *pv, size_t size)
634 {
635     unsigned long *bmp = pv;
636     int i, idx = 0;
637     for (i = 0; i < BITS_TO_U64S(size); i++) {
638         uint64_t w = bmp[idx++];
639         if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) {
640             w |= ((uint64_t)bmp[idx++]) << 32;
641         }
642         qemu_put_be64(f, w);
643     }
644 }
645
646 const VMStateInfo vmstate_info_bitmap = {
647     .name = "bitmap",
648     .get = get_bitmap,
649     .put = put_bitmap,
650 };