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 void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd, 280 void *opaque, QJSON *vmdesc) 281 { 282 VMStateField *field = vmsd->fields; 283 284 if (vmsd->pre_save) { 285 vmsd->pre_save(opaque); 286 } 287 288 if (vmdesc) { 289 json_prop_str(vmdesc, "vmsd_name", vmsd->name); 290 json_prop_int(vmdesc, "version", vmsd->version_id); 291 json_start_array(vmdesc, "fields"); 292 } 293 294 while (field->name) { 295 if (!field->field_exists || 296 field->field_exists(opaque, vmsd->version_id)) { 297 void *base_addr = vmstate_base_addr(opaque, field, false); 298 int i, n_elems = vmstate_n_elems(opaque, field); 299 int size = vmstate_size(opaque, field); 300 int64_t old_offset, written_bytes; 301 QJSON *vmdesc_loop = vmdesc; 302 303 for (i = 0; i < n_elems; i++) { 304 void *addr = base_addr + size * i; 305 306 vmsd_desc_field_start(vmsd, vmdesc_loop, field, i, n_elems); 307 old_offset = qemu_ftell_fast(f); 308 309 if (field->flags & VMS_ARRAY_OF_POINTER) { 310 addr = *(void **)addr; 311 } 312 if (field->flags & VMS_STRUCT) { 313 vmstate_save_state(f, field->vmsd, addr, vmdesc_loop); 314 } else { 315 field->info->put(f, addr, size); 316 } 317 318 written_bytes = qemu_ftell_fast(f) - old_offset; 319 vmsd_desc_field_end(vmsd, vmdesc_loop, field, written_bytes, i); 320 321 /* Compressed arrays only care about the first element */ 322 if (vmdesc_loop && vmsd_can_compress(field)) { 323 vmdesc_loop = NULL; 324 } 325 } 326 } else { 327 if (field->flags & VMS_MUST_EXIST) { 328 error_report("Output state validation failed: %s/%s", 329 vmsd->name, field->name); 330 assert(!(field->flags & VMS_MUST_EXIST)); 331 } 332 } 333 field++; 334 } 335 336 if (vmdesc) { 337 json_end_array(vmdesc); 338 } 339 340 vmstate_subsection_save(f, vmsd, opaque, vmdesc); 341 } 342 343 static const VMStateDescription * 344 vmstate_get_subsection(const VMStateSubsection *sub, char *idstr) 345 { 346 while (sub && sub->needed) { 347 if (strcmp(idstr, sub->vmsd->name) == 0) { 348 return sub->vmsd; 349 } 350 sub++; 351 } 352 return NULL; 353 } 354 355 static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, 356 void *opaque) 357 { 358 trace_vmstate_subsection_load(vmsd->name); 359 360 while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) { 361 char idstr[256]; 362 int ret; 363 uint8_t version_id, len, size; 364 const VMStateDescription *sub_vmsd; 365 366 len = qemu_peek_byte(f, 1); 367 if (len < strlen(vmsd->name) + 1) { 368 /* subsection name has be be "section_name/a" */ 369 trace_vmstate_subsection_load_bad(vmsd->name, "(short)"); 370 return 0; 371 } 372 size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2); 373 if (size != len) { 374 trace_vmstate_subsection_load_bad(vmsd->name, "(peek fail)"); 375 return 0; 376 } 377 idstr[size] = 0; 378 379 if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) { 380 trace_vmstate_subsection_load_bad(vmsd->name, idstr); 381 /* it don't have a valid subsection name */ 382 return 0; 383 } 384 sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr); 385 if (sub_vmsd == NULL) { 386 trace_vmstate_subsection_load_bad(vmsd->name, "(lookup)"); 387 return -ENOENT; 388 } 389 qemu_file_skip(f, 1); /* subsection */ 390 qemu_file_skip(f, 1); /* len */ 391 qemu_file_skip(f, len); /* idstr */ 392 version_id = qemu_get_be32(f); 393 394 ret = vmstate_load_state(f, sub_vmsd, opaque, version_id); 395 if (ret) { 396 trace_vmstate_subsection_load_bad(vmsd->name, "(child)"); 397 return ret; 398 } 399 } 400 401 trace_vmstate_subsection_load_good(vmsd->name); 402 return 0; 403 } 404 405 static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, 406 void *opaque, QJSON *vmdesc) 407 { 408 const VMStateSubsection *sub = vmsd->subsections; 409 bool subsection_found = false; 410 411 while (sub && sub->needed) { 412 if (sub->needed(opaque)) { 413 const VMStateDescription *vmsd = sub->vmsd; 414 uint8_t len; 415 416 if (vmdesc) { 417 /* Only create subsection array when we have any */ 418 if (!subsection_found) { 419 json_start_array(vmdesc, "subsections"); 420 subsection_found = true; 421 } 422 423 json_start_object(vmdesc, NULL); 424 } 425 426 qemu_put_byte(f, QEMU_VM_SUBSECTION); 427 len = strlen(vmsd->name); 428 qemu_put_byte(f, len); 429 qemu_put_buffer(f, (uint8_t *)vmsd->name, len); 430 qemu_put_be32(f, vmsd->version_id); 431 vmstate_save_state(f, vmsd, opaque, vmdesc); 432 433 if (vmdesc) { 434 json_end_object(vmdesc); 435 } 436 } 437 sub++; 438 } 439 440 if (vmdesc && subsection_found) { 441 json_end_array(vmdesc); 442 } 443 } 444 445 /* bool */ 446 447 static int get_bool(QEMUFile *f, void *pv, size_t size) 448 { 449 bool *v = pv; 450 *v = qemu_get_byte(f); 451 return 0; 452 } 453 454 static void put_bool(QEMUFile *f, void *pv, size_t size) 455 { 456 bool *v = pv; 457 qemu_put_byte(f, *v); 458 } 459 460 const VMStateInfo vmstate_info_bool = { 461 .name = "bool", 462 .get = get_bool, 463 .put = put_bool, 464 }; 465 466 /* 8 bit int */ 467 468 static int get_int8(QEMUFile *f, void *pv, size_t size) 469 { 470 int8_t *v = pv; 471 qemu_get_s8s(f, v); 472 return 0; 473 } 474 475 static void put_int8(QEMUFile *f, void *pv, size_t size) 476 { 477 int8_t *v = pv; 478 qemu_put_s8s(f, v); 479 } 480 481 const VMStateInfo vmstate_info_int8 = { 482 .name = "int8", 483 .get = get_int8, 484 .put = put_int8, 485 }; 486 487 /* 16 bit int */ 488 489 static int get_int16(QEMUFile *f, void *pv, size_t size) 490 { 491 int16_t *v = pv; 492 qemu_get_sbe16s(f, v); 493 return 0; 494 } 495 496 static void put_int16(QEMUFile *f, void *pv, size_t size) 497 { 498 int16_t *v = pv; 499 qemu_put_sbe16s(f, v); 500 } 501 502 const VMStateInfo vmstate_info_int16 = { 503 .name = "int16", 504 .get = get_int16, 505 .put = put_int16, 506 }; 507 508 /* 32 bit int */ 509 510 static int get_int32(QEMUFile *f, void *pv, size_t size) 511 { 512 int32_t *v = pv; 513 qemu_get_sbe32s(f, v); 514 return 0; 515 } 516 517 static void put_int32(QEMUFile *f, void *pv, size_t size) 518 { 519 int32_t *v = pv; 520 qemu_put_sbe32s(f, v); 521 } 522 523 const VMStateInfo vmstate_info_int32 = { 524 .name = "int32", 525 .get = get_int32, 526 .put = put_int32, 527 }; 528 529 /* 32 bit int. See that the received value is the same than the one 530 in the field */ 531 532 static int get_int32_equal(QEMUFile *f, void *pv, size_t size) 533 { 534 int32_t *v = pv; 535 int32_t v2; 536 qemu_get_sbe32s(f, &v2); 537 538 if (*v == v2) { 539 return 0; 540 } 541 return -EINVAL; 542 } 543 544 const VMStateInfo vmstate_info_int32_equal = { 545 .name = "int32 equal", 546 .get = get_int32_equal, 547 .put = put_int32, 548 }; 549 550 /* 32 bit int. Check that the received value is non-negative 551 * and less than or equal to the one in the field. 552 */ 553 554 static int get_int32_le(QEMUFile *f, void *pv, size_t size) 555 { 556 int32_t *cur = pv; 557 int32_t loaded; 558 qemu_get_sbe32s(f, &loaded); 559 560 if (loaded >= 0 && loaded <= *cur) { 561 *cur = loaded; 562 return 0; 563 } 564 return -EINVAL; 565 } 566 567 const VMStateInfo vmstate_info_int32_le = { 568 .name = "int32 le", 569 .get = get_int32_le, 570 .put = put_int32, 571 }; 572 573 /* 64 bit int */ 574 575 static int get_int64(QEMUFile *f, void *pv, size_t size) 576 { 577 int64_t *v = pv; 578 qemu_get_sbe64s(f, v); 579 return 0; 580 } 581 582 static void put_int64(QEMUFile *f, void *pv, size_t size) 583 { 584 int64_t *v = pv; 585 qemu_put_sbe64s(f, v); 586 } 587 588 const VMStateInfo vmstate_info_int64 = { 589 .name = "int64", 590 .get = get_int64, 591 .put = put_int64, 592 }; 593 594 /* 8 bit unsigned int */ 595 596 static int get_uint8(QEMUFile *f, void *pv, size_t size) 597 { 598 uint8_t *v = pv; 599 qemu_get_8s(f, v); 600 return 0; 601 } 602 603 static void put_uint8(QEMUFile *f, void *pv, size_t size) 604 { 605 uint8_t *v = pv; 606 qemu_put_8s(f, v); 607 } 608 609 const VMStateInfo vmstate_info_uint8 = { 610 .name = "uint8", 611 .get = get_uint8, 612 .put = put_uint8, 613 }; 614 615 /* 16 bit unsigned int */ 616 617 static int get_uint16(QEMUFile *f, void *pv, size_t size) 618 { 619 uint16_t *v = pv; 620 qemu_get_be16s(f, v); 621 return 0; 622 } 623 624 static void put_uint16(QEMUFile *f, void *pv, size_t size) 625 { 626 uint16_t *v = pv; 627 qemu_put_be16s(f, v); 628 } 629 630 const VMStateInfo vmstate_info_uint16 = { 631 .name = "uint16", 632 .get = get_uint16, 633 .put = put_uint16, 634 }; 635 636 /* 32 bit unsigned int */ 637 638 static int get_uint32(QEMUFile *f, void *pv, size_t size) 639 { 640 uint32_t *v = pv; 641 qemu_get_be32s(f, v); 642 return 0; 643 } 644 645 static void put_uint32(QEMUFile *f, void *pv, size_t size) 646 { 647 uint32_t *v = pv; 648 qemu_put_be32s(f, v); 649 } 650 651 const VMStateInfo vmstate_info_uint32 = { 652 .name = "uint32", 653 .get = get_uint32, 654 .put = put_uint32, 655 }; 656 657 /* 32 bit uint. See that the received value is the same than the one 658 in the field */ 659 660 static int get_uint32_equal(QEMUFile *f, void *pv, size_t size) 661 { 662 uint32_t *v = pv; 663 uint32_t v2; 664 qemu_get_be32s(f, &v2); 665 666 if (*v == v2) { 667 return 0; 668 } 669 return -EINVAL; 670 } 671 672 const VMStateInfo vmstate_info_uint32_equal = { 673 .name = "uint32 equal", 674 .get = get_uint32_equal, 675 .put = put_uint32, 676 }; 677 678 /* 64 bit unsigned int */ 679 680 static int get_uint64(QEMUFile *f, void *pv, size_t size) 681 { 682 uint64_t *v = pv; 683 qemu_get_be64s(f, v); 684 return 0; 685 } 686 687 static void put_uint64(QEMUFile *f, void *pv, size_t size) 688 { 689 uint64_t *v = pv; 690 qemu_put_be64s(f, v); 691 } 692 693 const VMStateInfo vmstate_info_uint64 = { 694 .name = "uint64", 695 .get = get_uint64, 696 .put = put_uint64, 697 }; 698 699 /* 64 bit unsigned int. See that the received value is the same than the one 700 in the field */ 701 702 static int get_uint64_equal(QEMUFile *f, void *pv, size_t size) 703 { 704 uint64_t *v = pv; 705 uint64_t v2; 706 qemu_get_be64s(f, &v2); 707 708 if (*v == v2) { 709 return 0; 710 } 711 return -EINVAL; 712 } 713 714 const VMStateInfo vmstate_info_uint64_equal = { 715 .name = "int64 equal", 716 .get = get_uint64_equal, 717 .put = put_uint64, 718 }; 719 720 /* 8 bit int. See that the received value is the same than the one 721 in the field */ 722 723 static int get_uint8_equal(QEMUFile *f, void *pv, size_t size) 724 { 725 uint8_t *v = pv; 726 uint8_t v2; 727 qemu_get_8s(f, &v2); 728 729 if (*v == v2) { 730 return 0; 731 } 732 return -EINVAL; 733 } 734 735 const VMStateInfo vmstate_info_uint8_equal = { 736 .name = "uint8 equal", 737 .get = get_uint8_equal, 738 .put = put_uint8, 739 }; 740 741 /* 16 bit unsigned int int. See that the received value is the same than the one 742 in the field */ 743 744 static int get_uint16_equal(QEMUFile *f, void *pv, size_t size) 745 { 746 uint16_t *v = pv; 747 uint16_t v2; 748 qemu_get_be16s(f, &v2); 749 750 if (*v == v2) { 751 return 0; 752 } 753 return -EINVAL; 754 } 755 756 const VMStateInfo vmstate_info_uint16_equal = { 757 .name = "uint16 equal", 758 .get = get_uint16_equal, 759 .put = put_uint16, 760 }; 761 762 /* floating point */ 763 764 static int get_float64(QEMUFile *f, void *pv, size_t size) 765 { 766 float64 *v = pv; 767 768 *v = make_float64(qemu_get_be64(f)); 769 return 0; 770 } 771 772 static void put_float64(QEMUFile *f, void *pv, size_t size) 773 { 774 uint64_t *v = pv; 775 776 qemu_put_be64(f, float64_val(*v)); 777 } 778 779 const VMStateInfo vmstate_info_float64 = { 780 .name = "float64", 781 .get = get_float64, 782 .put = put_float64, 783 }; 784 785 /* uint8_t buffers */ 786 787 static int get_buffer(QEMUFile *f, void *pv, size_t size) 788 { 789 uint8_t *v = pv; 790 qemu_get_buffer(f, v, size); 791 return 0; 792 } 793 794 static void put_buffer(QEMUFile *f, void *pv, size_t size) 795 { 796 uint8_t *v = pv; 797 qemu_put_buffer(f, v, size); 798 } 799 800 const VMStateInfo vmstate_info_buffer = { 801 .name = "buffer", 802 .get = get_buffer, 803 .put = put_buffer, 804 }; 805 806 /* unused buffers: space that was used for some fields that are 807 not useful anymore */ 808 809 static int get_unused_buffer(QEMUFile *f, void *pv, size_t size) 810 { 811 uint8_t buf[1024]; 812 int block_len; 813 814 while (size > 0) { 815 block_len = MIN(sizeof(buf), size); 816 size -= block_len; 817 qemu_get_buffer(f, buf, block_len); 818 } 819 return 0; 820 } 821 822 static void put_unused_buffer(QEMUFile *f, void *pv, size_t size) 823 { 824 static const uint8_t buf[1024]; 825 int block_len; 826 827 while (size > 0) { 828 block_len = MIN(sizeof(buf), size); 829 size -= block_len; 830 qemu_put_buffer(f, buf, block_len); 831 } 832 } 833 834 const VMStateInfo vmstate_info_unused_buffer = { 835 .name = "unused_buffer", 836 .get = get_unused_buffer, 837 .put = put_unused_buffer, 838 }; 839 840 /* bitmaps (as defined by bitmap.h). Note that size here is the size 841 * of the bitmap in bits. The on-the-wire format of a bitmap is 64 842 * bit words with the bits in big endian order. The in-memory format 843 * is an array of 'unsigned long', which may be either 32 or 64 bits. 844 */ 845 /* This is the number of 64 bit words sent over the wire */ 846 #define BITS_TO_U64S(nr) DIV_ROUND_UP(nr, 64) 847 static int get_bitmap(QEMUFile *f, void *pv, size_t size) 848 { 849 unsigned long *bmp = pv; 850 int i, idx = 0; 851 for (i = 0; i < BITS_TO_U64S(size); i++) { 852 uint64_t w = qemu_get_be64(f); 853 bmp[idx++] = w; 854 if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) { 855 bmp[idx++] = w >> 32; 856 } 857 } 858 return 0; 859 } 860 861 static void put_bitmap(QEMUFile *f, void *pv, size_t size) 862 { 863 unsigned long *bmp = pv; 864 int i, idx = 0; 865 for (i = 0; i < BITS_TO_U64S(size); i++) { 866 uint64_t w = bmp[idx++]; 867 if (sizeof(unsigned long) == 4 && idx < BITS_TO_LONGS(size)) { 868 w |= ((uint64_t)bmp[idx++]) << 32; 869 } 870 qemu_put_be64(f, w); 871 } 872 } 873 874 const VMStateInfo vmstate_info_bitmap = { 875 .name = "bitmap", 876 .get = get_bitmap, 877 .put = put_bitmap, 878 }; 879