int ram_load(QEMUFile *f, void *opaque, int version_id) { ram_addr_t addr; int flags; if (version_id < 3 || version_id > 4) { return -EINVAL; } do { addr = qemu_get_be64(f); flags = addr & ~TARGET_PAGE_MASK; addr &= TARGET_PAGE_MASK; if (flags & RAM_SAVE_FLAG_MEM_SIZE) { if (version_id == 3) { if (addr != ram_bytes_total()) { return -EINVAL; } } else { /* Synchronize RAM block list */ char id[256]; ram_addr_t length; ram_addr_t total_ram_bytes = addr; while (total_ram_bytes) { RAMBlock *block; uint8_t len; len = qemu_get_byte(f); qemu_get_buffer(f, (uint8_t *)id, len); id[len] = 0; length = qemu_get_be64(f); QLIST_FOREACH(block, &ram_list.blocks, next) { if (!strncmp(id, block->idstr, sizeof(id))) { if (block->length != length) return -EINVAL; break; } } if (!block) { fprintf(stderr, "Unknown ramblock \"%s\", cannot " "accept migration\n", id); return -EINVAL; } total_ram_bytes -= length; } } } if (flags & RAM_SAVE_FLAG_COMPRESS) { void *host; uint8_t ch; if (version_id == 3) host = qemu_get_ram_ptr(addr); else host = host_from_stream_offset(f, addr, flags); ch = qemu_get_byte(f); memset(host, ch, TARGET_PAGE_SIZE); #ifndef _WIN32 if (ch == 0 && (!kvm_enabled() || kvm_has_sync_mmu())) { madvise(host, TARGET_PAGE_SIZE, MADV_DONTNEED); } #endif } else if (flags & RAM_SAVE_FLAG_PAGE) { void *host; if (version_id == 3) host = qemu_get_ram_ptr(addr); else host = host_from_stream_offset(f, addr, flags); qemu_get_buffer(f, host, TARGET_PAGE_SIZE); } if (qemu_file_has_error(f)) { return -EIO; } } while (!(flags & RAM_SAVE_FLAG_EOS)); return 0; }