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