ia64/xen-unstable

view tools/xcutils/xc_save.c @ 15841:c5f735271e22

[IA64] Foreign p2m: Fix vti domain builder.

It should set arch_domain::convmem_end.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author Alex Williamson <alex.williamson@hp.com>
date Thu Sep 06 13:48:43 2007 -0600 (2007-09-06)
parents 07655ed2fe58
children 3633eae53572
line source
1 /*
2 * This file is subject to the terms and conditions of the GNU General
3 * Public License. See the file "COPYING" in the main directory of
4 * this archive for more details.
5 *
6 * Copyright (C) 2005 by Christian Limpach
7 *
8 */
10 #include <err.h>
11 #include <stdlib.h>
12 #include <stdint.h>
13 #include <string.h>
14 #include <stdio.h>
15 #include <sys/ipc.h>
16 #include <sys/shm.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <fcntl.h>
21 #include <xs.h>
22 #include <xenctrl.h>
23 #include <xenguest.h>
25 /**
26 * Issue a suspend request through stdout, and receive the acknowledgement
27 * from stdin. This is handled by XendCheckpoint in the Python layer.
28 */
29 static int suspend(int domid)
30 {
31 char ans[30];
33 printf("suspend\n");
34 fflush(stdout);
36 return (fgets(ans, sizeof(ans), stdin) != NULL &&
37 !strncmp(ans, "done\n", 5));
38 }
40 /* For HVM guests, there are two sources of dirty pages: the Xen shadow
41 * log-dirty bitmap, which we get with a hypercall, and qemu's version.
42 * The protocol for getting page-dirtying data from qemu uses a
43 * double-buffered shared memory interface directly between xc_save and
44 * qemu-dm.
45 *
46 * xc_save calculates the size of the bitmaps and notifies qemu-dm
47 * through the store that it wants to share the bitmaps. qemu-dm then
48 * starts filling in the 'active' buffer.
49 *
50 * To change the buffers over, xc_save writes the other buffer number to
51 * the store and waits for qemu to acknowledge that it is now writing to
52 * the new active buffer. xc_save can then process and clear the old
53 * active buffer. */
55 static char *qemu_active_path;
56 static char *qemu_next_active_path;
57 static int qemu_shmid = -1;
58 static struct xs_handle *xs;
61 /* Mark the shared-memory segment for destruction */
62 static void qemu_destroy_buffer(void)
63 {
64 if (qemu_shmid != -1)
65 shmctl(qemu_shmid, IPC_RMID, NULL);
66 qemu_shmid = -1;
67 }
69 /* Get qemu to change buffers. */
70 static void qemu_flip_buffer(int domid, int next_active)
71 {
72 char digit = '0' + next_active;
73 unsigned int len;
74 char *active_str, **watch;
75 struct timeval tv;
76 fd_set fdset;
78 /* Tell qemu that we want it to start writing log-dirty bits to the
79 * other buffer */
80 if (!xs_write(xs, XBT_NULL, qemu_next_active_path, &digit, 1)) {
81 errx(1, "can't write next-active to store path (%s)\n",
82 qemu_next_active_path);
83 exit(1);
84 }
86 /* Wait a while for qemu to signal that it has switched to the new
87 * active buffer */
88 read_again:
89 tv.tv_sec = 5;
90 tv.tv_usec = 0;
91 FD_ZERO(&fdset);
92 FD_SET(xs_fileno(xs), &fdset);
93 if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1) {
94 errx(1, "timed out waiting for qemu to switch buffers\n");
95 exit(1);
96 }
97 watch = xs_read_watch(xs, &len);
98 free(watch);
100 active_str = xs_read(xs, XBT_NULL, qemu_active_path, &len);
101 if (active_str == NULL || active_str[0] - '0' != next_active)
102 /* Watch fired but value is not yet right */
103 goto read_again;
104 }
106 static void * init_qemu_maps(int domid, unsigned int bitmap_size)
107 {
108 key_t key;
109 char key_ascii[17] = {0,};
110 void *seg;
111 char *path, *p;
113 /* Make a shared-memory segment */
114 do {
115 key = rand(); /* No security, just a sequence of numbers */
116 qemu_shmid = shmget(key, 2 * bitmap_size,
117 IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
118 if (qemu_shmid == -1 && errno != EEXIST)
119 errx(1, "can't get shmem to talk to qemu-dm");
120 } while (qemu_shmid == -1);
122 /* Remember to tidy up after ourselves */
123 atexit(qemu_destroy_buffer);
125 /* Map it into our address space */
126 seg = shmat(qemu_shmid, NULL, 0);
127 if (seg == (void *) -1)
128 errx(1, "can't map shmem to talk to qemu-dm");
129 memset(seg, 0, 2 * bitmap_size);
131 /* Write the size of it into the first 32 bits */
132 *(uint32_t *)seg = bitmap_size;
134 /* Tell qemu about it */
135 if ((xs = xs_daemon_open()) == NULL)
136 errx(1, "Couldn't contact xenstore");
137 if (!(path = strdup("/local/domain/0/device-model/")))
138 errx(1, "can't get domain path in store");
139 if (!(path = realloc(path, strlen(path)
140 + 10
141 + strlen("/logdirty/next-active") + 1)))
142 errx(1, "no memory for constructing xenstore path");
143 snprintf(path + strlen(path), 11, "%i", domid);
144 strcat(path, "/logdirty/");
145 p = path + strlen(path);
147 strcpy(p, "key");
148 snprintf(key_ascii, 17, "%16.16llx", (unsigned long long) key);
149 if (!xs_write(xs, XBT_NULL, path, key_ascii, 16))
150 errx(1, "can't write key (%s) to store path (%s)\n", key_ascii, path);
152 /* Watch for qemu's indication of the active buffer, and request it
153 * to start writing to buffer 0 */
154 strcpy(p, "active");
155 if (!xs_watch(xs, path, "qemu-active-buffer"))
156 errx(1, "can't set watch in store (%s)\n", path);
157 if (!(qemu_active_path = strdup(path)))
158 errx(1, "no memory for copying xenstore path");
160 strcpy(p, "next-active");
161 if (!(qemu_next_active_path = strdup(path)))
162 errx(1, "no memory for copying xenstore path");
164 qemu_flip_buffer(domid, 0);
166 free(path);
167 return seg;
168 }
171 int
172 main(int argc, char **argv)
173 {
174 unsigned int xc_fd, io_fd, domid, maxit, max_f, flags;
175 int ret;
177 if (argc != 6)
178 errx(1, "usage: %s iofd domid maxit maxf flags", argv[0]);
180 xc_fd = xc_interface_open();
181 if (xc_fd < 0)
182 errx(1, "failed to open control interface");
184 io_fd = atoi(argv[1]);
185 domid = atoi(argv[2]);
186 maxit = atoi(argv[3]);
187 max_f = atoi(argv[4]);
188 flags = atoi(argv[5]);
190 ret = xc_domain_save(xc_fd, io_fd, domid, maxit, max_f, flags,
191 &suspend, !!(flags & XCFLAGS_HVM),
192 &init_qemu_maps, &qemu_flip_buffer);
194 xc_interface_close(xc_fd);
196 return ret;
197 }