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