qemu migration: tcp migration: timeout if migration-end messages do not arrive on...
[qemu-kvm/fedora.git] / migration.c
blob9103eb8de735b55eb892d5752b75d5429b665282
1 /*
2 * QEMU migration support
3 *
4 * Copyright (C) 2007 Anthony Liguori <anthony@codemonkey.ws>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
25 #include "vl.h"
26 #include "qemu_socket.h"
27 #ifdef USE_KVM
28 #include "qemu-kvm.h"
29 #endif
31 #include <sys/wait.h>
33 #define MIN_FINALIZE_SIZE (200 << 10)
35 typedef struct MigrationState
37 int fd;
38 int throttle_count;
39 int bps;
40 int updated_pages;
41 int last_updated_pages;
42 int iteration;
43 int n_buffer; /* number of bytes in @buffer already sent */
44 int l_buffer; /* number of bytes in @buffer to send */
45 int throttled;
46 int *has_error;
47 char buffer[TARGET_PAGE_SIZE + 4 + 4];
48 target_ulong addr;
49 QEMUTimer *timer;
50 void *opaque;
51 int detach;
52 int (*release)(void *opaque);
53 } MigrationState;
55 static uint32_t max_throttle = (32 << 20);
56 static MigrationState *current_migration;
57 static int wait_for_message_timeout = 3000; /* 3 seconds */
59 //#define MIGRATION_VERIFY
60 #ifdef MIGRATION_VERIFY
61 static int save_verify_memory(QEMUFile *f, void *opaque);
62 static int load_verify_memory(QEMUFile *f, void *opaque, int version_id);
63 #endif /* MIGRATION_VERIFY */
65 /* QEMUFile migration implementation */
67 static void migrate_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
69 MigrationState *s = opaque;
70 int offset = 0;
72 if (*s->has_error)
73 return;
75 while (offset < size) {
76 ssize_t len;
78 len = write(s->fd, buf + offset, size - offset);
79 if (len == -1) {
80 if (errno == EAGAIN || errno == EINTR)
81 continue;
82 term_printf("migration: write failed (%s)\n", strerror(errno));
83 *s->has_error = 10;
84 break;
85 } else if (len == 0) {
86 term_printf("migration: other side closed connection\n");
87 *s->has_error = 11;
88 break;
91 offset += len;
95 static void migrate_close(void *opaque)
97 MigrationState *s = opaque;
99 if (s->release && s->release(s->opaque))
100 *s->has_error = 12;
102 qemu_free(s);
103 current_migration = NULL;
106 /* Outgoing migration routines */
107 static void migrate_finish(MigrationState *s)
109 QEMUFile *f;
110 int ret = 0;
111 int *has_error = s->has_error;
113 fcntl(s->fd, F_SETFL, 0);
115 if (! *has_error) {
116 f = qemu_fopen(s, migrate_put_buffer, NULL, migrate_close);
117 qemu_aio_flush();
118 vm_stop(0);
119 qemu_put_be32(f, 1);
120 ret = qemu_live_savevm_state(f);
121 #ifdef MIGRATION_VERIFY
122 save_verify_memory(f, NULL);
123 #endif /* MIGRATION_VERIFY */
124 qemu_fclose(f);
126 if (ret != 0 || *has_error) {
127 term_printf("Migration failed! ret=%d error=%d\n", ret, *has_error);
128 vm_start();
130 if (!s->detach)
131 monitor_resume();
132 qemu_free(has_error);
133 cpu_physical_memory_set_dirty_tracking(0);
136 static int migrate_write_buffer(MigrationState *s)
138 if (*s->has_error)
139 return 0;
141 if (s->n_buffer < s->l_buffer) {
142 ssize_t len;
143 again:
144 len = write(s->fd, s->buffer + s->n_buffer, s->l_buffer - s->n_buffer);
145 if (len == -1) {
146 if (errno == EINTR)
147 goto again;
148 if (errno == EAGAIN)
149 return 1;
150 *s->has_error = 13;
151 return 0;
153 if (len == 0) {
154 *s->has_error = 14;
155 return 0;
158 s->throttle_count += len;
159 s->n_buffer += len;
160 if (s->n_buffer < s->l_buffer)
161 goto again;
164 if (s->throttle_count > max_throttle) {
165 s->throttled = 1;
166 qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
167 return 1;
170 return 0;
173 static int migrate_check_convergence(MigrationState *s)
175 target_ulong addr;
176 int dirty_count = 0;
178 for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) {
179 #ifdef USE_KVM
180 if (kvm_allowed && (addr>=0xa0000) && (addr<0xc0000)) /* do not access video-addresses */
181 continue;
182 #endif
183 if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
184 dirty_count++;
187 return ((dirty_count * TARGET_PAGE_SIZE) < MIN_FINALIZE_SIZE);
190 static int ram_page_is_homogeneous(uint32_t addr)
192 int i, n;
193 uint32_t *p, v;
195 n = TARGET_PAGE_SIZE / sizeof(v);
196 p = (uint32 *)(phys_ram_base + addr);
198 v = p[0];
199 for (i=1; i<n; i++)
200 if (p[i] != v)
201 return 0;
202 return 1;
205 static void migrate_prepare_page(MigrationState *s)
207 uint32_t value;
208 char type;
209 const char *buff;
210 int bufflen;
212 value = cpu_to_be32(s->addr);
213 memcpy(s->buffer, &value, 4);
215 if (ram_page_is_homogeneous(s->addr)) {
216 type = 1; /* keeping ram_get_page() values */
217 bufflen = 4;
218 value = cpu_to_be32(s->addr);
219 buff = (const char *)&value;
221 else {
222 type = 0;
223 bufflen = TARGET_PAGE_SIZE;
224 buff = phys_ram_base + s->addr;
227 s->buffer[4] = type;
228 memcpy(s->buffer + 4 + 1, phys_ram_base + s->addr, bufflen);
229 s->n_buffer = 0;
230 s->l_buffer = 4 + 1 + bufflen;
233 static void migrate_write(void *opaque)
235 MigrationState *s = opaque;
237 if (migrate_write_buffer(s))
238 return;
240 #ifdef USE_KVM
241 if (kvm_allowed && !*s->has_error)
242 *s->has_error = kvm_update_dirty_pages_log();
243 #endif
245 if (migrate_check_convergence(s) || *s->has_error) {
246 qemu_del_timer(s->timer);
247 qemu_free_timer(s->timer);
248 qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
249 migrate_finish(s);
250 return;
253 while (s->addr < phys_ram_size) {
254 #ifdef USE_KVM
255 if (kvm_allowed && (s->addr>=0xa0000) && (s->addr<0xc0000)) /* do not access video-addresses */
256 s->addr = 0xc0000;
257 #endif
259 if (cpu_physical_memory_get_dirty(s->addr, MIGRATION_DIRTY_FLAG)) {
260 migrate_prepare_page(s);
261 cpu_physical_memory_reset_dirty(s->addr, s->addr + TARGET_PAGE_SIZE, MIGRATION_DIRTY_FLAG);
263 s->addr += TARGET_PAGE_SIZE;
265 s->updated_pages++;
267 if (migrate_write_buffer(s))
268 return;
269 } else
270 s->addr += TARGET_PAGE_SIZE;
273 s->last_updated_pages = s->updated_pages;
274 s->updated_pages = 0;
275 s->addr = 0;
276 s->iteration++;
279 static void migrate_reset_throttle(void *opaque)
281 MigrationState *s = opaque;
283 s->bps = s->throttle_count;
285 if (s->throttled) {
286 s->throttled = 0;
287 qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_write, s);
289 s->throttle_count = 0;
290 qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 1000);
293 static int start_migration(MigrationState *s)
295 uint32_t value = cpu_to_be32(phys_ram_size);
296 target_phys_addr_t addr;
297 size_t offset = 0;
299 while (offset != 4) {
300 ssize_t len = write(s->fd, ((char *)&value) + offset, 4 - offset);
301 if (len == -1 && errno == EINTR)
302 continue;
304 if (len < 1)
305 return -EIO;
307 offset += len;
310 fcntl(s->fd, F_SETFL, O_NONBLOCK);
312 for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) {
313 #ifdef USE_KVM
314 if (kvm_allowed && (addr>=0xa0000) && (addr<0xc0000)) /* do not access video-addresses */
315 continue;
316 #endif
317 if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
318 cpu_physical_memory_set_dirty(addr);
321 if (cpu_physical_memory_set_dirty_tracking(1)) {
322 *s->has_error = 16;
323 return -1;
326 s->addr = 0;
327 s->iteration = 0;
328 s->updated_pages = 0;
329 s->last_updated_pages = 0;
330 s->n_buffer = s->l_buffer = 0;
331 s->timer = qemu_new_timer(rt_clock, migrate_reset_throttle, s);
333 qemu_mod_timer(s->timer, qemu_get_clock(rt_clock));
334 qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_write, s);
335 return 0;
338 static MigrationState *migration_init_fd(int detach, int fd)
340 MigrationState *s;
342 s = qemu_mallocz(sizeof(MigrationState));
343 if (s == NULL) {
344 term_printf("Allocation error\n");
345 return NULL;
348 s->fd = fd;
349 s->has_error = qemu_mallocz(sizeof(int));
350 if (s->has_error == NULL) {
351 term_printf("malloc failed (for has_error)\n");
352 return NULL;
354 s->detach = detach;
356 current_migration = s;
358 if (start_migration(s) == -1) {
359 term_printf("Could not start migration\n");
360 return NULL;
363 if (!detach)
364 monitor_suspend();
366 return s;
369 typedef struct MigrationCmdState
371 int fd;
372 pid_t pid;
373 } MigrationCmdState;
375 static int cmd_release(void *opaque)
377 MigrationCmdState *c = opaque;
378 int status, ret;
380 close(c->fd);
382 again:
383 ret = waitpid(c->pid, &status, 0);
384 if (ret == -1 && errno == EINTR)
385 goto again;
387 if (ret == -1) {
388 term_printf("migration: waitpid failed (%s)\n", strerror(errno));
389 return -1;
391 /* FIXME: check and uncomment
392 * if (WIFEXITED(status))
393 * status = WEXITSTATUS(status);
395 return status;
398 static MigrationState *migration_init_cmd(int detach, const char *command, char **argv)
400 int fds[2];
401 pid_t pid;
402 int i;
403 MigrationState *s;
405 if (pipe(fds) == -1) {
406 term_printf("pipe() (%s)\n", strerror(errno));
407 return NULL;
410 pid = fork();
411 if (pid == -1) {
412 close(fds[0]);
413 close(fds[1]);
414 term_printf("fork error (%s)\n", strerror(errno));
415 return NULL;
417 if (pid == 0) {
418 close(fds[1]);
419 dup2(fds[0], STDIN_FILENO);
420 execvp(command, argv);
421 exit(1);
422 } else
423 close(fds[0]);
425 for (i = 0; argv[i]; i++)
426 qemu_free(argv[i]);
427 qemu_free(argv);
429 s = migration_init_fd(detach, fds[1]);
430 if (s) {
431 MigrationCmdState *c = qemu_mallocz(sizeof(*c));
432 c->pid = pid;
433 c->fd = fds[1];
434 s->release = cmd_release;
435 s->opaque = c;
438 return s;
441 static MigrationState *migration_init_exec(int detach, const char *command)
443 char **argv = NULL;
445 argv = qemu_mallocz(sizeof(char *) * 4);
446 argv[0] = strdup("sh");
447 argv[1] = strdup("-c");
448 argv[2] = strdup(command);
449 argv[3] = NULL;
451 return migration_init_cmd(detach, "/bin/sh", argv);
454 static MigrationState *migration_init_ssh(int detach, const char *host)
456 int qemu_argc, daemonize = 0, argc, i;
457 char **qemu_argv, **argv;
458 const char *incoming = NULL;
460 qemu_get_launch_info(&qemu_argc, &qemu_argv, &daemonize, &incoming);
462 argc = 3 + qemu_argc;
463 if (!daemonize)
464 argc++;
465 if (!incoming)
466 argc+=2;
468 argv = qemu_mallocz(sizeof(char *) * (argc + 1));
469 argv[0] = strdup("ssh");
470 argv[1] = strdup("-XC");
471 argv[2] = strdup(host);
473 for (i = 0; i < qemu_argc; i++)
474 argv[3 + i] = strdup(qemu_argv[i]);
476 if (!daemonize)
477 argv[3 + i++] = strdup("-daemonize");
478 if (!incoming) {
479 argv[3 + i++] = strdup("-incoming");
480 argv[3 + i++] = strdup("stdio");
483 argv[3 + i] = NULL;
485 return migration_init_cmd(detach, "ssh", argv);
488 /* (busy) wait timeout (miliseconds) for a message to arrive on fd. */
489 /* returns 0 on success error_code otherwise (18 for timeout) */
490 static int wait_for_message(const char *msg, int fd, int timeout)
492 fd_set rfds;
493 struct timeval tv;
494 int64_t now, expiration, delta; /* milliseconds */
495 int n = 0;
497 now = qemu_get_clock(rt_clock);
498 expiration = now + timeout;
499 do {
500 FD_ZERO(&rfds);
501 FD_SET(fd, &rfds);
502 tv.tv_sec = tv.tv_usec = 0;
503 now = qemu_get_clock(rt_clock);
504 delta = expiration - now;
505 if (delta > 0)
506 tv.tv_usec = delta * 1000;
507 n = select(fd + 1, &rfds, NULL, NULL, &tv);
508 } while ( (n == -1) && (errno == EINTR) );
510 switch (n) {
511 case -1: /* error */
512 fprintf(stderr, "%s FAILED: ", msg);
513 perror("");
514 return 17;
515 case 0: /* timeout */
516 fprintf(stderr, "%s: timeout reached\n", msg);
517 return 18;
518 case 1:
519 break;
520 default:
521 fprintf(stderr, "wait_for_message: %s: select returned %d\n", msg, n);
523 if (!FD_ISSET(fd, &rfds)) {
524 fprintf(stderr, "wait_for_message: %s: s->fd not set\n", msg);
525 return 19;
528 return 0;
531 static int tcp_release(void *opaque)
533 MigrationState *s = opaque;
534 uint8_t status = 0;
535 ssize_t len = 0;
536 int n;
538 if (*s->has_error)
539 goto out;
541 n = wait_for_message("WAIT FOR ACK", s->fd, wait_for_message_timeout);
542 if (n) {
543 *s->has_error = n;
544 goto out;
547 wait_for_ack:
548 len = read(s->fd, &status, 1);
549 if (len == -1 && errno == EINTR)
550 goto wait_for_ack;
551 if (len != 1 || status != 0)
552 goto out;
554 send_go:
555 len = write(s->fd, &status, 1);
556 if (len == -1 && errno == EINTR)
557 goto send_go;
559 out:
560 close(s->fd);
562 return (len != 1 || status != 0);
565 static MigrationState *migration_init_tcp(int detach, const char *host)
567 int fd;
568 struct sockaddr_in addr;
569 MigrationState *s;
571 fd = socket(PF_INET, SOCK_STREAM, 0);
572 if (fd == -1) {
573 term_printf("socket() failed %s\n", strerror(errno));
574 return NULL;
577 addr.sin_family = AF_INET;
578 if (parse_host_port(&addr, host) == -1) {
579 term_printf("parse_host_port() FAILED for %s\n", host);
580 close(fd);
581 return NULL;
584 again:
585 if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
586 if (errno == EINTR)
587 goto again;
588 term_printf("connect() failed %s\n", strerror(errno));
589 close(fd);
590 return NULL;
593 s = migration_init_fd(detach, fd);
594 if (s) {
595 s->opaque = s;
596 s->release = tcp_release;
598 return s;
601 /* Incoming migration */
603 static void migrate_incoming_homogeneous_page(uint32_t addr, uint32_t v)
605 int i, n;
606 uint32_t *p;
608 n = TARGET_PAGE_SIZE / sizeof(v);
609 p = (uint32 *)(phys_ram_base + addr);
611 for (i=0; i<n; i++)
612 p[i] = v;
615 static int migrate_incoming_page(QEMUFile *f, uint32_t addr)
617 int l, v, ret = 0;
619 switch (qemu_get_byte(f)) {
620 case 0: /* the whole page */
621 l = qemu_get_buffer(f, phys_ram_base + addr, TARGET_PAGE_SIZE);
622 if (l != TARGET_PAGE_SIZE)
623 ret = 102;
624 break;
625 case 1: /* homogeneous page -- a single byte */
626 v = qemu_get_be32(f);
627 migrate_incoming_homogeneous_page(addr, v);
628 break;
629 default:
630 ret = 104;
633 return ret;
636 static int migrate_incoming_fd(int fd)
638 int ret;
639 QEMUFile *f = qemu_fopen_fd(fd);
640 uint32_t addr;
641 extern void qemu_announce_self(void);
643 if (qemu_get_be32(f) != phys_ram_size)
644 return 101;
646 do {
647 addr = qemu_get_be32(f);
648 if (addr == 1)
649 break;
650 ret = migrate_incoming_page(f, addr);
651 if (ret)
652 return ret;
653 } while (1);
656 qemu_aio_flush();
657 vm_stop(0);
658 ret = qemu_live_loadvm_state(f);
659 #ifdef MIGRATION_VERIFY
660 if (ret==0) ret=load_verify_memory(f, NULL, 1);
661 #endif /* MIGRATION_VERIFY */
662 qemu_fclose(f);
664 return ret;
667 static int migrate_incoming_tcp(const char *host)
669 struct sockaddr_in addr;
670 socklen_t addrlen = sizeof(addr);
671 int fd, sfd;
672 ssize_t len;
673 uint8_t status = 0;
674 int reuse = 1;
675 int rc;
677 addr.sin_family = AF_INET;
678 if (parse_host_port(&addr, host) == -1) {
679 fprintf(stderr, "parse_host_port() failed for %s\n", host);
680 rc = 201;
681 goto error;
684 fd = socket(PF_INET, SOCK_STREAM, 0);
685 if (fd == -1) {
686 perror("socket failed");
687 rc = 202;
688 goto error;
691 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
692 perror("setsockopt() failed");
693 rc = 203;
694 goto error_socket;
697 if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
698 perror("bind() failed");
699 rc = 204;
700 goto error_socket;
703 if (listen(fd, 1) == -1) {
704 perror("listen() failed");
705 rc = 205;
706 goto error_socket;
709 again:
710 sfd = accept(fd, (struct sockaddr *)&addr, &addrlen);
711 if (sfd == -1) {
712 if (errno == EINTR)
713 goto again;
714 perror("accept() failed");
715 rc = 206;
716 goto error_socket;
719 rc = migrate_incoming_fd(sfd);
720 if (rc != 0) {
721 rc = 207;
722 fprintf(stderr, "migrate_incoming_fd failed (rc=%d)\n", rc);
723 goto error_accept;
726 send_ack:
727 len = write(sfd, &status, 1);
728 if (len == -1 && errno == EAGAIN)
729 goto send_ack;
730 if (len != 1) {
731 rc = 208;
732 goto error_accept;
735 rc = wait_for_message("WAIT FOR GO", sfd, wait_for_message_timeout);
736 if (rc) {
737 exit(200+rc);
740 wait_for_go:
741 len = read(sfd, &status, 1);
742 if (len == -1 && errno == EAGAIN)
743 goto wait_for_go;
744 if (len != 1)
745 rc = 209;
747 error_accept:
748 close(sfd);
749 error_socket:
750 close(fd);
751 error:
752 return rc;
755 int migrate_incoming(const char *device)
757 const char *ptr;
758 int ret = 0;
760 if (strcmp(device, "stdio") == 0)
761 ret = migrate_incoming_fd(STDIN_FILENO);
762 else if (strstart(device, "tcp://", &ptr)) {
763 char *host, *end;
764 host = strdup(ptr);
765 end = strchr(host, '/');
766 if (end) *end = 0;
767 ret = migrate_incoming_tcp(host);
768 qemu_free(host);
769 } else {
770 errno = EINVAL;
771 ret = -1;
774 return ret;
777 /* Migration monitor command */
779 /* TODO:
780 1) audit all error paths
783 void do_migrate(int detach, const char *uri)
785 const char *ptr;
787 if (strstart(uri, "exec:", &ptr)) {
788 char *command = urldecode(ptr);
789 migration_init_exec(detach, command);
790 free(command);
791 } else if (strstart(uri, "ssh://", &ptr)) {
792 char *host, *end;
794 host = strdup(ptr);
795 end = strchr(host, '/');
796 if (end) *end = 0;
797 migration_init_ssh(detach, host);
798 qemu_free(host);
799 } else if (strstart(uri, "tcp://", &ptr)) {
800 char *host, *end;
802 host = strdup(ptr);
803 end = strchr(host, '/');
804 if (end) *end = 0;
806 if (migration_init_tcp(detach, host) == NULL)
807 term_printf("migration failed (migration_init_tcp for %s failed)\n", host);
808 free(host);
809 } else {
810 term_printf("Unknown migration protocol '%s'\n", uri);
811 return;
815 void do_migrate_set_speed(const char *value)
817 double d;
818 char *ptr;
820 d = strtod(value, &ptr);
821 switch (*ptr) {
822 case 'G': case 'g':
823 d *= 1024;
824 case 'M': case 'm':
825 d *= 1024;
826 case 'K': case 'k':
827 d *= 1024;
828 default:
829 break;
832 max_throttle = (uint32_t)d;
835 void do_info_migration(void)
837 MigrationState *s = current_migration;
839 if (s) {
840 term_printf("Migration active\n");
841 if (s->bps < (1 << 20))
842 term_printf("Transfer rate %3.1f kb/s\n",
843 (double)s->bps / 1024);
844 else
845 term_printf("Transfer rate %3.1f mb/s\n",
846 (double)s->bps / (1024 * 1024));
847 term_printf("Iteration %d\n", s->iteration);
848 term_printf("Transferred %d/%d pages\n", s->updated_pages, phys_ram_size >> TARGET_PAGE_BITS);
849 if (s->iteration)
850 term_printf("Last iteration found %d dirty pages\n", s->last_updated_pages);
851 } else
852 term_printf("Migration inactive\n");
854 term_printf("Maximum migration speed is ");
855 if (max_throttle < (1 << 20))
856 term_printf("%3.1f kb/s\n", (double)max_throttle / 1024);
857 else
858 term_printf("%3.1f mb/s\n", (double)max_throttle / (1024 * 1024));
861 void do_migrate_cancel(void)
863 MigrationState *s = current_migration;
865 if (s)
866 *s->has_error = 20;
871 #ifdef MIGRATION_VERIFY
872 unsigned int calc_page_checksum(target_ulong addr)
874 unsigned int sum=0;
875 unsigned int *p = (unsigned int *)(phys_ram_base + addr);
876 unsigned int *q = p + (TARGET_PAGE_SIZE / sizeof(unsigned int));
878 for ( /*initialized already */ ; p<q ; p++)
879 sum += *p;
880 return sum;
884 static int save_verify_memory(QEMUFile *f, void *opaque)
886 unsigned int addr;
887 unsigned int sum;
889 for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) {
890 #ifdef USE_KVM
891 if (kvm_allowed && (addr>=0xa0000) && (addr<0xc0000)) /* do not access video-addresses */
892 continue;
893 #endif
894 sum = calc_page_checksum(addr);
895 qemu_put_be32(f, addr);
896 qemu_put_be32(f, sum);
898 return 0;
901 static int load_verify_memory(QEMUFile *f, void *opaque, int version_id)
903 unsigned int addr, raddr;
904 unsigned int sum, rsum;
905 int num_errors = 0;
907 for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) {
908 #ifdef USE_KVM
909 if (kvm_allowed && (addr>=0xa0000) && (addr<0xc0000)) /* do not access video-addresses */
910 continue;
911 #endif
912 sum = calc_page_checksum(addr);
913 raddr = qemu_get_be32(f);
914 rsum = qemu_get_be32(f);
915 if ((raddr != addr) || (rsum != sum)) {
916 term_printf("checksum mismatch: src:0x%x 0x%x , dst:0x%x 0x%x\n",
917 raddr, rsum, addr, sum);
918 num_errors++;
921 printf("memory_verify: num_errors=%d\n", num_errors);
922 term_printf("memory_verify: num_errors=%d\n", num_errors);
923 return 0/* num_errors */;
925 #endif /* MIGRATION_VERIFY */