Revision 97ab12d4

b/arch_init.c
113 113

  
114 114
    while (addr < total_ram) {
115 115
        if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
116
            RAMBlock *block;
117
            ram_addr_t offset;
116 118
            uint8_t *p;
117 119

  
118 120
            cpu_physical_memory_reset_dirty(current_addr,
119 121
                                            current_addr + TARGET_PAGE_SIZE,
120 122
                                            MIGRATION_DIRTY_FLAG);
121 123

  
122
            p = qemu_get_ram_ptr(current_addr);
124
            QLIST_FOREACH(block, &ram_list.blocks, next) {
125
                if (current_addr - block->offset < block->length)
126
                    break;
127
            }
128
            offset = current_addr - block->offset;
129
            p = block->host + offset;
123 130

  
124 131
            if (is_dup_page(p, *p)) {
125
                qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS);
132
                qemu_put_be64(f, offset | RAM_SAVE_FLAG_COMPRESS);
133
                qemu_put_byte(f, strlen(block->idstr));
134
                qemu_put_buffer(f, (uint8_t *)block->idstr,
135
                                strlen(block->idstr));
126 136
                qemu_put_byte(f, *p);
127 137
                bytes_sent = 1;
128 138
            } else {
129
                qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE);
139
                qemu_put_be64(f, offset | RAM_SAVE_FLAG_PAGE);
140
                qemu_put_byte(f, strlen(block->idstr));
141
                qemu_put_buffer(f, (uint8_t *)block->idstr,
142
                                strlen(block->idstr));
130 143
                qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
131 144
                bytes_sent = TARGET_PAGE_SIZE;
132 145
            }
......
196 209
    }
197 210

  
198 211
    if (stage == 1) {
212
        RAMBlock *block;
199 213
        uint64_t total_ram = ram_bytes_total();
200 214
        bytes_transferred = 0;
201 215

  
......
210 224
        cpu_physical_memory_set_dirty_tracking(1);
211 225

  
212 226
        qemu_put_be64(f, total_ram | RAM_SAVE_FLAG_MEM_SIZE);
227

  
228
        QLIST_FOREACH(block, &ram_list.blocks, next) {
229
            qemu_put_byte(f, strlen(block->idstr));
230
            qemu_put_buffer(f, (uint8_t *)block->idstr, strlen(block->idstr));
231
            qemu_put_be64(f, block->length);
232
        }
213 233
    }
214 234

  
215 235
    bytes_transferred_last = bytes_transferred;
......
257 277
    ram_addr_t addr;
258 278
    int flags;
259 279

  
260
    if (version_id != 3) {
280
    if (version_id < 3 || version_id > 4) {
261 281
        return -EINVAL;
262 282
    }
263 283

  
......
268 288
        addr &= TARGET_PAGE_MASK;
269 289

  
270 290
        if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
271
            if (addr != ram_bytes_total()) {
272
                return -EINVAL;
291
            if (version_id == 3) {
292
                if (addr != ram_bytes_total()) {
293
                    return -EINVAL;
294
                }
295
            } else {
296
                /* Synchronize RAM block list */
297
                char id[256];
298
                ram_addr_t length;
299
                ram_addr_t total_ram_bytes = addr;
300

  
301
                while (total_ram_bytes) {
302
                    RAMBlock *block;
303
                    uint8_t len;
304

  
305
                    len = qemu_get_byte(f);
306
                    qemu_get_buffer(f, (uint8_t *)id, len);
307
                    id[len] = 0;
308
                    length = qemu_get_be64(f);
309

  
310
                    QLIST_FOREACH(block, &ram_list.blocks, next) {
311
                        if (!strncmp(id, block->idstr, sizeof(id))) {
312
                            if (block->length != length)
313
                                return -EINVAL;
314
                            break;
315
                        }
316
                    }
317

  
318
                    if (!block) {
319
                        if (!qemu_ram_alloc(NULL, id, length))
320
                            return -ENOMEM;
321
                    }
322

  
323
                    total_ram_bytes -= length;
324
                }
273 325
            }
274 326
        }
275 327

  
276 328
        if (flags & RAM_SAVE_FLAG_COMPRESS) {
277
            uint8_t ch = qemu_get_byte(f);
278
            memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
329
            void *host;
330
            uint8_t ch;
331

  
332
            if (version_id == 3) {
333
                host = qemu_get_ram_ptr(addr);
334
            } else {
335
                RAMBlock *block;
336
                char id[256];
337
                uint8_t len;
338

  
339
                len = qemu_get_byte(f);
340
                qemu_get_buffer(f, (uint8_t *)id, len);
341
                id[len] = 0;
342

  
343
                QLIST_FOREACH(block, &ram_list.blocks, next) {
344
                    if (!strncmp(id, block->idstr, sizeof(id)))
345
                        break;
346
                }
347
                if (!block)
348
                    return -EINVAL;
349

  
350
                host = block->host + addr;
351
            }
352
            ch = qemu_get_byte(f);
353
            memset(host, ch, TARGET_PAGE_SIZE);
279 354
#ifndef _WIN32
280 355
            if (ch == 0 &&
281 356
                (!kvm_enabled() || kvm_has_sync_mmu())) {
282
                madvise(qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE,
283
                        MADV_DONTNEED);
357
                madvise(host, TARGET_PAGE_SIZE, MADV_DONTNEED);
284 358
            }
285 359
#endif
286 360
        } else if (flags & RAM_SAVE_FLAG_PAGE) {
287
            qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE);
361
            void *host;
362

  
363
            if (version_id == 3) {
364
                host = qemu_get_ram_ptr(addr);
365
            } else {
366
                RAMBlock *block;
367
                char id[256];
368
                uint8_t len;
369

  
370
                len = qemu_get_byte(f);
371
                qemu_get_buffer(f, (uint8_t *)id, len);
372
                id[len] = 0;
373

  
374
                QLIST_FOREACH(block, &ram_list.blocks, next) {
375
                    if (!strncmp(id, block->idstr, sizeof(id)))
376
                        break;
377
                }
378
                if (!block)
379
                    return -EINVAL;
380

  
381
                host = block->host + addr;
382
            }
383
            qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
288 384
        }
289 385
        if (qemu_file_has_error(f)) {
290 386
            return -EIO;
b/vl.c
2794 2794
    if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
2795 2795
        exit(1);
2796 2796

  
2797
    register_savevm_live(NULL, "ram", 0, 3, NULL, ram_save_live, NULL, 
2797
    register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
2798 2798
                         ram_load, NULL);
2799 2799

  
2800 2800
    if (nb_numa_nodes > 0) {

Also available in: Unified diff