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