Revision 302dfbeb savevm.c
b/savevm.c | ||
---|---|---|
2392 | 2392 |
{ |
2393 | 2393 |
vmstate_register_ram(mr, NULL); |
2394 | 2394 |
} |
2395 |
|
|
2396 |
/* |
|
2397 |
page = zrun nzrun |
|
2398 |
| zrun nzrun page |
|
2399 |
|
|
2400 |
zrun = length |
|
2401 |
|
|
2402 |
nzrun = length byte... |
|
2403 |
|
|
2404 |
length = uleb128 encoded integer |
|
2405 |
*/ |
|
2406 |
int xbzrle_encode_buffer(uint8_t *old_buf, uint8_t *new_buf, int slen, |
|
2407 |
uint8_t *dst, int dlen) |
|
2408 |
{ |
|
2409 |
uint32_t zrun_len = 0, nzrun_len = 0; |
|
2410 |
int d = 0, i = 0; |
|
2411 |
long res, xor; |
|
2412 |
uint8_t *nzrun_start = NULL; |
|
2413 |
|
|
2414 |
g_assert(!(((uintptr_t)old_buf | (uintptr_t)new_buf | slen) % |
|
2415 |
sizeof(long))); |
|
2416 |
|
|
2417 |
while (i < slen) { |
|
2418 |
/* overflow */ |
|
2419 |
if (d + 2 > dlen) { |
|
2420 |
return -1; |
|
2421 |
} |
|
2422 |
|
|
2423 |
/* not aligned to sizeof(long) */ |
|
2424 |
res = (slen - i) % sizeof(long); |
|
2425 |
while (res && old_buf[i] == new_buf[i]) { |
|
2426 |
zrun_len++; |
|
2427 |
i++; |
|
2428 |
res--; |
|
2429 |
} |
|
2430 |
|
|
2431 |
/* word at a time for speed */ |
|
2432 |
if (!res) { |
|
2433 |
while (i < slen && |
|
2434 |
(*(long *)(old_buf + i)) == (*(long *)(new_buf + i))) { |
|
2435 |
i += sizeof(long); |
|
2436 |
zrun_len += sizeof(long); |
|
2437 |
} |
|
2438 |
|
|
2439 |
/* go over the rest */ |
|
2440 |
while (i < slen && old_buf[i] == new_buf[i]) { |
|
2441 |
zrun_len++; |
|
2442 |
i++; |
|
2443 |
} |
|
2444 |
} |
|
2445 |
|
|
2446 |
/* buffer unchanged */ |
|
2447 |
if (zrun_len == slen) { |
|
2448 |
return 0; |
|
2449 |
} |
|
2450 |
|
|
2451 |
/* skip last zero run */ |
|
2452 |
if (i == slen) { |
|
2453 |
return d; |
|
2454 |
} |
|
2455 |
|
|
2456 |
d += uleb128_encode_small(dst + d, zrun_len); |
|
2457 |
|
|
2458 |
zrun_len = 0; |
|
2459 |
nzrun_start = new_buf + i; |
|
2460 |
|
|
2461 |
/* overflow */ |
|
2462 |
if (d + 2 > dlen) { |
|
2463 |
return -1; |
|
2464 |
} |
|
2465 |
/* not aligned to sizeof(long) */ |
|
2466 |
res = (slen - i) % sizeof(long); |
|
2467 |
while (res && old_buf[i] != new_buf[i]) { |
|
2468 |
i++; |
|
2469 |
nzrun_len++; |
|
2470 |
res--; |
|
2471 |
} |
|
2472 |
|
|
2473 |
/* word at a time for speed, use of 32-bit long okay */ |
|
2474 |
if (!res) { |
|
2475 |
/* truncation to 32-bit long okay */ |
|
2476 |
long mask = 0x0101010101010101ULL; |
|
2477 |
while (i < slen) { |
|
2478 |
xor = *(long *)(old_buf + i) ^ *(long *)(new_buf + i); |
|
2479 |
if ((xor - mask) & ~xor & (mask << 7)) { |
|
2480 |
/* found the end of an nzrun within the current long */ |
|
2481 |
while (old_buf[i] != new_buf[i]) { |
|
2482 |
nzrun_len++; |
|
2483 |
i++; |
|
2484 |
} |
|
2485 |
break; |
|
2486 |
} else { |
|
2487 |
i += sizeof(long); |
|
2488 |
nzrun_len += sizeof(long); |
|
2489 |
} |
|
2490 |
} |
|
2491 |
} |
|
2492 |
|
|
2493 |
d += uleb128_encode_small(dst + d, nzrun_len); |
|
2494 |
/* overflow */ |
|
2495 |
if (d + nzrun_len > dlen) { |
|
2496 |
return -1; |
|
2497 |
} |
|
2498 |
memcpy(dst + d, nzrun_start, nzrun_len); |
|
2499 |
d += nzrun_len; |
|
2500 |
nzrun_len = 0; |
|
2501 |
} |
|
2502 |
|
|
2503 |
return d; |
|
2504 |
} |
|
2505 |
|
|
2506 |
int xbzrle_decode_buffer(uint8_t *src, int slen, uint8_t *dst, int dlen) |
|
2507 |
{ |
|
2508 |
int i = 0, d = 0; |
|
2509 |
int ret; |
|
2510 |
uint32_t count = 0; |
|
2511 |
|
|
2512 |
while (i < slen) { |
|
2513 |
|
|
2514 |
/* zrun */ |
|
2515 |
if ((slen - i) < 2) { |
|
2516 |
return -1; |
|
2517 |
} |
|
2518 |
|
|
2519 |
ret = uleb128_decode_small(src + i, &count); |
|
2520 |
if (ret < 0 || (i && !count)) { |
|
2521 |
return -1; |
|
2522 |
} |
|
2523 |
i += ret; |
|
2524 |
d += count; |
|
2525 |
|
|
2526 |
/* overflow */ |
|
2527 |
if (d > dlen) { |
|
2528 |
return -1; |
|
2529 |
} |
|
2530 |
|
|
2531 |
/* nzrun */ |
|
2532 |
if ((slen - i) < 2) { |
|
2533 |
return -1; |
|
2534 |
} |
|
2535 |
|
|
2536 |
ret = uleb128_decode_small(src + i, &count); |
|
2537 |
if (ret < 0 || !count) { |
|
2538 |
return -1; |
|
2539 |
} |
|
2540 |
i += ret; |
|
2541 |
|
|
2542 |
/* overflow */ |
|
2543 |
if (d + count > dlen || i + count > slen) { |
|
2544 |
return -1; |
|
2545 |
} |
|
2546 |
|
|
2547 |
memcpy(dst + d, src + i, count); |
|
2548 |
d += count; |
|
2549 |
i += count; |
|
2550 |
} |
|
2551 |
|
|
2552 |
return d; |
|
2553 |
} |
Also available in: Unified diff