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