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