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