Revision c88676f8
b/vl.c | ||
---|---|---|
29 | 29 |
#include <time.h> |
30 | 30 |
#include <errno.h> |
31 | 31 |
#include <sys/time.h> |
32 |
#include <zlib.h> |
|
32 | 33 |
|
33 | 34 |
#ifndef _WIN32 |
34 | 35 |
#include <sys/times.h> |
... | ... | |
822 | 823 |
} |
823 | 824 |
qemu_put_be64s(f, &cpu_ticks_offset); |
824 | 825 |
qemu_put_be64s(f, &ticks_per_sec); |
826 |
qemu_put_be64s(f, &cpu_clock_offset); |
|
825 | 827 |
} |
826 | 828 |
|
827 | 829 |
static int timer_load(QEMUFile *f, void *opaque, int version_id) |
828 | 830 |
{ |
829 |
if (version_id != 1) |
|
831 |
if (version_id != 1 && version_id != 2)
|
|
830 | 832 |
return -EINVAL; |
831 | 833 |
if (cpu_ticks_enabled) { |
832 | 834 |
return -EINVAL; |
833 | 835 |
} |
834 | 836 |
qemu_get_be64s(f, &cpu_ticks_offset); |
835 | 837 |
qemu_get_be64s(f, &ticks_per_sec); |
838 |
if (version_id == 2) { |
|
839 |
qemu_get_be64s(f, &cpu_clock_offset); |
|
840 |
} |
|
836 | 841 |
return 0; |
837 | 842 |
} |
838 | 843 |
|
... | ... | |
5114 | 5119 |
/***********************************************************/ |
5115 | 5120 |
/* ram save/restore */ |
5116 | 5121 |
|
5117 |
/* we just avoid storing empty pages */ |
|
5118 |
static void ram_put_page(QEMUFile *f, const uint8_t *buf, int len) |
|
5119 |
{ |
|
5120 |
int i, v; |
|
5121 |
|
|
5122 |
v = buf[0]; |
|
5123 |
for(i = 1; i < len; i++) { |
|
5124 |
if (buf[i] != v) |
|
5125 |
goto normal_save; |
|
5126 |
} |
|
5127 |
qemu_put_byte(f, 1); |
|
5128 |
qemu_put_byte(f, v); |
|
5129 |
return; |
|
5130 |
normal_save: |
|
5131 |
qemu_put_byte(f, 0); |
|
5132 |
qemu_put_buffer(f, buf, len); |
|
5133 |
} |
|
5134 |
|
|
5135 | 5122 |
static int ram_get_page(QEMUFile *f, uint8_t *buf, int len) |
5136 | 5123 |
{ |
5137 | 5124 |
int v; |
... | ... | |
5152 | 5139 |
return 0; |
5153 | 5140 |
} |
5154 | 5141 |
|
5142 |
static int ram_load_v1(QEMUFile *f, void *opaque) |
|
5143 |
{ |
|
5144 |
int i, ret; |
|
5145 |
|
|
5146 |
if (qemu_get_be32(f) != phys_ram_size) |
|
5147 |
return -EINVAL; |
|
5148 |
for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) { |
|
5149 |
ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE); |
|
5150 |
if (ret) |
|
5151 |
return ret; |
|
5152 |
} |
|
5153 |
return 0; |
|
5154 |
} |
|
5155 |
|
|
5156 |
#define BDRV_HASH_BLOCK_SIZE 1024 |
|
5157 |
#define IOBUF_SIZE 4096 |
|
5158 |
#define RAM_CBLOCK_MAGIC 0xfabe |
|
5159 |
|
|
5160 |
typedef struct RamCompressState { |
|
5161 |
z_stream zstream; |
|
5162 |
QEMUFile *f; |
|
5163 |
uint8_t buf[IOBUF_SIZE]; |
|
5164 |
} RamCompressState; |
|
5165 |
|
|
5166 |
static int ram_compress_open(RamCompressState *s, QEMUFile *f) |
|
5167 |
{ |
|
5168 |
int ret; |
|
5169 |
memset(s, 0, sizeof(*s)); |
|
5170 |
s->f = f; |
|
5171 |
ret = deflateInit2(&s->zstream, 1, |
|
5172 |
Z_DEFLATED, 15, |
|
5173 |
9, Z_DEFAULT_STRATEGY); |
|
5174 |
if (ret != Z_OK) |
|
5175 |
return -1; |
|
5176 |
s->zstream.avail_out = IOBUF_SIZE; |
|
5177 |
s->zstream.next_out = s->buf; |
|
5178 |
return 0; |
|
5179 |
} |
|
5180 |
|
|
5181 |
static void ram_put_cblock(RamCompressState *s, const uint8_t *buf, int len) |
|
5182 |
{ |
|
5183 |
qemu_put_be16(s->f, RAM_CBLOCK_MAGIC); |
|
5184 |
qemu_put_be16(s->f, len); |
|
5185 |
qemu_put_buffer(s->f, buf, len); |
|
5186 |
} |
|
5187 |
|
|
5188 |
static int ram_compress_buf(RamCompressState *s, const uint8_t *buf, int len) |
|
5189 |
{ |
|
5190 |
int ret; |
|
5191 |
|
|
5192 |
s->zstream.avail_in = len; |
|
5193 |
s->zstream.next_in = (uint8_t *)buf; |
|
5194 |
while (s->zstream.avail_in > 0) { |
|
5195 |
ret = deflate(&s->zstream, Z_NO_FLUSH); |
|
5196 |
if (ret != Z_OK) |
|
5197 |
return -1; |
|
5198 |
if (s->zstream.avail_out == 0) { |
|
5199 |
ram_put_cblock(s, s->buf, IOBUF_SIZE); |
|
5200 |
s->zstream.avail_out = IOBUF_SIZE; |
|
5201 |
s->zstream.next_out = s->buf; |
|
5202 |
} |
|
5203 |
} |
|
5204 |
return 0; |
|
5205 |
} |
|
5206 |
|
|
5207 |
static void ram_compress_close(RamCompressState *s) |
|
5208 |
{ |
|
5209 |
int len, ret; |
|
5210 |
|
|
5211 |
/* compress last bytes */ |
|
5212 |
for(;;) { |
|
5213 |
ret = deflate(&s->zstream, Z_FINISH); |
|
5214 |
if (ret == Z_OK || ret == Z_STREAM_END) { |
|
5215 |
len = IOBUF_SIZE - s->zstream.avail_out; |
|
5216 |
if (len > 0) { |
|
5217 |
ram_put_cblock(s, s->buf, len); |
|
5218 |
} |
|
5219 |
s->zstream.avail_out = IOBUF_SIZE; |
|
5220 |
s->zstream.next_out = s->buf; |
|
5221 |
if (ret == Z_STREAM_END) |
|
5222 |
break; |
|
5223 |
} else { |
|
5224 |
goto fail; |
|
5225 |
} |
|
5226 |
} |
|
5227 |
fail: |
|
5228 |
deflateEnd(&s->zstream); |
|
5229 |
} |
|
5230 |
|
|
5231 |
typedef struct RamDecompressState { |
|
5232 |
z_stream zstream; |
|
5233 |
QEMUFile *f; |
|
5234 |
uint8_t buf[IOBUF_SIZE]; |
|
5235 |
} RamDecompressState; |
|
5236 |
|
|
5237 |
static int ram_decompress_open(RamDecompressState *s, QEMUFile *f) |
|
5238 |
{ |
|
5239 |
int ret; |
|
5240 |
memset(s, 0, sizeof(*s)); |
|
5241 |
s->f = f; |
|
5242 |
ret = inflateInit(&s->zstream); |
|
5243 |
if (ret != Z_OK) |
|
5244 |
return -1; |
|
5245 |
return 0; |
|
5246 |
} |
|
5247 |
|
|
5248 |
static int ram_decompress_buf(RamDecompressState *s, uint8_t *buf, int len) |
|
5249 |
{ |
|
5250 |
int ret, clen; |
|
5251 |
|
|
5252 |
s->zstream.avail_out = len; |
|
5253 |
s->zstream.next_out = buf; |
|
5254 |
while (s->zstream.avail_out > 0) { |
|
5255 |
if (s->zstream.avail_in == 0) { |
|
5256 |
if (qemu_get_be16(s->f) != RAM_CBLOCK_MAGIC) |
|
5257 |
return -1; |
|
5258 |
clen = qemu_get_be16(s->f); |
|
5259 |
if (clen > IOBUF_SIZE) |
|
5260 |
return -1; |
|
5261 |
qemu_get_buffer(s->f, s->buf, clen); |
|
5262 |
s->zstream.avail_in = clen; |
|
5263 |
s->zstream.next_in = s->buf; |
|
5264 |
} |
|
5265 |
ret = inflate(&s->zstream, Z_PARTIAL_FLUSH); |
|
5266 |
if (ret != Z_OK && ret != Z_STREAM_END) { |
|
5267 |
return -1; |
|
5268 |
} |
|
5269 |
} |
|
5270 |
return 0; |
|
5271 |
} |
|
5272 |
|
|
5273 |
static void ram_decompress_close(RamDecompressState *s) |
|
5274 |
{ |
|
5275 |
inflateEnd(&s->zstream); |
|
5276 |
} |
|
5277 |
|
|
5155 | 5278 |
static void ram_save(QEMUFile *f, void *opaque) |
5156 | 5279 |
{ |
5157 | 5280 |
int i; |
5281 |
RamCompressState s1, *s = &s1; |
|
5282 |
uint8_t buf[10]; |
|
5283 |
|
|
5158 | 5284 |
qemu_put_be32(f, phys_ram_size); |
5159 |
for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) { |
|
5160 |
ram_put_page(f, phys_ram_base + i, TARGET_PAGE_SIZE); |
|
5285 |
if (ram_compress_open(s, f) < 0) |
|
5286 |
return; |
|
5287 |
for(i = 0; i < phys_ram_size; i+= BDRV_HASH_BLOCK_SIZE) { |
|
5288 |
#if 0 |
|
5289 |
if (tight_savevm_enabled) { |
|
5290 |
int64_t sector_num; |
|
5291 |
int j; |
|
5292 |
|
|
5293 |
/* find if the memory block is available on a virtual |
|
5294 |
block device */ |
|
5295 |
sector_num = -1; |
|
5296 |
for(j = 0; j < MAX_DISKS; j++) { |
|
5297 |
if (bs_table[j]) { |
|
5298 |
sector_num = bdrv_hash_find(bs_table[j], |
|
5299 |
phys_ram_base + i, BDRV_HASH_BLOCK_SIZE); |
|
5300 |
if (sector_num >= 0) |
|
5301 |
break; |
|
5302 |
} |
|
5303 |
} |
|
5304 |
if (j == MAX_DISKS) |
|
5305 |
goto normal_compress; |
|
5306 |
buf[0] = 1; |
|
5307 |
buf[1] = j; |
|
5308 |
cpu_to_be64wu((uint64_t *)(buf + 2), sector_num); |
|
5309 |
ram_compress_buf(s, buf, 10); |
|
5310 |
} else |
|
5311 |
#endif |
|
5312 |
{ |
|
5313 |
// normal_compress: |
|
5314 |
buf[0] = 0; |
|
5315 |
ram_compress_buf(s, buf, 1); |
|
5316 |
ram_compress_buf(s, phys_ram_base + i, BDRV_HASH_BLOCK_SIZE); |
|
5317 |
} |
|
5161 | 5318 |
} |
5319 |
ram_compress_close(s); |
|
5162 | 5320 |
} |
5163 | 5321 |
|
5164 | 5322 |
static int ram_load(QEMUFile *f, void *opaque, int version_id) |
5165 | 5323 |
{ |
5166 |
int i, ret; |
|
5324 |
RamDecompressState s1, *s = &s1; |
|
5325 |
uint8_t buf[10]; |
|
5326 |
int i; |
|
5167 | 5327 |
|
5168 |
if (version_id != 1) |
|
5328 |
if (version_id == 1) |
|
5329 |
return ram_load_v1(f, opaque); |
|
5330 |
if (version_id != 2) |
|
5169 | 5331 |
return -EINVAL; |
5170 | 5332 |
if (qemu_get_be32(f) != phys_ram_size) |
5171 | 5333 |
return -EINVAL; |
5172 |
for(i = 0; i < phys_ram_size; i+= TARGET_PAGE_SIZE) { |
|
5173 |
ret = ram_get_page(f, phys_ram_base + i, TARGET_PAGE_SIZE); |
|
5174 |
if (ret) |
|
5175 |
return ret; |
|
5334 |
if (ram_decompress_open(s, f) < 0) |
|
5335 |
return -EINVAL; |
|
5336 |
for(i = 0; i < phys_ram_size; i+= BDRV_HASH_BLOCK_SIZE) { |
|
5337 |
if (ram_decompress_buf(s, buf, 1) < 0) { |
|
5338 |
fprintf(stderr, "Error while reading ram block header\n"); |
|
5339 |
goto error; |
|
5340 |
} |
|
5341 |
if (buf[0] == 0) { |
|
5342 |
if (ram_decompress_buf(s, phys_ram_base + i, BDRV_HASH_BLOCK_SIZE) < 0) { |
|
5343 |
fprintf(stderr, "Error while reading ram block address=0x%08x", i); |
|
5344 |
goto error; |
|
5345 |
} |
|
5346 |
} else |
|
5347 |
#if 0 |
|
5348 |
if (buf[0] == 1) { |
|
5349 |
int bs_index; |
|
5350 |
int64_t sector_num; |
|
5351 |
|
|
5352 |
ram_decompress_buf(s, buf + 1, 9); |
|
5353 |
bs_index = buf[1]; |
|
5354 |
sector_num = be64_to_cpupu((const uint64_t *)(buf + 2)); |
|
5355 |
if (bs_index >= MAX_DISKS || bs_table[bs_index] == NULL) { |
|
5356 |
fprintf(stderr, "Invalid block device index %d\n", bs_index); |
|
5357 |
goto error; |
|
5358 |
} |
|
5359 |
if (bdrv_read(bs_table[bs_index], sector_num, phys_ram_base + i, |
|
5360 |
BDRV_HASH_BLOCK_SIZE / 512) < 0) { |
|
5361 |
fprintf(stderr, "Error while reading sector %d:%" PRId64 "\n", |
|
5362 |
bs_index, sector_num); |
|
5363 |
goto error; |
|
5364 |
} |
|
5365 |
} else |
|
5366 |
#endif |
|
5367 |
{ |
|
5368 |
error: |
|
5369 |
printf("Error block header\n"); |
|
5370 |
return -EINVAL; |
|
5371 |
} |
|
5176 | 5372 |
} |
5373 |
ram_decompress_close(s); |
|
5177 | 5374 |
return 0; |
5178 | 5375 |
} |
5179 | 5376 |
|
... | ... | |
6612 | 6809 |
} |
6613 | 6810 |
} |
6614 | 6811 |
|
6615 |
register_savevm("timer", 0, 1, timer_save, timer_load, NULL);
|
|
6616 |
register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
|
|
6812 |
register_savevm("timer", 0, 2, timer_save, timer_load, NULL);
|
|
6813 |
register_savevm("ram", 0, 2, ram_save, ram_load, NULL);
|
|
6617 | 6814 |
|
6618 | 6815 |
init_ioports(); |
6619 | 6816 |
|
Also available in: Unified diff