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