|
|
1.1 root 1: #include <signal.h>
2: #include "xen_backend.h"
3: #include "xen_domainbuild.h"
4: #include "sysemu.h"
5: #include "qemu-timer.h"
1.1.1.2 ! root 6: #include "qemu-log.h"
1.1 root 7:
8: #include <xenguest.h>
9:
10: static int xenstore_domain_mkdir(char *path)
11: {
12: struct xs_permissions perms_ro[] = {{
13: .id = 0, /* set owner: dom0 */
14: },{
15: .id = xen_domid,
16: .perms = XS_PERM_READ,
17: }};
18: struct xs_permissions perms_rw[] = {{
19: .id = 0, /* set owner: dom0 */
20: },{
21: .id = xen_domid,
22: .perms = XS_PERM_READ | XS_PERM_WRITE,
23: }};
24: const char *writable[] = { "device", "control", "error", NULL };
25: char subpath[256];
26: int i;
27:
28: if (!xs_mkdir(xenstore, 0, path)) {
29: fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, path);
30: return -1;
31: }
32: if (!xs_set_permissions(xenstore, 0, path, perms_ro, 2)) {
33: fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
34: return -1;
35: }
36:
37: for (i = 0; writable[i]; i++) {
38: snprintf(subpath, sizeof(subpath), "%s/%s", path, writable[i]);
39: if (!xs_mkdir(xenstore, 0, subpath)) {
40: fprintf(stderr, "%s: xs_mkdir %s: failed\n", __FUNCTION__, subpath);
41: return -1;
42: }
43: if (!xs_set_permissions(xenstore, 0, subpath, perms_rw, 2)) {
44: fprintf(stderr, "%s: xs_set_permissions failed\n", __FUNCTION__);
45: return -1;
46: }
47: }
48: return 0;
49: }
50:
51: int xenstore_domain_init1(const char *kernel, const char *ramdisk,
52: const char *cmdline)
53: {
54: char *dom, uuid_string[42], vm[256], path[256];
55: int i;
56:
57: snprintf(uuid_string, sizeof(uuid_string), UUID_FMT,
58: qemu_uuid[0], qemu_uuid[1], qemu_uuid[2], qemu_uuid[3],
59: qemu_uuid[4], qemu_uuid[5], qemu_uuid[6], qemu_uuid[7],
60: qemu_uuid[8], qemu_uuid[9], qemu_uuid[10], qemu_uuid[11],
61: qemu_uuid[12], qemu_uuid[13], qemu_uuid[14], qemu_uuid[15]);
62: dom = xs_get_domain_path(xenstore, xen_domid);
63: snprintf(vm, sizeof(vm), "/vm/%s", uuid_string);
64:
65: xenstore_domain_mkdir(dom);
66:
67: xenstore_write_str(vm, "image/ostype", "linux");
68: if (kernel)
69: xenstore_write_str(vm, "image/kernel", kernel);
70: if (ramdisk)
71: xenstore_write_str(vm, "image/ramdisk", ramdisk);
72: if (cmdline)
73: xenstore_write_str(vm, "image/cmdline", cmdline);
74:
75: /* name + id */
76: xenstore_write_str(vm, "name", qemu_name ? qemu_name : "no-name");
77: xenstore_write_str(vm, "uuid", uuid_string);
78: xenstore_write_str(dom, "name", qemu_name ? qemu_name : "no-name");
79: xenstore_write_int(dom, "domid", xen_domid);
80: xenstore_write_str(dom, "vm", vm);
81:
82: /* memory */
83: xenstore_write_int(dom, "memory/target", ram_size >> 10); // kB
84: xenstore_write_int(vm, "memory", ram_size >> 20); // MB
85: xenstore_write_int(vm, "maxmem", ram_size >> 20); // MB
86:
87: /* cpus */
88: for (i = 0; i < smp_cpus; i++) {
89: snprintf(path, sizeof(path), "cpu/%d/availability",i);
90: xenstore_write_str(dom, path, "online");
91: }
92: xenstore_write_int(vm, "vcpu_avail", smp_cpus);
93: xenstore_write_int(vm, "vcpus", smp_cpus);
94:
95: /* vnc password */
96: xenstore_write_str(vm, "vncpassword", "" /* FIXME */);
97:
98: free(dom);
99: return 0;
100: }
101:
102: int xenstore_domain_init2(int xenstore_port, int xenstore_mfn,
103: int console_port, int console_mfn)
104: {
105: char *dom;
106:
107: dom = xs_get_domain_path(xenstore, xen_domid);
108:
109: /* signal new domain */
110: xs_introduce_domain(xenstore,
111: xen_domid,
112: xenstore_mfn,
113: xenstore_port);
114:
115: /* xenstore */
116: xenstore_write_int(dom, "store/ring-ref", xenstore_mfn);
117: xenstore_write_int(dom, "store/port", xenstore_port);
118:
119: /* console */
120: xenstore_write_str(dom, "console/type", "ioemu");
121: xenstore_write_int(dom, "console/limit", 128 * 1024);
122: xenstore_write_int(dom, "console/ring-ref", console_mfn);
123: xenstore_write_int(dom, "console/port", console_port);
124: xen_config_dev_console(0);
125:
126: free(dom);
127: return 0;
128: }
129:
130: /* ------------------------------------------------------------- */
131:
132: static QEMUTimer *xen_poll;
133:
134: /* check domain state once per second */
135: static void xen_domain_poll(void *opaque)
136: {
137: struct xc_dominfo info;
138: int rc;
139:
140: rc = xc_domain_getinfo(xen_xc, xen_domid, 1, &info);
141: if ((rc != 1) || (info.domid != xen_domid)) {
142: qemu_log("xen: domain %d is gone\n", xen_domid);
143: goto quit;
144: }
145: if (info.dying) {
146: qemu_log("xen: domain %d is dying (%s%s)\n", xen_domid,
147: info.crashed ? "crashed" : "",
148: info.shutdown ? "shutdown" : "");
149: goto quit;
150: }
151:
152: qemu_mod_timer(xen_poll, qemu_get_clock(rt_clock) + 1000);
153: return;
154:
155: quit:
156: qemu_system_shutdown_request();
157: return;
158: }
159:
1.1.1.2 ! root 160: static int xen_domain_watcher(void)
1.1 root 161: {
162: int qemu_running = 1;
163: int fd[2], i, n, rc;
164: char byte;
165:
1.1.1.2 ! root 166: if (pipe(fd) != 0) {
! 167: qemu_log("%s: Huh? pipe error: %s\n", __FUNCTION__, strerror(errno));
! 168: return -1;
! 169: }
1.1 root 170: if (fork() != 0)
1.1.1.2 ! root 171: return 0; /* not child */
1.1 root 172:
173: /* close all file handles, except stdio/out/err,
174: * our watch pipe and the xen interface handle */
175: n = getdtablesize();
176: for (i = 3; i < n; i++) {
177: if (i == fd[0])
178: continue;
179: if (i == xen_xc)
180: continue;
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:
193: if (errno == EINTR)
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 */
215: static void xen_domain_cleanup(void)
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);
244: atexit(xen_domain_cleanup);
1.1.1.2 ! root 245: if (xen_domain_watcher() == -1) {
! 246: goto err;
! 247: }
1.1 root 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:
294: xen_poll = qemu_new_timer(rt_clock, xen_domain_poll, NULL);
295: qemu_mod_timer(xen_poll, qemu_get_clock(rt_clock) + 1000);
296: return 0;
297:
298: err:
299: return -1;
300: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.