root / hw / xen_domainbuild.c @ 8294a64d
History | View | Annotate | Download (8.5 kB)
1 | 9306acb5 | aliguori | #include <signal.h> |
---|---|---|---|
2 | 9306acb5 | aliguori | #include "xen_backend.h" |
3 | 9306acb5 | aliguori | #include "xen_domainbuild.h" |
4 | 9306acb5 | aliguori | #include "qemu-timer.h" |
5 | a88790a1 | Paolo Bonzini | #include "qemu-log.h" |
6 | 9306acb5 | aliguori | |
7 | 9306acb5 | aliguori | #include <xenguest.h> |
8 | 9306acb5 | aliguori | |
9 | 9306acb5 | aliguori | static int xenstore_domain_mkdir(char *path) |
10 | 9306acb5 | aliguori | { |
11 | 9306acb5 | aliguori | struct xs_permissions perms_ro[] = {{
|
12 | 9306acb5 | aliguori | .id = 0, /* set owner: dom0 */ |
13 | 9306acb5 | aliguori | },{ |
14 | 9306acb5 | aliguori | .id = xen_domid, |
15 | 9306acb5 | aliguori | .perms = XS_PERM_READ, |
16 | 9306acb5 | aliguori | }}; |
17 | 9306acb5 | aliguori | struct xs_permissions perms_rw[] = {{
|
18 | 9306acb5 | aliguori | .id = 0, /* set owner: dom0 */ |
19 | 9306acb5 | aliguori | },{ |
20 | 9306acb5 | aliguori | .id = xen_domid, |
21 | 9306acb5 | aliguori | .perms = XS_PERM_READ | XS_PERM_WRITE, |
22 | 9306acb5 | aliguori | }}; |
23 | 9306acb5 | aliguori | const char *writable[] = { "device", "control", "error", NULL }; |
24 | 9306acb5 | aliguori | char subpath[256]; |
25 | 9306acb5 | aliguori | int i;
|
26 | 9306acb5 | aliguori | |
27 | 9306acb5 | aliguori | if (!xs_mkdir(xenstore, 0, path)) { |
28 | 9306acb5 | aliguori | fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
|
29 | 9306acb5 | aliguori | return -1; |
30 | 9306acb5 | aliguori | } |
31 | 9306acb5 | aliguori | if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) { |
32 | 9306acb5 | aliguori | fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
|
33 | 9306acb5 | aliguori | return -1; |
34 | 9306acb5 | aliguori | } |
35 | 9306acb5 | aliguori | |
36 | 9306acb5 | aliguori | for (i = 0; writable[i]; i++) { |
37 | 9306acb5 | aliguori | snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]); |
38 | 9306acb5 | aliguori | if (!xs_mkdir(xenstore, 0, subpath)) { |
39 | 9306acb5 | aliguori | fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
|
40 | 9306acb5 | aliguori | return -1; |
41 | 9306acb5 | aliguori | } |
42 | 9306acb5 | aliguori | if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) { |
43 | 9306acb5 | aliguori | fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
|
44 | 9306acb5 | aliguori | return -1; |
45 | 9306acb5 | aliguori | } |
46 | 9306acb5 | aliguori | } |
47 | 9306acb5 | aliguori | return 0; |
48 | 9306acb5 | aliguori | } |
49 | 9306acb5 | aliguori | |
50 | 9306acb5 | aliguori | int xenstore_domain_init1(const char *kernel, const char *ramdisk, |
51 | 9306acb5 | aliguori | const char *cmdline) |
52 | 9306acb5 | aliguori | { |
53 | 9306acb5 | aliguori | char *dom, uuid_string[42], vm[256], path[256]; |
54 | 9306acb5 | aliguori | int i;
|
55 | 9306acb5 | aliguori | |
56 | 9306acb5 | aliguori | snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
|
57 | 9306acb5 | aliguori | qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3], |
58 | 9306acb5 | aliguori | qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7], |
59 | 9306acb5 | aliguori | qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11], |
60 | 9306acb5 | aliguori | qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]); |
61 | 9306acb5 | aliguori | dom = xs_get_domain_path(xenstore, xen_domid); |
62 | 9306acb5 | aliguori | snprintf(vm, sizeof(vm), "/vm/%s", uuid_string); |
63 | 9306acb5 | aliguori | |
64 | 9306acb5 | aliguori | xenstore_domain_mkdir(dom); |
65 | 9306acb5 | aliguori | |
66 | 9306acb5 | aliguori | xenstore_write_str(vm, "image/ostype", "linux"); |
67 | 9306acb5 | aliguori | if (kernel)
|
68 | 9306acb5 | aliguori | xenstore_write_str(vm, "image/kernel", kernel);
|
69 | 9306acb5 | aliguori | if (ramdisk)
|
70 | 9306acb5 | aliguori | xenstore_write_str(vm, "image/ramdisk", ramdisk);
|
71 | 9306acb5 | aliguori | if (cmdline)
|
72 | 9306acb5 | aliguori | xenstore_write_str(vm, "image/cmdline", cmdline);
|
73 | 9306acb5 | aliguori | |
74 | 9306acb5 | aliguori | /* name + id */
|
75 | 9306acb5 | aliguori | xenstore_write_str(vm, "name", qemu_name ? qemu_name : "no-name"); |
76 | 9306acb5 | aliguori | xenstore_write_str(vm, "uuid", uuid_string);
|
77 | 9306acb5 | aliguori | xenstore_write_str(dom, "name", qemu_name ? qemu_name : "no-name"); |
78 | 9306acb5 | aliguori | xenstore_write_int(dom, "domid", xen_domid);
|
79 | 9306acb5 | aliguori | xenstore_write_str(dom, "vm", vm);
|
80 | 9306acb5 | aliguori | |
81 | 9306acb5 | aliguori | /* memory */
|
82 | 9306acb5 | aliguori | xenstore_write_int(dom, "memory/target", ram_size >> 10); // kB |
83 | 9306acb5 | aliguori | xenstore_write_int(vm, "memory", ram_size >> 20); // MB |
84 | 9306acb5 | aliguori | xenstore_write_int(vm, "maxmem", ram_size >> 20); // MB |
85 | 9306acb5 | aliguori | |
86 | 9306acb5 | aliguori | /* cpus */
|
87 | 9306acb5 | aliguori | for (i = 0; i < smp_cpus; i++) { |
88 | 9306acb5 | aliguori | snprintf(path, sizeof(path), "cpu/%d/availability",i); |
89 | 9306acb5 | aliguori | xenstore_write_str(dom, path, "online");
|
90 | 9306acb5 | aliguori | } |
91 | 9306acb5 | aliguori | xenstore_write_int(vm, "vcpu_avail", smp_cpus);
|
92 | 9306acb5 | aliguori | xenstore_write_int(vm, "vcpus", smp_cpus);
|
93 | 9306acb5 | aliguori | |
94 | 9306acb5 | aliguori | /* vnc password */
|
95 | 9306acb5 | aliguori | xenstore_write_str(vm, "vncpassword", "" /* FIXME */); |
96 | 9306acb5 | aliguori | |
97 | 9306acb5 | aliguori | free(dom); |
98 | 9306acb5 | aliguori | return 0; |
99 | 9306acb5 | aliguori | } |
100 | 9306acb5 | aliguori | |
101 | 9306acb5 | aliguori | int xenstore_domain_init2(int xenstore_port, int xenstore_mfn, |
102 | 9306acb5 | aliguori | int console_port, int console_mfn) |
103 | 9306acb5 | aliguori | { |
104 | 9306acb5 | aliguori | char *dom;
|
105 | 9306acb5 | aliguori | |
106 | 9306acb5 | aliguori | dom = xs_get_domain_path(xenstore, xen_domid); |
107 | 9306acb5 | aliguori | |
108 | 9306acb5 | aliguori | /* signal new domain */
|
109 | 9306acb5 | aliguori | xs_introduce_domain(xenstore, |
110 | 9306acb5 | aliguori | xen_domid, |
111 | 9306acb5 | aliguori | xenstore_mfn, |
112 | 9306acb5 | aliguori | xenstore_port); |
113 | 9306acb5 | aliguori | |
114 | 9306acb5 | aliguori | /* xenstore */
|
115 | 9306acb5 | aliguori | xenstore_write_int(dom, "store/ring-ref", xenstore_mfn);
|
116 | 9306acb5 | aliguori | xenstore_write_int(dom, "store/port", xenstore_port);
|
117 | 9306acb5 | aliguori | |
118 | 9306acb5 | aliguori | /* console */
|
119 | 9306acb5 | aliguori | xenstore_write_str(dom, "console/type", "ioemu"); |
120 | 9306acb5 | aliguori | xenstore_write_int(dom, "console/limit", 128 * 1024); |
121 | 9306acb5 | aliguori | xenstore_write_int(dom, "console/ring-ref", console_mfn);
|
122 | 9306acb5 | aliguori | xenstore_write_int(dom, "console/port", console_port);
|
123 | 9306acb5 | aliguori | xen_config_dev_console(0);
|
124 | 9306acb5 | aliguori | |
125 | 9306acb5 | aliguori | free(dom); |
126 | 9306acb5 | aliguori | return 0; |
127 | 9306acb5 | aliguori | } |
128 | 9306acb5 | aliguori | |
129 | 9306acb5 | aliguori | /* ------------------------------------------------------------- */
|
130 | 9306acb5 | aliguori | |
131 | 9306acb5 | aliguori | static QEMUTimer *xen_poll;
|
132 | 9306acb5 | aliguori | |
133 | 9306acb5 | aliguori | /* check domain state once per second */
|
134 | 9306acb5 | aliguori | static void xen_domain_poll(void *opaque) |
135 | 9306acb5 | aliguori | { |
136 | 9306acb5 | aliguori | struct xc_dominfo info;
|
137 | 9306acb5 | aliguori | int rc;
|
138 | 9306acb5 | aliguori | |
139 | 9306acb5 | aliguori | rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
|
140 | fc1f79f7 | blueswir1 | if ((rc != 1) || (info.domid != xen_domid)) { |
141 | 9306acb5 | aliguori | qemu_log("xen: domain %d is gone\n", xen_domid);
|
142 | 9306acb5 | aliguori | goto quit;
|
143 | 9306acb5 | aliguori | } |
144 | 9306acb5 | aliguori | if (info.dying) {
|
145 | 9306acb5 | aliguori | qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid,
|
146 | 9306acb5 | aliguori | info.crashed ? "crashed" : "", |
147 | 9306acb5 | aliguori | info.shutdown ? "shutdown" : ""); |
148 | 9306acb5 | aliguori | goto quit;
|
149 | 9306acb5 | aliguori | } |
150 | 9306acb5 | aliguori | |
151 | 7bd427d8 | Paolo Bonzini | qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
|
152 | 9306acb5 | aliguori | return;
|
153 | 9306acb5 | aliguori | |
154 | 9306acb5 | aliguori | quit:
|
155 | 9306acb5 | aliguori | qemu_system_shutdown_request(); |
156 | 9306acb5 | aliguori | return;
|
157 | 9306acb5 | aliguori | } |
158 | 9306acb5 | aliguori | |
159 | acdc3f0c | Juan Quintela | static int xen_domain_watcher(void) |
160 | 9306acb5 | aliguori | { |
161 | 9306acb5 | aliguori | int qemu_running = 1; |
162 | 9306acb5 | aliguori | int fd[2], i, n, rc; |
163 | 9306acb5 | aliguori | char byte;
|
164 | 9306acb5 | aliguori | |
165 | acdc3f0c | Juan Quintela | if (pipe(fd) != 0) { |
166 | acdc3f0c | Juan Quintela | qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno));
|
167 | acdc3f0c | Juan Quintela | return -1; |
168 | acdc3f0c | Juan Quintela | } |
169 | 9306acb5 | aliguori | if (fork() != 0) |
170 | acdc3f0c | Juan Quintela | return 0; /* not child */ |
171 | 9306acb5 | aliguori | |
172 | 9306acb5 | aliguori | /* close all file handles, except stdio/out/err,
|
173 | 9306acb5 | aliguori | * our watch pipe and the xen interface handle */
|
174 | 9306acb5 | aliguori | n = getdtablesize(); |
175 | 9306acb5 | aliguori | for (i = 3; i < n; i++) { |
176 | 9306acb5 | aliguori | if (i == fd[0]) |
177 | 9306acb5 | aliguori | continue;
|
178 | d5b93ddf | Anthony PERARD | if (i == xc_fd(xen_xc)) {
|
179 | 9306acb5 | aliguori | continue;
|
180 | d5b93ddf | Anthony PERARD | } |
181 | 9306acb5 | aliguori | close(i); |
182 | 9306acb5 | aliguori | } |
183 | 9306acb5 | aliguori | |
184 | 9306acb5 | aliguori | /* ignore term signals */
|
185 | 9306acb5 | aliguori | signal(SIGINT, SIG_IGN); |
186 | 9306acb5 | aliguori | signal(SIGTERM, SIG_IGN); |
187 | 9306acb5 | aliguori | |
188 | 9306acb5 | aliguori | /* wait for qemu exiting */
|
189 | 9306acb5 | aliguori | while (qemu_running) {
|
190 | 9306acb5 | aliguori | rc = read(fd[0], &byte, 1); |
191 | 9306acb5 | aliguori | switch (rc) {
|
192 | 9306acb5 | aliguori | case -1: |
193 | fc1f79f7 | blueswir1 | if (errno == EINTR)
|
194 | 9306acb5 | aliguori | continue;
|
195 | 9306acb5 | aliguori | qemu_log("%s: Huh? read error: %s\n", __FUNCTION__, strerror(errno));
|
196 | 9306acb5 | aliguori | qemu_running = 0;
|
197 | 9306acb5 | aliguori | break;
|
198 | 9306acb5 | aliguori | case 0: |
199 | 9306acb5 | aliguori | /* EOF -> qemu exited */
|
200 | 9306acb5 | aliguori | qemu_running = 0;
|
201 | 9306acb5 | aliguori | break;
|
202 | 9306acb5 | aliguori | default:
|
203 | 9306acb5 | aliguori | qemu_log("%s: Huh? data on the watch pipe?\n", __FUNCTION__);
|
204 | 9306acb5 | aliguori | break;
|
205 | 9306acb5 | aliguori | } |
206 | 9306acb5 | aliguori | } |
207 | 9306acb5 | aliguori | |
208 | 9306acb5 | aliguori | /* cleanup */
|
209 | 9306acb5 | aliguori | qemu_log("%s: destroy domain %d\n", __FUNCTION__, xen_domid);
|
210 | 9306acb5 | aliguori | xc_domain_destroy(xen_xc, xen_domid); |
211 | 9306acb5 | aliguori | _exit(0);
|
212 | 9306acb5 | aliguori | } |
213 | 9306acb5 | aliguori | |
214 | 9306acb5 | aliguori | /* normal cleanup */
|
215 | 28695489 | Anthony Liguori | static void xen_domain_cleanup(void) |
216 | 9306acb5 | aliguori | { |
217 | 9306acb5 | aliguori | char *dom;
|
218 | 9306acb5 | aliguori | |
219 | 9306acb5 | aliguori | dom = xs_get_domain_path(xenstore, xen_domid); |
220 | 9306acb5 | aliguori | if (dom) {
|
221 | 9306acb5 | aliguori | xs_rm(xenstore, 0, dom);
|
222 | 9306acb5 | aliguori | free(dom); |
223 | 9306acb5 | aliguori | } |
224 | 9306acb5 | aliguori | xs_release_domain(xenstore, xen_domid); |
225 | 9306acb5 | aliguori | } |
226 | 9306acb5 | aliguori | |
227 | 9306acb5 | aliguori | int xen_domain_build_pv(const char *kernel, const char *ramdisk, |
228 | 9306acb5 | aliguori | const char *cmdline) |
229 | 9306acb5 | aliguori | { |
230 | 9306acb5 | aliguori | uint32_t ssidref = 0;
|
231 | 9306acb5 | aliguori | uint32_t flags = 0;
|
232 | 9306acb5 | aliguori | xen_domain_handle_t uuid; |
233 | 9306acb5 | aliguori | unsigned int xenstore_port = 0, console_port = 0; |
234 | 9306acb5 | aliguori | unsigned long xenstore_mfn = 0, console_mfn = 0; |
235 | 9306acb5 | aliguori | int rc;
|
236 | 9306acb5 | aliguori | |
237 | 9306acb5 | aliguori | memcpy(uuid, qemu_uuid, sizeof(uuid));
|
238 | 9306acb5 | aliguori | rc = xc_domain_create(xen_xc, ssidref, uuid, flags, &xen_domid); |
239 | 9306acb5 | aliguori | if (rc < 0) { |
240 | 9306acb5 | aliguori | fprintf(stderr, "xen: xc_domain_create() failed\n");
|
241 | 9306acb5 | aliguori | goto err;
|
242 | 9306acb5 | aliguori | } |
243 | 9306acb5 | aliguori | qemu_log("xen: created domain %d\n", xen_domid);
|
244 | 28695489 | Anthony Liguori | atexit(xen_domain_cleanup); |
245 | acdc3f0c | Juan Quintela | if (xen_domain_watcher() == -1) { |
246 | acdc3f0c | Juan Quintela | goto err;
|
247 | acdc3f0c | Juan Quintela | } |
248 | 9306acb5 | aliguori | |
249 | 9306acb5 | aliguori | xenstore_domain_init1(kernel, ramdisk, cmdline); |
250 | 9306acb5 | aliguori | |
251 | 9306acb5 | aliguori | rc = xc_domain_max_vcpus(xen_xc, xen_domid, smp_cpus); |
252 | 9306acb5 | aliguori | if (rc < 0) { |
253 | 9306acb5 | aliguori | fprintf(stderr, "xen: xc_domain_max_vcpus() failed\n");
|
254 | 9306acb5 | aliguori | goto err;
|
255 | 9306acb5 | aliguori | } |
256 | 9306acb5 | aliguori | |
257 | 9306acb5 | aliguori | #if 0
|
258 | 9306acb5 | aliguori | rc = xc_domain_setcpuweight(xen_xc, xen_domid, 256);
|
259 | 9306acb5 | aliguori | if (rc < 0) {
|
260 | 9306acb5 | aliguori | fprintf(stderr, "xen: xc_domain_setcpuweight() failed\n");
|
261 | 9306acb5 | aliguori | goto err;
|
262 | 9306acb5 | aliguori | }
|
263 | 9306acb5 | aliguori | #endif
|
264 | 9306acb5 | aliguori | |
265 | 9306acb5 | aliguori | rc = xc_domain_setmaxmem(xen_xc, xen_domid, ram_size >> 10);
|
266 | 9306acb5 | aliguori | if (rc < 0) { |
267 | 9306acb5 | aliguori | fprintf(stderr, "xen: xc_domain_setmaxmem() failed\n");
|
268 | 9306acb5 | aliguori | goto err;
|
269 | 9306acb5 | aliguori | } |
270 | 9306acb5 | aliguori | |
271 | 9306acb5 | aliguori | xenstore_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
|
272 | 9306acb5 | aliguori | console_port = xc_evtchn_alloc_unbound(xen_xc, xen_domid, 0);
|
273 | 9306acb5 | aliguori | |
274 | 9306acb5 | aliguori | rc = xc_linux_build(xen_xc, xen_domid, ram_size >> 20,
|
275 | 9306acb5 | aliguori | kernel, ramdisk, cmdline, |
276 | 9306acb5 | aliguori | 0, flags,
|
277 | 9306acb5 | aliguori | xenstore_port, &xenstore_mfn, |
278 | 9306acb5 | aliguori | console_port, &console_mfn); |
279 | 9306acb5 | aliguori | if (rc < 0) { |
280 | 9306acb5 | aliguori | fprintf(stderr, "xen: xc_linux_build() failed\n");
|
281 | 9306acb5 | aliguori | goto err;
|
282 | 9306acb5 | aliguori | } |
283 | 9306acb5 | aliguori | |
284 | 9306acb5 | aliguori | xenstore_domain_init2(xenstore_port, xenstore_mfn, |
285 | 9306acb5 | aliguori | console_port, console_mfn); |
286 | 9306acb5 | aliguori | |
287 | 9306acb5 | aliguori | qemu_log("xen: unpausing domain %d\n", xen_domid);
|
288 | 9306acb5 | aliguori | rc = xc_domain_unpause(xen_xc, xen_domid); |
289 | 9306acb5 | aliguori | if (rc < 0) { |
290 | 9306acb5 | aliguori | fprintf(stderr, "xen: xc_domain_unpause() failed\n");
|
291 | 9306acb5 | aliguori | goto err;
|
292 | 9306acb5 | aliguori | } |
293 | 9306acb5 | aliguori | |
294 | 7bd427d8 | Paolo Bonzini | xen_poll = qemu_new_timer_ms(rt_clock, xen_domain_poll, NULL);
|
295 | 7bd427d8 | Paolo Bonzini | qemu_mod_timer(xen_poll, qemu_get_clock_ms(rt_clock) + 1000);
|
296 | 9306acb5 | aliguori | return 0; |
297 | 9306acb5 | aliguori | |
298 | 9306acb5 | aliguori | err:
|
299 | 9306acb5 | aliguori | return -1; |
300 | 9306acb5 | aliguori | } |