debuggers.hg

view tools/libxl/libxl.c @ 22165:d6663c62524a

libxl: Ensure all _hidden functions use libxl__ prefix (manual part)

This patch covers the remaining functions identified by:
rgrep _hidden tools/libxl/*.h | grep -v libxl__

sed -i -e 's/XL_LOG/LIBXL__LOG/g' tools/libxl/*.[ch]
sed -i -e 's/xl_log/libxl__log/g' tools/libxl/*.[ch]
sed -i -e 's/\(build_\(pre\|post\|pv\|hvm\)\)/libxl__\1/g' tools/libxl/*.[ch]
sed -i -e 's/is_hvm/libxl__domain_is_hvm/g' tools/libxl/*.[ch]
sed -i -e 's/get_shutdown_reason/libxl__domain_shutdown_reason/g' tools/libxl/*.[ch]
sed -i -e 's/restore_common/libxl__domain_restore_common/g' tools/libxl/*.[ch]
sed -i -e 's/core_suspend/libxl__domain_suspend_common/g' tools/libxl/*.[ch]
sed -i -e 's/save_device_model/libxl__domain_save_device_model/g' tools/libxl/*.[ch]
sed -i -e 's/device_disk_backend_type_of_phystype/libxl__device_disk_backend_type_of_phystype/g' tools/libxl/*.[ch]
sed -i -e 's/\<libxl_blktap_enabled\>/libxl__blktap_enabled/g' tools/libxl/*.[ch]
sed -i -e 's/\<libxl_blktap_devpath\>/libxl__blktap_devpath/g' tools/libxl/*.[ch]

Add _hidden to libxl__blktap_enabled and libxl__blktap_devpath

Inline dominfo_libxl__domain_shutdown_reason(info) into
libxl__domain_shutdown_reason, its only caller.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Ian Campbell <ian.campbell@citrix.com>
date Wed Sep 08 16:46:27 2010 +0100 (2010-09-08)
parents 23112038074f
children 4ed9f9218620
line source
1 /*
2 * Copyright (C) 2009 Citrix Ltd.
3 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
4 * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; version 2.1 only. with the special
9 * exception on linking described in file LICENSE.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 */
17 #include "libxl_osdeps.h"
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <sys/select.h>
26 #include <sys/wait.h>
27 #include <sys/time.h>
28 #include <signal.h>
29 #include <unistd.h> /* for write, unlink and close */
30 #include <stdint.h>
31 #include <inttypes.h>
32 #include <assert.h>
34 #include "libxl.h"
35 #include "libxl_utils.h"
36 #include "libxl_internal.h"
37 #include "flexarray.h"
39 #define PAGE_TO_MEMKB(pages) ((pages) * 4)
41 int libxl_ctx_init(libxl_ctx *ctx, int version, xentoollog_logger *lg)
42 {
43 if (version != LIBXL_VERSION)
44 return ERROR_VERSION;
45 memset(ctx, 0, sizeof(libxl_ctx));
46 ctx->lg = lg;
47 memset(&ctx->version_info, 0, sizeof(libxl_version_info));
49 ctx->xch = xc_interface_open(lg,lg,0);
50 if (!ctx->xch) {
51 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno,
52 "cannot open libxc handle");
53 return ERROR_FAIL;
54 }
56 ctx->xsh = xs_daemon_open();
57 if (!ctx->xsh)
58 ctx->xsh = xs_domain_open();
59 if (!ctx->xsh) {
60 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno,
61 "cannot connect to xenstore");
62 xc_interface_close(ctx->xch);
63 return ERROR_FAIL;
64 }
65 return 0;
66 }
68 int libxl_ctx_free(libxl_ctx *ctx)
69 {
70 if (ctx->xch) xc_interface_close(ctx->xch);
71 libxl_version_info_destroy(&ctx->version_info);
72 if (ctx->xsh) xs_daemon_close(ctx->xsh);
73 return 0;
74 }
76 void libxl_string_list_destroy(libxl_string_list *psl)
77 {
78 int i;
79 libxl_string_list sl = *psl;
81 if (!sl)
82 return;
84 for (i = 0; sl[i] != NULL; i++)
85 free(sl[i]);
86 free(sl);
87 }
89 void libxl_key_value_list_destroy(libxl_key_value_list *pkvl)
90 {
91 int i;
92 libxl_key_value_list kvl = *pkvl;
94 if (!kvl)
95 return;
97 for (i = 0; kvl[i] != NULL; i += 2) {
98 free(kvl[i]);
99 if (kvl[i + 1])
100 free(kvl[i + 1]);
101 }
102 free(kvl);
103 }
105 /******************************************************************************/
107 int libxl_domain_make(libxl_ctx *ctx, libxl_domain_create_info *info,
108 uint32_t *domid)
109 {
110 libxl_gc gc = LIBXL_INIT_GC(ctx);
111 int flags, ret, i, rc;
112 char *uuid_string;
113 char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"};
114 char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
115 "control", "attr", "messages" };
116 char *dom_path, *vm_path;
117 struct xs_permissions roperm[2];
118 struct xs_permissions rwperm[1];
119 xs_transaction_t t;
120 xen_domain_handle_t handle;
122 uuid_string = libxl__uuid2string(&gc, info->uuid);
123 if (!uuid_string) {
124 libxl__free_all(&gc);
125 return ERROR_NOMEM;
126 }
128 flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
129 flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
130 flags |= info->oos ? 0 : XEN_DOMCTL_CDF_oos_off;
131 *domid = -1;
133 /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
134 libxl_uuid_copy((libxl_uuid *)handle, &info->uuid);
136 ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
137 if (ret < 0) {
138 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain creation fail");
139 libxl__free_all(&gc);
140 return ERROR_FAIL;
141 }
143 ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid);
144 if (ret < 0) {
145 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain move fail");
146 libxl__free_all(&gc);
147 return ERROR_FAIL;
148 }
150 dom_path = libxl__xs_get_dompath(&gc, *domid);
151 if (!dom_path) {
152 libxl__free_all(&gc);
153 return ERROR_FAIL;
154 }
156 vm_path = libxl__sprintf(&gc, "/vm/%s", uuid_string);
157 if (!vm_path) {
158 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "cannot allocate create paths");
159 libxl__free_all(&gc);
160 return ERROR_FAIL;
161 }
163 roperm[0].id = 0;
164 roperm[0].perms = XS_PERM_NONE;
165 roperm[1].id = *domid;
166 roperm[1].perms = XS_PERM_READ;
167 rwperm[0].id = *domid;
168 rwperm[0].perms = XS_PERM_NONE;
170 retry_transaction:
171 t = xs_transaction_start(ctx->xsh);
172 xs_rm(ctx->xsh, t, dom_path);
173 xs_mkdir(ctx->xsh, t, dom_path);
174 xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm));
176 xs_rm(ctx->xsh, t, vm_path);
177 xs_mkdir(ctx->xsh, t, vm_path);
178 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
180 xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
181 rc = libxl_domain_rename(ctx, *domid, 0, info->name, t);
182 if (rc) {
183 libxl__free_all(&gc);
184 return rc;
185 }
187 for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
188 char *path = libxl__sprintf(&gc, "%s/%s", dom_path, rw_paths[i]);
189 xs_mkdir(ctx->xsh, t, path);
190 xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm));
191 }
192 for (i = 0; i < ARRAY_SIZE(ro_paths); i++) {
193 char *path = libxl__sprintf(&gc, "%s/%s", dom_path, ro_paths[i]);
194 xs_mkdir(ctx->xsh, t, path);
195 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
196 }
198 xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
199 xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/name", vm_path), info->name, strlen(info->name));
200 if (info->poolname)
201 xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/pool_name", vm_path), info->poolname, strlen(info->poolname));
203 libxl__xs_writev(&gc, t, dom_path, info->xsdata);
204 libxl__xs_writev(&gc, t, libxl__sprintf(&gc, "%s/platform", dom_path), info->platformdata);
206 xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
208 if (!xs_transaction_end(ctx->xsh, t, 0))
209 if (errno == EAGAIN)
210 goto retry_transaction;
212 libxl__free_all(&gc);
213 return 0;
214 }
216 int libxl_domain_rename(libxl_ctx *ctx, uint32_t domid,
217 const char *old_name, const char *new_name,
218 xs_transaction_t trans)
219 {
220 libxl_gc gc = LIBXL_INIT_GC(ctx);
221 char *dom_path = 0;
222 const char *name_path;
223 char *got_old_name;
224 unsigned int got_old_len;
225 xs_transaction_t our_trans = 0;
226 int rc;
228 dom_path = libxl__xs_get_dompath(&gc, domid);
229 if (!dom_path) goto x_nomem;
231 name_path= libxl__sprintf(&gc, "%s/name", dom_path);
232 if (!name_path) goto x_nomem;
234 retry_transaction:
235 if (!trans) {
236 trans = our_trans = xs_transaction_start(ctx->xsh);
237 if (!our_trans) {
238 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno,
239 "create xs transaction for domain (re)name");
240 goto x_fail;
241 }
242 }
244 if (old_name) {
245 got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len);
246 if (!got_old_name) {
247 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno, "check old name"
248 " for domain %"PRIu32" allegedly named `%s'",
249 domid, old_name);
250 goto x_fail;
251 }
252 if (strcmp(old_name, got_old_name)) {
253 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "domain %"PRIu32" allegedly named "
254 "`%s' is actually named `%s' - racing ?",
255 domid, old_name, got_old_name);
256 free(got_old_name);
257 goto x_fail;
258 }
259 free(got_old_name);
260 }
261 if (!xs_write(ctx->xsh, trans, name_path,
262 new_name, strlen(new_name))) {
263 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "failed to write new name `%s'"
264 " for domain %"PRIu32" previously named `%s'",
265 new_name, domid, old_name);
266 goto x_fail;
267 }
269 if (our_trans) {
270 if (!xs_transaction_end(ctx->xsh, our_trans, 0)) {
271 trans = our_trans = 0;
272 if (errno != EAGAIN) {
273 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "failed to commit new name `%s'"
274 " for domain %"PRIu32" previously named `%s'",
275 new_name, domid, old_name);
276 goto x_fail;
277 }
278 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "need to retry rename transaction"
279 " for domain %"PRIu32" (name_path=\"%s\", new_name=\"%s\")",
280 domid, name_path, new_name);
281 goto retry_transaction;
282 }
283 our_trans = 0;
284 }
286 rc = 0;
287 x_rc:
288 if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
289 libxl__free_all(&gc);
290 return rc;
292 x_fail: rc = ERROR_FAIL; goto x_rc;
293 x_nomem: rc = ERROR_NOMEM; goto x_rc;
294 }
296 int libxl_domain_build(libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, libxl_domain_build_state *state)
297 {
298 libxl_gc gc = LIBXL_INIT_GC(ctx);
299 char **vments = NULL, **localents = NULL;
300 struct timeval start_time;
301 int i, ret;
303 ret = libxl__build_pre(ctx, domid, info, state);
304 if (ret)
305 goto out;
307 gettimeofday(&start_time, NULL);
309 if (info->hvm) {
310 ret = libxl__build_hvm(ctx, domid, info, state);
311 if (ret)
312 goto out;
314 vments = libxl__calloc(&gc, 7, sizeof(char *));
315 vments[0] = "rtc/timeoffset";
316 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
317 vments[2] = "image/ostype";
318 vments[3] = "hvm";
319 vments[4] = "start_time";
320 vments[5] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
321 } else {
322 ret = libxl__build_pv(ctx, domid, info, state);
323 if (ret)
324 goto out;
326 vments = libxl__calloc(&gc, 11, sizeof(char *));
327 i = 0;
328 vments[i++] = "image/ostype";
329 vments[i++] = "linux";
330 vments[i++] = "image/kernel";
331 vments[i++] = (char*) info->kernel.path;
332 vments[i++] = "start_time";
333 vments[i++] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
334 if (info->u.pv.ramdisk.path) {
335 vments[i++] = "image/ramdisk";
336 vments[i++] = (char*) info->u.pv.ramdisk.path;
337 }
338 if (info->u.pv.cmdline) {
339 vments[i++] = "image/cmdline";
340 vments[i++] = (char*) info->u.pv.cmdline;
341 }
342 }
343 ret = libxl__build_post(ctx, domid, info, state, vments, localents);
344 out:
345 libxl__file_reference_unmap(&info->kernel);
346 if (!info->hvm)
347 libxl__file_reference_unmap(&info->u.pv.ramdisk);
349 libxl__free_all(&gc);
350 return ret;
351 }
353 int libxl_domain_restore(libxl_ctx *ctx, libxl_domain_build_info *info,
354 uint32_t domid, int fd, libxl_domain_build_state *state,
355 libxl_device_model_info *dm_info)
356 {
357 libxl_gc gc = LIBXL_INIT_GC(ctx);
358 char **vments = NULL, **localents = NULL;
359 struct timeval start_time;
360 int i, ret, esave, flags;
362 ret = libxl__build_pre(ctx, domid, info, state);
363 if (ret)
364 goto out;
366 ret = libxl__domain_restore_common(ctx, domid, info, state, fd);
367 if (ret)
368 goto out;
370 gettimeofday(&start_time, NULL);
372 if (info->hvm) {
373 vments = libxl__calloc(&gc, 7, sizeof(char *));
374 vments[0] = "rtc/timeoffset";
375 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
376 vments[2] = "image/ostype";
377 vments[3] = "hvm";
378 vments[4] = "start_time";
379 vments[5] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
380 } else {
381 vments = libxl__calloc(&gc, 11, sizeof(char *));
382 i = 0;
383 vments[i++] = "image/ostype";
384 vments[i++] = "linux";
385 vments[i++] = "image/kernel";
386 vments[i++] = (char*) info->kernel.path;
387 vments[i++] = "start_time";
388 vments[i++] = libxl__sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
389 if (info->u.pv.ramdisk.path) {
390 vments[i++] = "image/ramdisk";
391 vments[i++] = (char*) info->u.pv.ramdisk.path;
392 }
393 if (info->u.pv.cmdline) {
394 vments[i++] = "image/cmdline";
395 vments[i++] = (char*) info->u.pv.cmdline;
396 }
397 }
398 ret = libxl__build_post(ctx, domid, info, state, vments, localents);
399 if (ret)
400 goto out;
402 dm_info->saved_state = NULL;
403 if (info->hvm) {
404 ret = asprintf(&dm_info->saved_state,
405 "/var/lib/xen/qemu-save.%d", domid);
406 ret = (ret < 0) ? ERROR_FAIL : 0;
407 }
409 out:
410 libxl__file_reference_unmap(&info->kernel);
411 if (!info->hvm)
412 libxl__file_reference_unmap(&info->u.pv.ramdisk);
414 esave = errno;
416 flags = fcntl(fd, F_GETFL);
417 if (flags == -1) {
418 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to get flags on restore fd");
419 } else {
420 flags &= ~O_NONBLOCK;
421 if (fcntl(fd, F_SETFL, flags) == -1)
422 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unable to put restore fd"
423 " back to blocking mode");
424 }
426 errno = esave;
427 libxl__free_all(&gc);
428 return ret;
429 }
431 int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid)
432 {
433 libxl_gc gc = LIBXL_INIT_GC(ctx);
434 int rc = 0;
436 if (libxl__domain_is_hvm(ctx, domid)) {
437 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Called domain_resume on "
438 "non-cooperative hvm domain %u", domid);
439 rc = ERROR_NI;
440 goto out;
441 }
442 if (xc_domain_resume(ctx->xch, domid, 1)) {
443 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
444 "xc_domain_resume failed for domain %u",
445 domid);
446 rc = ERROR_FAIL;
447 goto out;
448 }
449 if (!xs_resume_domain(ctx->xsh, domid)) {
450 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
451 "xs_resume_domain failed for domain %u",
452 domid);
453 rc = ERROR_FAIL;
454 }
455 out:
456 libxl__free_all(&gc);
457 return 0;
458 }
460 /*
461 * Preserves a domain but rewrites xenstore etc to make it unique so
462 * that the domain can be restarted.
463 *
464 * Does not modify info so that it may be reused.
465 */
466 int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid,
467 libxl_domain_create_info *info, const char *name_suffix, libxl_uuid new_uuid)
468 {
469 libxl_gc gc = LIBXL_INIT_GC(ctx);
470 struct xs_permissions roperm[2];
471 xs_transaction_t t;
472 char *preserved_name;
473 char *uuid_string;
474 char *vm_path;
475 char *dom_path;
477 int rc;
479 preserved_name = libxl__sprintf(&gc, "%s%s", info->name, name_suffix);
480 if (!preserved_name) {
481 libxl__free_all(&gc);
482 return ERROR_NOMEM;
483 }
485 uuid_string = libxl__uuid2string(&gc, new_uuid);
486 if (!uuid_string) {
487 libxl__free_all(&gc);
488 return ERROR_NOMEM;
489 }
491 dom_path = libxl__xs_get_dompath(&gc, domid);
492 if (!dom_path) {
493 libxl__free_all(&gc);
494 return ERROR_FAIL;
495 }
497 vm_path = libxl__sprintf(&gc, "/vm/%s", uuid_string);
498 if (!vm_path) {
499 libxl__free_all(&gc);
500 return ERROR_FAIL;
501 }
503 roperm[0].id = 0;
504 roperm[0].perms = XS_PERM_NONE;
505 roperm[1].id = domid;
506 roperm[1].perms = XS_PERM_READ;
508 retry_transaction:
509 t = xs_transaction_start(ctx->xsh);
511 xs_rm(ctx->xsh, t, vm_path);
512 xs_mkdir(ctx->xsh, t, vm_path);
513 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
515 xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
516 rc = libxl_domain_rename(ctx, domid, info->name, preserved_name, t);
517 if (rc) return rc;
519 xs_write(ctx->xsh, t, libxl__sprintf(&gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
521 if (!xs_transaction_end(ctx->xsh, t, 0))
522 if (errno == EAGAIN)
523 goto retry_transaction;
525 libxl__free_all(&gc);
526 return 0;
527 }
529 static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo,
530 libxl_dominfo *xlinfo)
531 {
532 memcpy(&(xlinfo->uuid), xcinfo->handle, sizeof(xen_domain_handle_t));
533 xlinfo->domid = xcinfo->domain;
535 xlinfo->dying = !!(xcinfo->flags&XEN_DOMINF_dying);
536 xlinfo->shutdown = !!(xcinfo->flags&XEN_DOMINF_shutdown);
537 xlinfo->paused = !!(xcinfo->flags&XEN_DOMINF_paused);
538 xlinfo->blocked = !!(xcinfo->flags&XEN_DOMINF_blocked);
539 xlinfo->running = !!(xcinfo->flags&XEN_DOMINF_running);
541 if (xlinfo->shutdown || xlinfo->dying)
542 xlinfo->shutdown_reason = (xcinfo->flags>>XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask;
543 else
544 xlinfo->shutdown_reason = ~0;
546 xlinfo->max_memkb = PAGE_TO_MEMKB(xcinfo->tot_pages);
547 xlinfo->cpu_time = xcinfo->cpu_time;
548 xlinfo->vcpu_max_id = xcinfo->max_vcpu_id;
549 xlinfo->vcpu_online = xcinfo->nr_online_vcpus;
550 }
552 libxl_dominfo * libxl_list_domain(libxl_ctx *ctx, int *nb_domain)
553 {
554 libxl_dominfo *ptr;
555 int i, ret;
556 xc_domaininfo_t info[1024];
557 int size = 1024;
559 ptr = calloc(size, sizeof(libxl_dominfo));
560 if (!ptr) {
561 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating domain info");
562 return NULL;
563 }
565 ret = xc_domain_getinfolist(ctx->xch, 0, 1024, info);
566 if (ret<0) {
567 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "geting domain info list");
568 return NULL;
569 }
571 for (i = 0; i < ret; i++) {
572 xcinfo2xlinfo(&info[i], &ptr[i]);
573 }
574 *nb_domain = ret;
575 return ptr;
576 }
578 int libxl_domain_info(libxl_ctx *ctx, libxl_dominfo *info_r,
579 uint32_t domid) {
580 xc_domaininfo_t xcinfo;
581 int ret;
583 ret = xc_domain_getinfolist(ctx->xch, domid, 1, &xcinfo);
584 if (ret<0) {
585 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "geting domain info list");
586 return ERROR_FAIL;
587 }
588 if (ret==0 || xcinfo.domain != domid) return ERROR_INVAL;
590 xcinfo2xlinfo(&xcinfo, info_r);
591 return 0;
592 }
594 libxl_poolinfo * libxl_list_pool(libxl_ctx *ctx, int *nb_pool)
595 {
596 libxl_poolinfo *ptr;
597 int i, ret;
598 xc_cpupoolinfo_t info[256];
599 int size = 256;
601 ptr = calloc(size, sizeof(libxl_poolinfo));
602 if (!ptr) {
603 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "allocating cpupool info");
604 return NULL;
605 }
607 ret = xc_cpupool_getinfo(ctx->xch, 0, 256, info);
608 if (ret<0) {
609 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting cpupool info");
610 return NULL;
611 }
613 for (i = 0; i < ret; i++) {
614 ptr[i].poolid = info[i].cpupool_id;
615 }
616 *nb_pool = ret;
617 return ptr;
618 }
620 /* this API call only list VM running on this host. a VM can be an aggregate of multiple domains. */
621 libxl_vminfo * libxl_list_vm(libxl_ctx *ctx, int *nb_vm)
622 {
623 libxl_vminfo *ptr;
624 int index, i, ret;
625 xc_domaininfo_t info[1024];
626 int size = 1024;
628 ptr = calloc(size, sizeof(libxl_dominfo));
629 if (!ptr)
630 return NULL;
632 ret = xc_domain_getinfolist(ctx->xch, 1, 1024, info);
633 if (ret<0) {
634 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "geting domain info list");
635 return NULL;
636 }
637 for (index = i = 0; i < ret; i++) {
638 if (libxl_is_stubdom(ctx, info[i].domain, NULL))
639 continue;
640 memcpy(&(ptr[index].uuid), info[i].handle, sizeof(xen_domain_handle_t));
641 ptr[index].domid = info[i].domain;
643 index++;
644 }
645 *nb_vm = index;
646 return ptr;
647 }
649 int libxl_domain_suspend(libxl_ctx *ctx, libxl_domain_suspend_info *info,
650 uint32_t domid, int fd)
651 {
652 int hvm = libxl__domain_is_hvm(ctx, domid);
653 int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
654 int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG;
655 int rc = 0;
657 libxl__domain_suspend_common(ctx, domid, fd, hvm, live, debug);
658 if (hvm)
659 rc = libxl__domain_save_device_model(ctx, domid, fd);
660 return rc;
661 }
663 int libxl_domain_pause(libxl_ctx *ctx, uint32_t domid)
664 {
665 int ret;
666 ret = xc_domain_pause(ctx->xch, domid);
667 if (ret<0) {
668 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "pausing domain %d", domid);
669 return ERROR_FAIL;
670 }
671 return 0;
672 }
674 int libxl_domain_core_dump(libxl_ctx *ctx, uint32_t domid,
675 const char *filename)
676 {
677 int ret;
678 ret = xc_domain_dumpcore(ctx->xch, domid, filename);
679 if (ret<0) {
680 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "core dumping domain %d to %s",
681 domid, filename);
682 return ERROR_FAIL;
683 }
684 return 0;
685 }
687 int libxl_domain_unpause(libxl_ctx *ctx, uint32_t domid)
688 {
689 libxl_gc gc = LIBXL_INIT_GC(ctx);
690 char *path;
691 char *state;
692 int ret, rc = 0;
694 if (libxl__domain_is_hvm(ctx, domid)) {
695 path = libxl__sprintf(&gc, "/local/domain/0/device-model/%d/state", domid);
696 state = libxl__xs_read(&gc, XBT_NULL, path);
697 if (state != NULL && !strcmp(state, "paused")) {
698 libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/0/device-model/%d/command", domid), "continue");
699 libxl__wait_for_device_model(ctx, domid, "running", NULL, NULL);
700 }
701 }
702 ret = xc_domain_unpause(ctx->xch, domid);
703 if (ret<0) {
704 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unpausing domain %d", domid);
705 rc = ERROR_FAIL;
706 }
707 libxl__free_all(&gc);
708 return rc;
709 }
711 static char *req_table[] = {
712 [0] = "poweroff",
713 [1] = "reboot",
714 [2] = "suspend",
715 [3] = "crash",
716 [4] = "halt",
717 };
719 int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid, int req)
720 {
721 libxl_gc gc = LIBXL_INIT_GC(ctx);
722 char *shutdown_path;
723 char *dom_path;
725 if (req > ARRAY_SIZE(req_table)) {
726 libxl__free_all(&gc);
727 return ERROR_INVAL;
728 }
730 dom_path = libxl__xs_get_dompath(&gc, domid);
731 if (!dom_path) {
732 libxl__free_all(&gc);
733 return ERROR_FAIL;
734 }
736 shutdown_path = libxl__sprintf(&gc, "%s/control/shutdown", dom_path);
738 xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], strlen(req_table[req]));
739 if (libxl__domain_is_hvm(ctx,domid)) {
740 unsigned long acpi_s_state = 0;
741 unsigned long pvdriver = 0;
742 int ret;
743 ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, &acpi_s_state);
744 if (ret<0) {
745 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting ACPI S-state");
746 return ERROR_FAIL;
747 }
748 ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
749 if (ret<0) {
750 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting HVM callback IRQ");
751 return ERROR_FAIL;
752 }
753 if (!pvdriver || acpi_s_state != 0) {
754 ret = xc_domain_shutdown(ctx->xch, domid, req);
755 if (ret<0) {
756 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unpausing domain");
757 return ERROR_FAIL;
758 }
759 }
760 }
761 libxl__free_all(&gc);
762 return 0;
763 }
765 int libxl_get_wait_fd(libxl_ctx *ctx, int *fd)
766 {
767 *fd = xs_fileno(ctx->xsh);
768 return 0;
769 }
771 int libxl_wait_for_domain_death(libxl_ctx *ctx, uint32_t domid, libxl_waiter *waiter)
772 {
773 waiter->path = strdup("@releaseDomain");
774 if (asprintf(&(waiter->token), "%d", LIBXL_EVENT_DOMAIN_DEATH) < 0)
775 return -1;
776 if (!xs_watch(ctx->xsh, waiter->path, waiter->token))
777 return -1;
778 return 0;
779 }
781 int libxl_wait_for_disk_ejects(libxl_ctx *ctx, uint32_t guest_domid, libxl_device_disk *disks, int num_disks, libxl_waiter *waiter)
782 {
783 libxl_gc gc = LIBXL_INIT_GC(ctx);
784 int i, rc = -1;
785 uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
787 if (!domid)
788 domid = guest_domid;
790 for (i = 0; i < num_disks; i++) {
791 if (asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject",
792 libxl__xs_get_dompath(&gc, domid),
793 libxl__device_disk_dev_number(disks[i].virtpath)) < 0)
794 goto out;
795 if (asprintf(&(waiter[i].token), "%d", LIBXL_EVENT_DISK_EJECT) < 0)
796 goto out;
797 xs_watch(ctx->xsh, waiter->path, waiter->token);
798 }
799 rc = 0;
800 out:
801 libxl__free_all(&gc);
802 return rc;
803 }
805 int libxl_get_event(libxl_ctx *ctx, libxl_event *event)
806 {
807 unsigned int num;
808 char **events = xs_read_watch(ctx->xsh, &num);
809 if (num != 2) {
810 free(events);
811 return ERROR_FAIL;
812 }
813 event->path = strdup(events[XS_WATCH_PATH]);
814 event->token = strdup(events[XS_WATCH_TOKEN]);
815 event->type = atoi(event->token);
816 free(events);
817 return 0;
818 }
820 int libxl_stop_waiting(libxl_ctx *ctx, libxl_waiter *waiter)
821 {
822 if (!xs_unwatch(ctx->xsh, waiter->path, waiter->token))
823 return ERROR_FAIL;
824 else
825 return 0;
826 }
828 int libxl_free_event(libxl_event *event)
829 {
830 free(event->path);
831 free(event->token);
832 return 0;
833 }
835 int libxl_free_waiter(libxl_waiter *waiter)
836 {
837 free(waiter->path);
838 free(waiter->token);
839 return 0;
840 }
842 int libxl_event_get_domain_death_info(libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_dominfo *info)
843 {
844 if (libxl_domain_info(ctx, info, domid) < 0)
845 return 0;
847 if (info->running || (!info->shutdown && !info->dying))
848 return ERROR_INVAL;
850 return 1;
851 }
853 int libxl_event_get_disk_eject_info(libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_device_disk *disk)
854 {
855 libxl_gc gc = LIBXL_INIT_GC(ctx);
856 char *path;
857 char *backend;
858 char *value;
860 value = libxl__xs_read(&gc, XBT_NULL, event->path);
862 if (!value || strcmp(value, "eject")) {
863 libxl__free_all(&gc);
864 return 0;
865 }
867 path = strdup(event->path);
868 path[strlen(path) - 6] = '\0';
869 backend = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend", path));
871 disk->backend_domid = 0;
872 disk->domid = domid;
873 disk->physpath = NULL;
874 disk->phystype = 0;
875 /* this value is returned to the user: do not free right away */
876 disk->virtpath = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/dev", backend));
877 disk->unpluggable = 1;
878 disk->readwrite = 0;
879 disk->is_cdrom = 1;
881 free(path);
882 libxl__free_all(&gc);
883 return 1;
884 }
886 static int libxl_destroy_device_model(libxl_ctx *ctx, uint32_t domid)
887 {
888 libxl_gc gc = LIBXL_INIT_GC(ctx);
889 char *pid;
890 int ret;
892 pid = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid));
893 if (!pid) {
894 int stubdomid = libxl_get_stubdom_id(ctx, domid);
895 if (!stubdomid) {
896 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't find device model's pid");
897 ret = ERROR_INVAL;
898 goto out;
899 }
900 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Device model is a stubdom, domid=%d\n", stubdomid);
901 ret = libxl_domain_destroy(ctx, stubdomid, 0);
902 goto out;
903 }
904 xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", domid));
906 ret = kill(atoi(pid), SIGHUP);
907 if (ret < 0 && errno == ESRCH) {
908 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model already exited");
909 ret = 0;
910 } else if (ret == 0) {
911 LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model signaled");
912 ret = 0;
913 } else {
914 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "failed to kill Device Model [%d]",
915 atoi(pid));
916 }
917 out:
918 libxl__free_all(&gc);
919 return ret;
920 }
922 int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, int force)
923 {
924 libxl_gc gc = LIBXL_INIT_GC(ctx);
925 char *dom_path;
926 char *vm_path;
927 int rc, dm_present;
929 if (libxl__domain_is_hvm(ctx, domid)) {
930 dm_present = 1;
931 } else {
932 char *pid;
933 pid = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid));
934 dm_present = (pid != NULL);
935 }
937 dom_path = libxl__xs_get_dompath(&gc, domid);
938 if (!dom_path) {
939 rc = ERROR_FAIL;
940 goto out;
941 }
943 if (libxl_device_pci_shutdown(ctx, domid) < 0)
944 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "pci shutdown failed for domid %d", domid);
945 if (dm_present) {
946 xs_write(ctx->xsh, XBT_NULL,
947 libxl__sprintf(&gc, "/local/domain/0/device-model/%d/command", domid),
948 "shutdown", strlen("shutdown"));
949 }
950 rc = xc_domain_pause(ctx->xch, domid);
951 if (rc < 0) {
952 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_domain_pause failed for %d", domid);
953 }
954 if (dm_present) {
955 if (libxl_destroy_device_model(ctx, domid) < 0)
956 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl_destroy_device_model failed for %d", domid);
957 }
958 if (libxl__devices_destroy(ctx, domid, force) < 0)
959 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "libxl_destroy_devices failed for %d", domid);
961 vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/vm", dom_path));
962 if (vm_path)
963 if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
964 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xs_rm failed for %s", vm_path);
966 if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
967 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xs_rm failed for %s", dom_path);
969 libxl__userdata_destroyall(ctx, domid);
971 rc = xc_domain_destroy(ctx->xch, domid);
972 if (rc < 0) {
973 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
974 rc = ERROR_FAIL;
975 goto out;
976 }
977 rc = 0;
978 out:
979 libxl__free_all(&gc);
980 return 0;
981 }
983 int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_constype type)
984 {
985 libxl_gc gc = LIBXL_INIT_GC(ctx);
986 char *p = libxl__sprintf(&gc, "%s/xenconsole", libxl_private_bindir_path());
987 char *domid_s = libxl__sprintf(&gc, "%d", domid);
988 char *cons_num_s = libxl__sprintf(&gc, "%d", cons_num);
989 char *cons_type_s;
991 switch (type) {
992 case LIBXL_CONSTYPE_PV:
993 cons_type_s = "pv";
994 break;
995 case LIBXL_CONSTYPE_SERIAL:
996 cons_type_s = "serial";
997 break;
998 default:
999 goto out;
1002 execl(p, p, domid_s, "--num", cons_num_s, "--type", cons_type_s, (void *)NULL);
1004 out:
1005 libxl__free_all(&gc);
1006 return ERROR_FAIL;
1009 int libxl_primary_console_exec(libxl_ctx *ctx, uint32_t domid_vm)
1011 uint32_t stubdomid = libxl_get_stubdom_id(ctx, domid_vm);
1012 if (stubdomid)
1013 return libxl_console_exec(ctx, stubdomid, 1, LIBXL_CONSTYPE_PV);
1014 else {
1015 if (libxl__domain_is_hvm(ctx, domid_vm))
1016 return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_SERIAL);
1017 else
1018 return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_PV);
1022 int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass)
1024 libxl_gc gc = LIBXL_INIT_GC(ctx);
1025 const char *vnc_port, *vfb_back;
1026 const char *vnc_listen = NULL, *vnc_pass = NULL;
1027 int port = 0, autopass_fd = -1;
1028 char *vnc_bin, *args[] = {
1029 "vncviewer",
1030 NULL, /* hostname:display */
1031 NULL, /* -autopass */
1032 NULL,
1033 };
1035 vnc_port = libxl__xs_read(&gc, XBT_NULL,
1036 libxl__sprintf(&gc,
1037 "/local/domain/%d/console/vnc-port", domid));
1038 if ( vnc_port )
1039 port = atoi(vnc_port) - 5900;
1041 vfb_back = libxl__xs_read(&gc, XBT_NULL,
1042 libxl__sprintf(&gc,
1043 "/local/domain/%d/device/vfb/0/backend", domid));
1044 if ( vfb_back ) {
1045 vnc_listen = libxl__xs_read(&gc, XBT_NULL,
1046 libxl__sprintf(&gc,
1047 "/local/domain/%d/console/vnc-listen", domid));
1048 if ( autopass )
1049 vnc_pass = libxl__xs_read(&gc, XBT_NULL,
1050 libxl__sprintf(&gc,
1051 "/local/domain/%d/console/vnc-pass", domid));
1054 if ( NULL == vnc_listen )
1055 vnc_listen = "localhost";
1057 if ( (vnc_bin = getenv("VNCVIEWER")) )
1058 args[0] = vnc_bin;
1060 args[1] = libxl__sprintf(&gc, "%s:%d", vnc_listen, port);
1062 if ( vnc_pass ) {
1063 char tmpname[] = "/tmp/vncautopass.XXXXXX";
1064 autopass_fd = mkstemp(tmpname);
1065 if ( autopass_fd < 0 )
1066 goto skip_autopass;
1068 if ( unlink(tmpname) )
1069 /* should never happen */
1070 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "unlink %s failed", tmpname);
1072 if ( libxl_write_exactly(ctx, autopass_fd, vnc_pass, strlen(vnc_pass),
1073 tmpname, "vnc password") ) {
1074 do { close(autopass_fd); } while(errno == EINTR);
1075 goto skip_autopass;
1078 args[2] = "-autopass";
1081 skip_autopass:
1082 libxl__free_all(&gc);
1083 libxl__exec(autopass_fd, -1, -1, args[0], args);
1084 return 0;
1087 static char ** libxl_build_device_model_args_old(libxl_gc *gc,
1088 libxl_device_model_info *info,
1089 libxl_device_nic *vifs,
1090 int num_vifs)
1092 int num = 0, i;
1093 flexarray_t *dm_args;
1094 dm_args = flexarray_make(16, 1);
1096 if (!dm_args)
1097 return NULL;
1099 flexarray_set(dm_args, num++, "qemu-dm");
1100 flexarray_set(dm_args, num++, "-d");
1102 flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->domid));
1104 if (info->dom_name) {
1105 flexarray_set(dm_args, num++, "-domain-name");
1106 flexarray_set(dm_args, num++, info->dom_name);
1108 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
1109 flexarray_set(dm_args, num++, "-vnc");
1110 if (info->vncdisplay) {
1111 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
1112 flexarray_set(
1113 dm_args, num++,
1114 libxl__sprintf(gc, "%s:%d%s",
1115 info->vnclisten,
1116 info->vncdisplay,
1117 info->vncpasswd ? ",password" : ""));
1118 } else {
1119 flexarray_set(dm_args, num++, libxl__sprintf(gc, "127.0.0.1:%d", info->vncdisplay));
1121 } else if (info->vnclisten) {
1122 if (strchr(info->vnclisten, ':') != NULL) {
1123 flexarray_set(dm_args, num++, info->vnclisten);
1124 } else {
1125 flexarray_set(dm_args, num++, libxl__sprintf(gc, "%s:0", info->vnclisten));
1127 } else {
1128 flexarray_set(dm_args, num++, "127.0.0.1:0");
1130 if (info->vncunused) {
1131 flexarray_set(dm_args, num++, "-vncunused");
1134 if (info->sdl) {
1135 flexarray_set(dm_args, num++, "-sdl");
1136 if (!info->opengl) {
1137 flexarray_set(dm_args, num++, "-disable-opengl");
1140 if (info->keymap) {
1141 flexarray_set(dm_args, num++, "-k");
1142 flexarray_set(dm_args, num++, info->keymap);
1144 if (info->nographic && (!info->sdl && !info->vnc)) {
1145 flexarray_set(dm_args, num++, "-nographic");
1147 if (info->serial) {
1148 flexarray_set(dm_args, num++, "-serial");
1149 flexarray_set(dm_args, num++, info->serial);
1151 if (info->type == XENFV) {
1152 int ioemu_vifs = 0;
1154 if (info->videoram) {
1155 flexarray_set(dm_args, num++, "-videoram");
1156 flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->videoram));
1158 if (info->stdvga) {
1159 flexarray_set(dm_args, num++, "-std-vga");
1162 if (info->boot) {
1163 flexarray_set(dm_args, num++, "-boot");
1164 flexarray_set(dm_args, num++, info->boot);
1166 if (info->usb || info->usbdevice) {
1167 flexarray_set(dm_args, num++, "-usb");
1168 if (info->usbdevice) {
1169 flexarray_set(dm_args, num++, "-usbdevice");
1170 flexarray_set(dm_args, num++, info->usbdevice);
1173 if (info->soundhw) {
1174 flexarray_set(dm_args, num++, "-soundhw");
1175 flexarray_set(dm_args, num++, info->soundhw);
1177 if (info->apic) {
1178 flexarray_set(dm_args, num++, "-acpi");
1180 if (info->vcpus > 1) {
1181 flexarray_set(dm_args, num++, "-vcpus");
1182 flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->vcpus));
1184 if (info->vcpu_avail) {
1185 flexarray_set(dm_args, num++, "-vcpu_avail");
1186 flexarray_set(dm_args, num++, libxl__sprintf(gc, "0x%x", info->vcpu_avail));
1188 for (i = 0; i < num_vifs; i++) {
1189 if (vifs[i].nictype == NICTYPE_IOEMU) {
1190 char *smac = libxl__sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
1191 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
1192 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
1193 if (!vifs[i].ifname)
1194 vifs[i].ifname = libxl__sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid);
1195 flexarray_set(dm_args, num++, "-net");
1196 flexarray_set(dm_args, num++, libxl__sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s",
1197 vifs[i].devid, smac, vifs[i].model));
1198 flexarray_set(dm_args, num++, "-net");
1199 flexarray_set(dm_args, num++, libxl__sprintf(gc, "tap,vlan=%d,ifname=%s,bridge=%s,script=no",
1200 vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
1201 ioemu_vifs++;
1204 /* If we have no emulated nics, tell qemu not to create any */
1205 if ( ioemu_vifs == 0 ) {
1206 flexarray_set(dm_args, num++, "-net");
1207 flexarray_set(dm_args, num++, "none");
1210 if (info->saved_state) {
1211 flexarray_set(dm_args, num++, "-loadvm");
1212 flexarray_set(dm_args, num++, info->saved_state);
1214 for (i = 0; info->extra && info->extra[i] != NULL; i++)
1215 flexarray_set(dm_args, num++, info->extra[i]);
1216 flexarray_set(dm_args, num++, "-M");
1217 if (info->type == XENPV)
1218 flexarray_set(dm_args, num++, "xenpv");
1219 else
1220 flexarray_set(dm_args, num++, "xenfv");
1221 flexarray_set(dm_args, num++, NULL);
1222 return (char **) flexarray_contents(dm_args);
1225 static char ** libxl_build_device_model_args_new(libxl_gc *gc,
1226 libxl_device_model_info *info,
1227 libxl_device_nic *vifs,
1228 int num_vifs)
1230 int num = 0, i;
1231 flexarray_t *dm_args;
1232 int nb;
1233 libxl_device_disk *disks;
1235 dm_args = flexarray_make(16, 1);
1236 if (!dm_args)
1237 return NULL;
1239 flexarray_set(dm_args, num++, "qemu-system-xen");
1240 flexarray_set(dm_args, num++, "-xen-domid");
1242 flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->domid));
1244 if (info->dom_name) {
1245 flexarray_set(dm_args, num++, "-name");
1246 flexarray_set(dm_args, num++, info->dom_name);
1248 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
1249 int display = 0;
1250 const char *listen = "127.0.0.1";
1252 flexarray_set(dm_args, num++, "-vnc");
1254 if (info->vncdisplay) {
1255 display = info->vncdisplay;
1256 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
1257 listen = info->vnclisten;
1259 } else if (info->vnclisten) {
1260 listen = info->vnclisten;
1263 if (strchr(listen, ':') != NULL)
1264 flexarray_set(dm_args, num++,
1265 libxl__sprintf(gc, "%s%s", listen,
1266 info->vncunused ? ",to=99" : ""));
1267 else
1268 flexarray_set(dm_args, num++,
1269 libxl__sprintf(gc, "%s:%d%s", listen, display,
1270 info->vncunused ? ",to=99" : ""));
1272 if (info->sdl) {
1273 flexarray_set(dm_args, num++, "-sdl");
1275 if (info->keymap) {
1276 flexarray_set(dm_args, num++, "-k");
1277 flexarray_set(dm_args, num++, info->keymap);
1279 if (info->nographic && (!info->sdl && !info->vnc)) {
1280 flexarray_set(dm_args, num++, "-nographic");
1282 if (info->serial) {
1283 flexarray_set(dm_args, num++, "-serial");
1284 flexarray_set(dm_args, num++, info->serial);
1286 if (info->type == XENFV) {
1287 int ioemu_vifs = 0;
1289 if (info->stdvga) {
1290 flexarray_set(dm_args, num++, "-vga");
1291 flexarray_set(dm_args, num++, "std");
1294 if (info->boot) {
1295 flexarray_set(dm_args, num++, "-boot");
1296 flexarray_set(dm_args, num++, libxl__sprintf(gc, "order=%s", info->boot));
1298 if (info->usb || info->usbdevice) {
1299 flexarray_set(dm_args, num++, "-usb");
1300 if (info->usbdevice) {
1301 flexarray_set(dm_args, num++, "-usbdevice");
1302 flexarray_set(dm_args, num++, info->usbdevice);
1305 if (info->soundhw) {
1306 flexarray_set(dm_args, num++, "-soundhw");
1307 flexarray_set(dm_args, num++, info->soundhw);
1309 if (!info->apic) {
1310 flexarray_set(dm_args, num++, "-no-acpi");
1312 if (info->vcpus > 1) {
1313 flexarray_set(dm_args, num++, "-smp");
1314 if (info->vcpu_avail)
1315 flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d,maxcpus=%d", info->vcpus, info->vcpu_avail));
1316 else
1317 flexarray_set(dm_args, num++, libxl__sprintf(gc, "%d", info->vcpus));
1319 for (i = 0; i < num_vifs; i++) {
1320 if (vifs[i].nictype == NICTYPE_IOEMU) {
1321 char *smac = libxl__sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
1322 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
1323 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
1324 if (!vifs[i].ifname)
1325 vifs[i].ifname = libxl__sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid);
1326 flexarray_set(dm_args, num++, "-net");
1327 flexarray_set(dm_args, num++, libxl__sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s",
1328 vifs[i].devid, smac, vifs[i].model));
1329 flexarray_set(dm_args, num++, "-net");
1330 flexarray_set(dm_args, num++, libxl__sprintf(gc, "tap,vlan=%d,ifname=%s,script=no",
1331 vifs[i].devid, vifs[i].ifname));
1332 ioemu_vifs++;
1335 /* If we have no emulated nics, tell qemu not to create any */
1336 if ( ioemu_vifs == 0 ) {
1337 flexarray_set(dm_args, num++, "-net");
1338 flexarray_set(dm_args, num++, "none");
1341 if (info->saved_state) {
1342 flexarray_set(dm_args, num++, "-loadvm");
1343 flexarray_set(dm_args, num++, info->saved_state);
1345 for (i = 0; info->extra && info->extra[i] != NULL; i++)
1346 flexarray_set(dm_args, num++, info->extra[i]);
1347 flexarray_set(dm_args, num++, "-M");
1348 if (info->type == XENPV)
1349 flexarray_set(dm_args, num++, "xenpv");
1350 else
1351 flexarray_set(dm_args, num++, "xenfv");
1353 disks = libxl_device_disk_list(libxl_gc_owner(gc), info->domid, &nb);
1354 for (i; i < nb; i++) {
1355 if ( disks[i].is_cdrom ) {
1356 flexarray_set(dm_args, num++, "-cdrom");
1357 flexarray_set(dm_args, num++, disks[i].physpath);
1358 }else{
1359 flexarray_set(dm_args, num++, libxl__sprintf(gc, "-%s", disks[i].virtpath));
1360 flexarray_set(dm_args, num++, disks[i].physpath);
1362 libxl_device_disk_destroy(&disks[i]);
1364 free(disks);
1365 flexarray_set(dm_args, num++, NULL);
1366 return (char **) flexarray_contents(dm_args);
1369 static char ** libxl_build_device_model_args(libxl_gc *gc,
1370 libxl_device_model_info *info,
1371 libxl_device_nic *vifs,
1372 int num_vifs)
1374 libxl_ctx *ctx = libxl_gc_owner(gc);
1375 int new_qemu;
1377 new_qemu = libxl_check_device_model_version(ctx, info->device_model);
1379 if (new_qemu == 1) {
1380 return libxl_build_device_model_args_new(gc, info, vifs, num_vifs);
1381 } else {
1382 return libxl_build_device_model_args_old(gc, info, vifs, num_vifs);
1386 static void dm_xenstore_record_pid(void *for_spawn, pid_t innerchild)
1388 libxl_device_model_starting *starting = for_spawn;
1389 char *kvs[3];
1390 int rc;
1391 struct xs_handle *xsh;
1393 xsh = xs_daemon_open();
1394 /* we mustn't use the parent's handle in the child */
1396 kvs[0] = "image/device-model-pid";
1397 if (asprintf(&kvs[1], "%d", innerchild) < 0)
1398 return;
1399 kvs[2] = NULL;
1401 rc = xs_writev(xsh, XBT_NULL, starting->dom_path, kvs);
1402 if (rc)
1403 return;
1404 xs_daemon_close(xsh);
1407 static int libxl_vfb_and_vkb_from_device_model_info(libxl_ctx *ctx,
1408 libxl_device_model_info *info,
1409 libxl_device_vfb *vfb,
1410 libxl_device_vkb *vkb)
1412 memset(vfb, 0x00, sizeof(libxl_device_vfb));
1413 memset(vkb, 0x00, sizeof(libxl_device_vkb));
1415 vfb->backend_domid = 0;
1416 vfb->devid = 0;
1417 vfb->vnc = info->vnc;
1418 vfb->vnclisten = info->vnclisten;
1419 vfb->vncdisplay = info->vncdisplay;
1420 vfb->vncunused = info->vncunused;
1421 vfb->vncpasswd = info->vncpasswd;
1422 vfb->keymap = info->keymap;
1423 vfb->sdl = info->sdl;
1424 vfb->opengl = info->opengl;
1426 vkb->backend_domid = 0;
1427 vkb->devid = 0;
1428 return 0;
1431 static int libxl_write_dmargs(libxl_ctx *ctx, int domid, int guest_domid, char **args)
1433 libxl_gc gc = LIBXL_INIT_GC(ctx);
1434 int i;
1435 char *vm_path;
1436 char *dmargs, *path;
1437 int dmargs_size;
1438 struct xs_permissions roperm[2];
1439 xs_transaction_t t;
1441 roperm[0].id = 0;
1442 roperm[0].perms = XS_PERM_NONE;
1443 roperm[1].id = domid;
1444 roperm[1].perms = XS_PERM_READ;
1446 vm_path = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/%d/vm", guest_domid));
1448 i = 0;
1449 dmargs_size = 0;
1450 while (args[i] != NULL) {
1451 dmargs_size = dmargs_size + strlen(args[i]) + 1;
1452 i++;
1454 dmargs_size++;
1455 dmargs = (char *) malloc(dmargs_size);
1456 i = 1;
1457 dmargs[0] = '\0';
1458 while (args[i] != NULL) {
1459 if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) {
1460 strcat(dmargs, " ");
1461 strcat(dmargs, args[i]);
1463 i++;
1465 path = libxl__sprintf(&gc, "%s/image/dmargs", vm_path);
1467 retry_transaction:
1468 t = xs_transaction_start(ctx->xsh);
1469 xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs));
1470 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
1471 xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm));
1472 if (!xs_transaction_end(ctx->xsh, t, 0))
1473 if (errno == EAGAIN)
1474 goto retry_transaction;
1475 free(dmargs);
1476 libxl__free_all(&gc);
1477 return 0;
1480 static int libxl_create_stubdom(libxl_ctx *ctx,
1481 libxl_device_model_info *info,
1482 libxl_device_disk *disks, int num_disks,
1483 libxl_device_nic *vifs, int num_vifs,
1484 libxl_device_vfb *vfb,
1485 libxl_device_vkb *vkb,
1486 libxl_device_model_starting **starting_r)
1488 libxl_gc gc = LIBXL_INIT_GC(ctx);
1489 int i, num_console = 1, ret;
1490 libxl_device_console *console;
1491 libxl_domain_create_info c_info;
1492 libxl_domain_build_info b_info;
1493 libxl_domain_build_state state;
1494 uint32_t domid;
1495 char **args;
1496 struct xs_permissions perm[2];
1497 xs_transaction_t t;
1498 libxl_device_model_starting *dm_starting = 0;
1500 args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
1501 if (!args) {
1502 ret = ERROR_FAIL;
1503 goto out;
1506 memset(&c_info, 0x00, sizeof(libxl_domain_create_info));
1507 c_info.hvm = 0;
1508 c_info.name = libxl__sprintf(&gc, "%s-dm", libxl__domid_to_name(&gc, info->domid));
1510 libxl_uuid_copy(&c_info.uuid, &info->uuid);
1512 memset(&b_info, 0x00, sizeof(libxl_domain_build_info));
1513 b_info.max_vcpus = 1;
1514 b_info.max_memkb = 32 * 1024;
1515 b_info.target_memkb = b_info.max_memkb;
1516 b_info.kernel.path = libxl__abs_path(&gc, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path());
1517 b_info.u.pv.cmdline = libxl__sprintf(&gc, " -d %d", info->domid);
1518 b_info.u.pv.ramdisk.path = "";
1519 b_info.u.pv.features = "";
1520 b_info.hvm = 0;
1522 ret = libxl_domain_make(ctx, &c_info, &domid);
1523 if (ret)
1524 goto out_free;
1525 ret = libxl_domain_build(ctx, &b_info, domid, &state);
1526 if (ret)
1527 goto out_free;
1529 libxl_write_dmargs(ctx, domid, info->domid, args);
1530 libxl__xs_write(&gc, XBT_NULL,
1531 libxl__sprintf(&gc, "%s/image/device-model-domid", libxl__xs_get_dompath(&gc, info->domid)),
1532 "%d", domid);
1533 libxl__xs_write(&gc, XBT_NULL,
1534 libxl__sprintf(&gc, "%s/target", libxl__xs_get_dompath(&gc, domid)),
1535 "%d", info->domid);
1536 ret = xc_domain_set_target(ctx->xch, domid, info->domid);
1537 if (ret<0) {
1538 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting target domain %d -> %d", domid, info->domid);
1539 ret = ERROR_FAIL;
1540 goto out_free;
1542 xs_set_target(ctx->xsh, domid, info->domid);
1544 perm[0].id = domid;
1545 perm[0].perms = XS_PERM_NONE;
1546 perm[1].id = info->domid;
1547 perm[1].perms = XS_PERM_READ;
1548 retry_transaction:
1549 t = xs_transaction_start(ctx->xsh);
1550 xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid));
1551 xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm));
1552 xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs", domid));
1553 xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm));
1554 if (!xs_transaction_end(ctx->xsh, t, 0))
1555 if (errno == EAGAIN)
1556 goto retry_transaction;
1558 for (i = 0; i < num_disks; i++) {
1559 disks[i].domid = domid;
1560 ret = libxl_device_disk_add(ctx, domid, &disks[i]);
1561 if (ret)
1562 goto out_free;
1564 for (i = 0; i < num_vifs; i++) {
1565 vifs[i].domid = domid;
1566 ret = libxl_device_nic_add(ctx, domid, &vifs[i]);
1567 if (ret)
1568 goto out_free;
1570 vfb->domid = domid;
1571 ret = libxl_device_vfb_add(ctx, domid, vfb);
1572 if (ret)
1573 goto out_free;
1574 vkb->domid = domid;
1575 ret = libxl_device_vkb_add(ctx, domid, vkb);
1576 if (ret)
1577 goto out_free;
1579 if (info->serial)
1580 num_console++;
1582 console = libxl__calloc(&gc, num_console, sizeof(libxl_device_console));
1583 if (!console) {
1584 ret = ERROR_NOMEM;
1585 goto out_free;
1588 for (i = 0; i < num_console; i++) {
1589 console[i].devid = i;
1590 console[i].consback = LIBXL_CONSBACK_IOEMU;
1591 console[i].domid = domid;
1592 if (!i) {
1593 char *filename;
1594 char *name = libxl__sprintf(&gc, "qemu-dm-%s", libxl_domid_to_name(ctx, info->domid));
1595 libxl_create_logfile(ctx, name, &filename);
1596 console[i].output = libxl__sprintf(&gc, "file:%s", filename);
1597 console[i].build_state = &state;
1598 free(filename);
1599 } else
1600 console[i].output = "pty";
1601 ret = libxl_device_console_add(ctx, domid, &console[i]);
1602 if (ret)
1603 goto out_free;
1605 if (libxl_create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) {
1606 ret = ERROR_FAIL;
1607 goto out_free;
1609 if (libxl_confirm_device_model_startup(ctx, dm_starting) < 0) {
1610 ret = ERROR_FAIL;
1611 goto out_free;
1614 libxl_domain_unpause(ctx, domid);
1616 if (starting_r) {
1617 *starting_r = calloc(sizeof(libxl_device_model_starting), 1);
1618 (*starting_r)->domid = info->domid;
1619 (*starting_r)->dom_path = libxl__xs_get_dompath(&gc, info->domid);
1620 (*starting_r)->for_spawn = NULL;
1623 ret = 0;
1625 out_free:
1626 free(args);
1627 out:
1628 libxl__free_all(&gc);
1629 return ret;
1632 int libxl_create_device_model(libxl_ctx *ctx,
1633 libxl_device_model_info *info,
1634 libxl_device_disk *disks, int num_disks,
1635 libxl_device_nic *vifs, int num_vifs,
1636 libxl_device_model_starting **starting_r)
1638 libxl_gc gc = LIBXL_INIT_GC(ctx);
1639 char *path, *logfile;
1640 int logfile_w, null;
1641 int rc;
1642 char **args;
1643 libxl_device_model_starting buf_starting, *p;
1644 xs_transaction_t t;
1645 char *vm_path;
1646 char **pass_stuff;
1648 if (strstr(info->device_model, "stubdom-dm")) {
1649 libxl_device_vfb vfb;
1650 libxl_device_vkb vkb;
1652 libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb);
1653 rc = libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r);
1654 goto out;
1657 args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
1658 if (!args) {
1659 rc = ERROR_FAIL;
1660 goto out;
1663 path = libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid);
1664 xs_mkdir(ctx->xsh, XBT_NULL, path);
1665 libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/disable_pf", path), "%d", !info->xen_platform_pci);
1667 libxl_create_logfile(ctx, libxl__sprintf(&gc, "qemu-dm-%s", info->dom_name), &logfile);
1668 logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
1669 free(logfile);
1670 null = open("/dev/null", O_RDONLY);
1672 if (starting_r) {
1673 rc = ERROR_NOMEM;
1674 *starting_r = calloc(sizeof(libxl_device_model_starting), 1);
1675 if (!*starting_r)
1676 goto out_close;
1677 p = *starting_r;
1678 p->for_spawn = calloc(sizeof(libxl_spawn_starting), 1);
1679 } else {
1680 p = &buf_starting;
1681 p->for_spawn = NULL;
1684 p->domid = info->domid;
1685 p->dom_path = libxl__xs_get_dompath(&gc, info->domid);
1686 if (!p->dom_path) {
1687 rc = ERROR_FAIL;
1688 goto out_close;
1691 if (info->vncpasswd) {
1692 retry_transaction:
1693 /* Find uuid and the write the vnc password to xenstore for qemu. */
1694 t = xs_transaction_start(ctx->xsh);
1695 vm_path = libxl__xs_read(&gc,t,libxl__sprintf(&gc, "%s/vm", p->dom_path));
1696 if (vm_path) {
1697 /* Now write the vncpassword into it. */
1698 pass_stuff = libxl__calloc(&gc, 2, sizeof(char *));
1699 pass_stuff[0] = "vncpasswd";
1700 pass_stuff[1] = info->vncpasswd;
1701 libxl__xs_writev(&gc,t,vm_path,pass_stuff);
1702 if (!xs_transaction_end(ctx->xsh, t, 0))
1703 if (errno == EAGAIN)
1704 goto retry_transaction;
1708 rc = libxl__spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid);
1709 if (rc < 0)
1710 goto out_close;
1711 if (!rc) { /* inner child */
1712 libxl__exec(null, logfile_w, logfile_w,
1713 libxl__abs_path(&gc, info->device_model, libxl_private_bindir_path()),
1714 args);
1717 rc = 0;
1719 out_close:
1720 close(null);
1721 close(logfile_w);
1722 free(args);
1723 out:
1724 libxl__free_all(&gc);
1725 return rc;
1728 int libxl_detach_device_model(libxl_ctx *ctx,
1729 libxl_device_model_starting *starting)
1731 int rc;
1732 rc = libxl__spawn_detach(ctx, starting->for_spawn);
1733 if (starting->for_spawn)
1734 free(starting->for_spawn);
1735 free(starting);
1736 return rc;
1740 int libxl_confirm_device_model_startup(libxl_ctx *ctx,
1741 libxl_device_model_starting *starting)
1743 int problem = libxl__wait_for_device_model(ctx, starting->domid, "running", NULL, NULL);
1744 int detach;
1745 if ( !problem )
1746 problem = libxl__spawn_check(ctx, starting->for_spawn);
1747 detach = libxl_detach_device_model(ctx, starting);
1748 return problem ? problem : detach;
1752 /******************************************************************************/
1754 int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
1756 libxl_gc gc = LIBXL_INIT_GC(ctx);
1757 flexarray_t *front;
1758 flexarray_t *back;
1759 char *backend_type;
1760 unsigned int boffset = 0;
1761 unsigned int foffset = 0;
1762 int devid;
1763 libxl_device device;
1764 int major, minor, rc;
1766 front = flexarray_make(16, 1);
1767 if (!front) {
1768 rc = ERROR_NOMEM;
1769 goto out;
1771 back = flexarray_make(16, 1);
1772 if (!back) {
1773 rc = ERROR_NOMEM;
1774 goto out_free;
1777 backend_type = libxl__device_disk_backend_type_of_phystype(disk->phystype);
1778 devid = libxl__device_disk_dev_number(disk->virtpath);
1779 if (devid==-1) {
1780 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Invalid or unsupported"
1781 " virtual disk identifier %s", disk->virtpath);
1782 rc = ERROR_INVAL;
1783 goto out_free;
1786 device.backend_devid = devid;
1787 device.backend_domid = disk->backend_domid;
1788 device.devid = devid;
1789 device.domid = disk->domid;
1790 device.kind = DEVICE_VBD;
1792 switch (disk->phystype) {
1793 case PHYSTYPE_PHY: {
1795 libxl__device_physdisk_major_minor(disk->physpath, &major, &minor);
1796 flexarray_set(back, boffset++, "physical-device");
1797 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%x:%x", major, minor));
1799 flexarray_set(back, boffset++, "params");
1800 flexarray_set(back, boffset++, disk->physpath);
1802 device.backend_kind = DEVICE_VBD;
1803 break;
1805 case PHYSTYPE_FILE:
1806 /* let's pretend is tap:aio for the moment */
1807 disk->phystype = PHYSTYPE_AIO;
1808 case PHYSTYPE_AIO:
1809 case PHYSTYPE_QCOW:
1810 case PHYSTYPE_QCOW2:
1811 case PHYSTYPE_VHD:
1812 if (libxl__blktap_enabled(&gc)) {
1813 const char *dev = libxl__blktap_devpath(&gc,
1814 disk->physpath, disk->phystype);
1815 if (!dev) {
1816 rc = ERROR_FAIL;
1817 goto out_free;
1819 flexarray_set(back, boffset++, "tapdisk-params");
1820 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%s:%s", libxl__device_disk_string_of_phystype(disk->phystype), disk->physpath));
1821 flexarray_set(back, boffset++, "params");
1822 flexarray_set(back, boffset++, libxl__strdup(&gc, dev));
1823 backend_type = "phy";
1824 libxl__device_physdisk_major_minor(dev, &major, &minor);
1825 flexarray_set(back, boffset++, "physical-device");
1826 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%x:%x", major, minor));
1827 device.backend_kind = DEVICE_VBD;
1829 break;
1831 flexarray_set(back, boffset++, "params");
1832 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%s:%s",
1833 libxl__device_disk_string_of_phystype(disk->phystype), disk->physpath));
1835 device.backend_kind = DEVICE_TAP;
1836 break;
1838 default:
1839 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk physical type: %d\n", disk->phystype);
1840 rc = ERROR_INVAL;
1841 goto out_free;
1844 flexarray_set(back, boffset++, "frontend-id");
1845 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", disk->domid));
1846 flexarray_set(back, boffset++, "online");
1847 flexarray_set(back, boffset++, "1");
1848 flexarray_set(back, boffset++, "removable");
1849 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", (disk->unpluggable) ? 1 : 0));
1850 flexarray_set(back, boffset++, "bootable");
1851 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", 1));
1852 flexarray_set(back, boffset++, "state");
1853 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", 1));
1854 flexarray_set(back, boffset++, "dev");
1855 flexarray_set(back, boffset++, disk->virtpath);
1856 flexarray_set(back, boffset++, "type");
1857 flexarray_set(back, boffset++, backend_type);
1858 flexarray_set(back, boffset++, "mode");
1859 flexarray_set(back, boffset++, disk->readwrite ? "w" : "r");
1861 flexarray_set(front, foffset++, "backend-id");
1862 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", disk->backend_domid));
1863 flexarray_set(front, foffset++, "state");
1864 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", 1));
1865 flexarray_set(front, foffset++, "virtual-device");
1866 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", devid));
1867 flexarray_set(front, foffset++, "device-type");
1868 flexarray_set(front, foffset++, disk->is_cdrom ? "cdrom" : "disk");
1870 if (0 /* protocol != native*/) {
1871 flexarray_set(front, foffset++, "protocol");
1872 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
1875 libxl__device_generic_add(ctx, &device,
1876 libxl__xs_kvs_of_flexarray(&gc, back, boffset),
1877 libxl__xs_kvs_of_flexarray(&gc, front, foffset));
1879 rc = 0;
1881 out_free:
1882 flexarray_free(back);
1883 flexarray_free(front);
1884 out:
1885 libxl__free_all(&gc);
1886 return rc;
1889 int libxl_device_disk_del(libxl_ctx *ctx,
1890 libxl_device_disk *disk, int wait)
1892 libxl_device device;
1893 int devid;
1895 devid = libxl__device_disk_dev_number(disk->virtpath);
1896 device.backend_domid = disk->backend_domid;
1897 device.backend_devid = devid;
1898 device.backend_kind =
1899 (disk->phystype == PHYSTYPE_PHY) ? DEVICE_VBD : DEVICE_TAP;
1900 device.domid = disk->domid;
1901 device.devid = devid;
1902 device.kind = DEVICE_VBD;
1903 return libxl__device_del(ctx, &device, wait);
1906 char * libxl_device_disk_local_attach(libxl_ctx *ctx, libxl_device_disk *disk)
1908 libxl_gc gc = LIBXL_INIT_GC(ctx);
1909 const char *dev = NULL;
1910 char *ret;
1911 int phystype = disk->phystype;
1912 switch (phystype) {
1913 case PHYSTYPE_PHY: {
1914 fprintf(stderr, "attaching PHY disk %s to domain 0\n", disk->physpath);
1915 dev = disk->physpath;
1916 break;
1918 case PHYSTYPE_FILE:
1919 /* let's pretend is tap:aio for the moment */
1920 phystype = PHYSTYPE_AIO;
1921 case PHYSTYPE_AIO:
1922 case PHYSTYPE_QCOW:
1923 case PHYSTYPE_QCOW2:
1924 case PHYSTYPE_VHD:
1925 if (libxl__blktap_enabled(&gc))
1926 dev = libxl__blktap_devpath(&gc, disk->physpath, phystype);
1927 break;
1929 default:
1930 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk physical type: %d\n", phystype);
1931 break;
1933 ret = strdup(dev);
1934 libxl__free_all(&gc);
1935 return ret;
1938 int libxl_device_disk_local_detach(libxl_ctx *ctx, libxl_device_disk *disk)
1940 /* Nothing to do for PHYSTYPE_PHY. */
1942 /*
1943 * For other device types assume that the blktap2 process is
1944 * needed by the soon to be started domain and do nothing.
1945 */
1947 return 0;
1950 /******************************************************************************/
1951 int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
1953 libxl_gc gc = LIBXL_INIT_GC(ctx);
1954 flexarray_t *front;
1955 flexarray_t *back;
1956 unsigned int boffset = 0;
1957 unsigned int foffset = 0;
1958 libxl_device device;
1959 char *dompath, **l;
1960 unsigned int nb, rc;
1962 front = flexarray_make(16, 1);
1963 if (!front) {
1964 rc = ERROR_NOMEM;
1965 goto out;
1967 back = flexarray_make(16, 1);
1968 if (!back) {
1969 rc = ERROR_NOMEM;
1970 goto out_free;
1973 if (nic->devid == -1) {
1974 if (!(dompath = libxl__xs_get_dompath(&gc, domid))) {
1975 rc = ERROR_FAIL;
1976 goto out_free;
1978 if (!(l = libxl__xs_directory(&gc, XBT_NULL,
1979 libxl__sprintf(&gc, "%s/device/vif", dompath), &nb))) {
1980 nic->devid = 0;
1981 } else {
1982 nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
1986 device.backend_devid = nic->devid;
1987 device.backend_domid = nic->backend_domid;
1988 device.backend_kind = DEVICE_VIF;
1989 device.devid = nic->devid;
1990 device.domid = nic->domid;
1991 device.kind = DEVICE_VIF;
1993 flexarray_set(back, boffset++, "frontend-id");
1994 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", nic->domid));
1995 flexarray_set(back, boffset++, "online");
1996 flexarray_set(back, boffset++, "1");
1997 flexarray_set(back, boffset++, "state");
1998 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", 1));
1999 flexarray_set(back, boffset++, "script");
2000 flexarray_set(back, boffset++, nic->script);
2001 flexarray_set(back, boffset++, "mac");
2002 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
2003 nic->mac[0], nic->mac[1], nic->mac[2],
2004 nic->mac[3], nic->mac[4], nic->mac[5]));
2005 flexarray_set(back, boffset++, "bridge");
2006 flexarray_set(back, boffset++, libxl__strdup(&gc, nic->bridge));
2007 flexarray_set(back, boffset++, "handle");
2008 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", nic->devid));
2010 flexarray_set(front, foffset++, "backend-id");
2011 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", nic->backend_domid));
2012 flexarray_set(front, foffset++, "state");
2013 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", 1));
2014 flexarray_set(front, foffset++, "handle");
2015 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", nic->devid));
2016 flexarray_set(front, foffset++, "mac");
2017 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
2018 nic->mac[0], nic->mac[1], nic->mac[2],
2019 nic->mac[3], nic->mac[4], nic->mac[5]));
2020 if (0 /* protocol != native*/) {
2021 flexarray_set(front, foffset++, "protocol");
2022 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
2025 libxl__device_generic_add(ctx, &device,
2026 libxl__xs_kvs_of_flexarray(&gc, back, boffset),
2027 libxl__xs_kvs_of_flexarray(&gc, front, foffset));
2029 /* FIXME: wait for plug */
2030 rc = 0;
2031 out_free:
2032 flexarray_free(back);
2033 flexarray_free(front);
2034 out:
2035 libxl__free_all(&gc);
2036 return rc;
2039 int libxl_device_nic_del(libxl_ctx *ctx,
2040 libxl_device_nic *nic, int wait)
2042 libxl_device device;
2044 device.backend_devid = nic->devid;
2045 device.backend_domid = nic->backend_domid;
2046 device.backend_kind = DEVICE_VIF;
2047 device.devid = nic->devid;
2048 device.domid = nic->domid;
2049 device.kind = DEVICE_VIF;
2051 return libxl__device_del(ctx, &device, wait);
2054 libxl_nicinfo *libxl_list_nics(libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
2056 libxl_gc gc = LIBXL_INIT_GC(ctx);
2057 char *dompath, *nic_path_fe;
2058 char **l, **list;
2059 char *val, *tok;
2060 unsigned int nb_nics, i;
2061 libxl_nicinfo *res, *nics;
2063 dompath = libxl__xs_get_dompath(&gc, domid);
2064 if (!dompath)
2065 goto err;
2066 list = l = libxl__xs_directory(&gc, XBT_NULL,
2067 libxl__sprintf(&gc, "%s/device/vif", dompath), &nb_nics);
2068 if (!l)
2069 goto err;
2070 nics = res = calloc(nb_nics, sizeof (libxl_device_nic));
2071 if (!res)
2072 goto err;
2073 for (*nb = nb_nics; nb_nics > 0; --nb_nics, ++l, ++nics) {
2074 nic_path_fe = libxl__sprintf(&gc, "%s/device/vif/%s", dompath, *l);
2076 nics->backend = xs_read(ctx->xsh, XBT_NULL,
2077 libxl__sprintf(&gc, "%s/backend", nic_path_fe), NULL);
2078 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend-id", nic_path_fe));
2079 nics->backend_id = val ? strtoul(val, NULL, 10) : -1;
2081 nics->devid = strtoul(*l, NULL, 10);
2082 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/state", nic_path_fe));
2083 nics->state = val ? strtoul(val, NULL, 10) : -1;
2084 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/mac", nic_path_fe));
2085 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
2086 ++i, tok = strtok(NULL, ":")) {
2087 nics->mac[i] = strtoul(tok, NULL, 16);
2089 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/event-channel", nic_path_fe));
2090 nics->evtch = val ? strtol(val, NULL, 10) : -1;
2091 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/tx-ring-ref", nic_path_fe));
2092 nics->rref_tx = val ? strtol(val, NULL, 10) : -1;
2093 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/rx-ring-ref", nic_path_fe));
2094 nics->rref_rx = val ? strtol(val, NULL, 10) : -1;
2095 nics->frontend = xs_read(ctx->xsh, XBT_NULL,
2096 libxl__sprintf(&gc, "%s/frontend", nics->backend), NULL);
2097 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/frontend-id", nics->backend));
2098 nics->frontend_id = val ? strtoul(val, NULL, 10) : -1;
2099 nics->script = xs_read(ctx->xsh, XBT_NULL,
2100 libxl__sprintf(&gc, "%s/script", nics->backend), NULL);
2103 libxl__free_all(&gc);
2104 return res;
2105 err:
2106 libxl__free_all(&gc);
2107 return NULL;
2110 /******************************************************************************/
2111 int libxl_device_net2_add(libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2)
2113 libxl_gc gc = LIBXL_INIT_GC(ctx);
2114 flexarray_t *front, *back;
2115 unsigned int boffset = 0, foffset = 0;
2116 libxl_device device;
2117 char *dompath, *dom, **l;
2118 unsigned int nb;
2119 int rc;
2121 front = flexarray_make(16, 1);
2122 if (!front) {
2123 rc = ERROR_NOMEM;
2124 goto err;
2126 back = flexarray_make(16, 1);
2127 if (!back) {
2128 rc = ERROR_NOMEM;
2129 goto err_free;
2132 if (!(dompath = libxl__xs_get_dompath(&gc, domid))) {
2133 rc = ERROR_FAIL;
2134 goto err_free;
2136 dom = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/name", dompath));
2138 if (net2->devid == -1) {
2139 if (!(l = libxl__xs_directory(&gc, XBT_NULL,
2140 libxl__sprintf(&gc, "%s/device/vif2", dompath), &nb))) {
2141 net2->devid = 0;
2142 } else {
2143 net2->devid = strtoul(l[nb - 1], NULL, 10) + 1;
2147 device.backend_devid = net2->devid;
2148 device.backend_domid = net2->backend_domid;
2149 device.backend_kind = DEVICE_VIF2;
2150 device.devid = net2->devid;
2151 device.domid = net2->domid;
2152 device.kind = DEVICE_VIF2;
2154 flexarray_set(back, boffset++, "domain");
2155 flexarray_set(back, boffset++, dom);
2156 flexarray_set(back, boffset++, "frontend-id");
2157 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", net2->domid));
2159 flexarray_set(back, boffset++, "local-trusted");
2160 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", net2->back_trusted));
2161 flexarray_set(back, boffset++, "mac");
2162 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
2163 net2->back_mac[0], net2->back_mac[1],
2164 net2->back_mac[2], net2->back_mac[3],
2165 net2->back_mac[4], net2->back_mac[5]));
2167 flexarray_set(back, boffset++, "remote-trusted");
2168 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", net2->trusted));
2169 flexarray_set(back, boffset++, "remote-mac");
2170 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
2171 net2->front_mac[0], net2->front_mac[1],
2172 net2->front_mac[2], net2->front_mac[3],
2173 net2->front_mac[4], net2->front_mac[5]));
2175 flexarray_set(back, boffset++, "max-bypasses");
2176 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", net2->max_bypasses));
2177 flexarray_set(back, boffset++, "filter-mac");
2178 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", !!(net2->filter_mac)));
2179 flexarray_set(back, boffset++, "handle");
2180 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", net2->devid));
2181 flexarray_set(back, boffset++, "online");
2182 flexarray_set(back, boffset++, "1");
2183 flexarray_set(back, boffset++, "state");
2184 flexarray_set(back, boffset++, "1");
2186 flexarray_set(front, foffset++, "backend-id");
2187 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", net2->backend_domid));
2189 flexarray_set(front, foffset++, "local-trusted");
2190 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", net2->trusted));
2191 flexarray_set(front, foffset++, "mac");
2192 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
2193 net2->front_mac[0], net2->front_mac[1],
2194 net2->front_mac[2], net2->front_mac[3],
2195 net2->front_mac[4], net2->front_mac[5]));
2197 flexarray_set(front, foffset++, "remote-trusted");
2198 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", net2->back_trusted));
2199 flexarray_set(front, foffset++, "remote-mac");
2200 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
2201 net2->back_mac[0], net2->back_mac[1],
2202 net2->back_mac[2], net2->back_mac[3],
2203 net2->back_mac[4], net2->back_mac[5]));
2205 flexarray_set(front, foffset++, "filter-mac");
2206 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", !!(net2->filter_mac)));
2207 flexarray_set(front, foffset++, "state");
2208 flexarray_set(front, foffset++, "1");
2210 libxl__device_generic_add(ctx, &device,
2211 libxl__xs_kvs_of_flexarray(&gc, back, boffset),
2212 libxl__xs_kvs_of_flexarray(&gc, front, foffset));
2214 /* FIXME: wait for plug */
2215 rc = 0;
2216 err_free:
2217 flexarray_free(back);
2218 flexarray_free(front);
2219 err:
2220 libxl__free_all(&gc);
2221 return rc;
2224 libxl_net2info *libxl_device_net2_list(libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
2226 libxl_gc gc = LIBXL_INIT_GC(ctx);
2227 char *dompath, *net2_path_fe;
2228 char **l;
2229 char *val, *tok;
2230 unsigned int nb_net2s, i;
2231 libxl_net2info *res, *net2s;
2233 dompath = libxl__xs_get_dompath(&gc, domid);
2234 if (!dompath)
2235 goto err;
2236 l = libxl__xs_directory(&gc, XBT_NULL,
2237 libxl__sprintf(&gc, "%s/device/vif2", dompath), &nb_net2s);
2238 if (!l)
2239 goto err;
2240 res = calloc(nb_net2s, sizeof (libxl_net2info));
2241 if (!res)
2242 goto err;
2243 net2s = res;
2244 for (*nb = nb_net2s; nb_net2s > 0; --nb_net2s, ++l, ++net2s) {
2245 net2_path_fe = libxl__sprintf(&gc, "%s/device/vif2/%s", dompath, *l);
2247 net2s->backend = libxl__xs_read(&gc, XBT_NULL,
2248 libxl__sprintf(&gc, "%s/backend", net2_path_fe));
2249 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend-id", net2_path_fe));
2250 net2s->backend_id = val ? strtoul(val, NULL, 10) : -1;
2252 net2s->devid = strtoul(*l, NULL, 10);
2253 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/state", net2_path_fe));
2254 net2s->state = val ? strtoul(val, NULL, 10) : -1;
2256 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/mac", net2_path_fe));
2257 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
2258 ++i, tok = strtok(NULL, ":")) {
2259 net2s->mac[i] = strtoul(tok, NULL, 16);
2261 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/remote-trusted", net2_path_fe));
2262 net2s->trusted = val ? strtoul(val, NULL, 10) : -1;
2264 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/remote-mac", net2_path_fe));
2265 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
2266 ++i, tok = strtok(NULL, ":")) {
2267 net2s->back_mac[i] = strtoul(tok, NULL, 16);
2269 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/filter-mac", net2_path_fe));
2270 net2s->filter_mac = val ? strtoul(val, NULL, 10) : -1;
2272 net2s->frontend = libxl__xs_read(&gc, XBT_NULL,
2273 libxl__sprintf(&gc, "%s/frontend", net2s->backend));
2274 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/frontend-id", net2s->backend));
2275 net2s->frontend_id = val ? strtoul(val, NULL, 10) : -1;
2278 libxl__free_all(&gc);
2279 return res;
2280 err:
2281 libxl__free_all(&gc);
2282 return NULL;
2285 int libxl_device_net2_del(libxl_ctx *ctx, libxl_device_net2 *net2, int wait)
2287 libxl_device device;
2289 device.backend_devid = net2->devid;
2290 device.backend_domid = net2->backend_domid;
2291 device.backend_kind = DEVICE_VIF2;
2292 device.devid = net2->devid;
2293 device.domid = net2->domid;
2294 device.kind = DEVICE_VIF2;
2296 return libxl__device_del(ctx, &device, wait);
2300 /******************************************************************************/
2301 int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
2303 libxl_gc gc = LIBXL_INIT_GC(ctx);
2304 flexarray_t *front;
2305 flexarray_t *back;
2306 unsigned int boffset = 0;
2307 unsigned int foffset = 0;
2308 libxl_device device;
2309 int rc;
2311 if (console->build_state) {
2312 xs_transaction_t t;
2313 char **ents = (char **) libxl__calloc(&gc, 11, sizeof(char *));
2314 ents[0] = "console/port";
2315 ents[1] = libxl__sprintf(&gc, "%"PRIu32, console->build_state->console_port);
2316 ents[2] = "console/ring-ref";
2317 ents[3] = libxl__sprintf(&gc, "%lu", console->build_state->console_mfn);
2318 ents[4] = "console/limit";
2319 ents[5] = libxl__sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT);
2320 ents[6] = "console/type";
2321 if (console->consback == LIBXL_CONSBACK_XENCONSOLED)
2322 ents[7] = "xenconsoled";
2323 else
2324 ents[7] = "ioemu";
2325 ents[8] = "console/output";
2326 ents[9] = console->output;
2327 retry_transaction:
2328 t = xs_transaction_start(ctx->xsh);
2329 libxl__xs_writev(&gc, t, libxl__xs_get_dompath(&gc, console->domid), ents);
2330 if (!xs_transaction_end(ctx->xsh, t, 0))
2331 if (errno == EAGAIN)
2332 goto retry_transaction;
2335 front = flexarray_make(16, 1);
2336 if (!front) {
2337 rc = ERROR_NOMEM;
2338 goto out;
2340 back = flexarray_make(16, 1);
2341 if (!back) {
2342 rc = ERROR_NOMEM;
2343 goto out_free;
2346 device.backend_devid = console->devid;
2347 device.backend_domid = console->backend_domid;
2348 device.backend_kind = DEVICE_CONSOLE;
2349 device.devid = console->devid;
2350 device.domid = console->domid;
2351 device.kind = DEVICE_CONSOLE;
2353 flexarray_set(back, boffset++, "frontend-id");
2354 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", console->domid));
2355 flexarray_set(back, boffset++, "online");
2356 flexarray_set(back, boffset++, "1");
2357 flexarray_set(back, boffset++, "state");
2358 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", 1));
2359 flexarray_set(back, boffset++, "domain");
2360 flexarray_set(back, boffset++, libxl__domid_to_name(&gc, domid));
2361 flexarray_set(back, boffset++, "protocol");
2362 flexarray_set(back, boffset++, LIBXL_XENCONSOLE_PROTOCOL);
2364 /* if devid == 0 do not add the frontend to device/console/ because
2365 * it has already been added to console/ */
2366 if (device.devid > 0) {
2367 flexarray_set(front, foffset++, "backend-id");
2368 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", console->backend_domid));
2369 flexarray_set(front, foffset++, "state");
2370 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", 1));
2371 flexarray_set(front, foffset++, "limit");
2372 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT));
2373 flexarray_set(front, foffset++, "protocol");
2374 flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL);
2375 flexarray_set(front, foffset++, "type");
2376 if (console->consback == LIBXL_CONSBACK_XENCONSOLED)
2377 flexarray_set(front, foffset++, "xenconsoled");
2378 else
2379 flexarray_set(front, foffset++, "ioemu");
2380 flexarray_set(front, foffset++, "output");
2381 flexarray_set(front, foffset++, console->output);
2384 libxl__device_generic_add(ctx, &device,
2385 libxl__xs_kvs_of_flexarray(&gc, back, boffset),
2386 libxl__xs_kvs_of_flexarray(&gc, front, foffset));
2387 rc = 0;
2388 out_free:
2389 flexarray_free(back);
2390 flexarray_free(front);
2391 out:
2392 libxl__free_all(&gc);
2393 return rc;
2396 /******************************************************************************/
2397 int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
2399 libxl_gc gc = LIBXL_INIT_GC(ctx);
2400 flexarray_t *front;
2401 flexarray_t *back;
2402 unsigned int boffset = 0;
2403 unsigned int foffset = 0;
2404 libxl_device device;
2405 int rc;
2407 front = flexarray_make(16, 1);
2408 if (!front) {
2409 rc = ERROR_NOMEM;
2410 goto out;
2412 back = flexarray_make(16, 1);
2413 if (!back) {
2414 rc = ERROR_NOMEM;
2415 goto out_free;
2418 device.backend_devid = vkb->devid;
2419 device.backend_domid = vkb->backend_domid;
2420 device.backend_kind = DEVICE_VKBD;
2421 device.devid = vkb->devid;
2422 device.domid = vkb->domid;
2423 device.kind = DEVICE_VKBD;
2425 flexarray_set(back, boffset++, "frontend-id");
2426 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vkb->domid));
2427 flexarray_set(back, boffset++, "online");
2428 flexarray_set(back, boffset++, "1");
2429 flexarray_set(back, boffset++, "state");
2430 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", 1));
2431 flexarray_set(back, boffset++, "domain");
2432 flexarray_set(back, boffset++, libxl__domid_to_name(&gc, domid));
2434 flexarray_set(front, foffset++, "backend-id");
2435 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", vkb->backend_domid));
2436 flexarray_set(front, foffset++, "state");
2437 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", 1));
2439 libxl__device_generic_add(ctx, &device,
2440 libxl__xs_kvs_of_flexarray(&gc, back, boffset),
2441 libxl__xs_kvs_of_flexarray(&gc, front, foffset));
2442 rc = 0;
2443 out_free:
2444 flexarray_free(back);
2445 flexarray_free(front);
2446 out:
2447 libxl__free_all(&gc);
2448 return rc;
2451 int libxl_device_vkb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
2453 return ERROR_NI;
2456 int libxl_device_vkb_hard_shutdown(libxl_ctx *ctx, uint32_t domid)
2458 return ERROR_NI;
2461 libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num)
2463 libxl_gc gc = LIBXL_INIT_GC(ctx);
2464 char *be_path_tap, *be_path_vbd;
2465 libxl_device_disk *dend, *disks, *ret = NULL;
2466 char **b, **l = NULL;
2467 unsigned int numl, len;
2468 char *type;
2470 be_path_vbd = libxl__sprintf(&gc, "%s/backend/vbd/%d", libxl__xs_get_dompath(&gc, 0), domid);
2471 be_path_tap = libxl__sprintf(&gc, "%s/backend/tap/%d", libxl__xs_get_dompath(&gc, 0), domid);
2473 b = l = libxl__xs_directory(&gc, XBT_NULL, be_path_vbd, &numl);
2474 if (l) {
2475 ret = realloc(ret, sizeof(libxl_device_disk) * numl);
2476 disks = ret;
2477 *num = numl;
2478 dend = ret + *num;
2479 for (; disks < dend; ++disks, ++l) {
2480 disks->backend_domid = 0;
2481 disks->domid = domid;
2482 disks->physpath = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "%s/%s/params", be_path_vbd, *l), &len);
2483 libxl_string_to_phystype(ctx, libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/type", be_path_vbd, *l)), &(disks->phystype));
2484 disks->virtpath = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "%s/%s/dev", be_path_vbd, *l), &len);
2485 disks->unpluggable = atoi(libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/removable", be_path_vbd, *l)));
2486 if (!strcmp(libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/mode", be_path_vbd, *l)), "w"))
2487 disks->readwrite = 1;
2488 else
2489 disks->readwrite = 0;
2490 type = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/device-type", libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/frontend", be_path_vbd, *l))));
2491 disks->is_cdrom = !strcmp(type, "cdrom");
2494 b = l = libxl__xs_directory(&gc, XBT_NULL, be_path_tap, &numl);
2495 if (l) {
2496 ret = realloc(ret, sizeof(libxl_device_disk) * (*num + numl));
2497 disks = ret + *num;
2498 *num += numl;
2499 for (dend = ret + *num; disks < dend; ++disks, ++l) {
2500 disks->backend_domid = 0;
2501 disks->domid = domid;
2502 disks->physpath = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "%s/%s/params", be_path_tap, *l), &len);
2503 libxl_string_to_phystype(ctx, libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/type", be_path_tap, *l)), &(disks->phystype));
2504 disks->virtpath = xs_read(ctx->xsh, XBT_NULL, libxl__sprintf(&gc, "%s/%s/dev", be_path_tap, *l), &len);
2505 disks->unpluggable = atoi(libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/removable", be_path_tap, *l)));
2506 if (!strcmp(libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/mode", be_path_tap, *l)), "w"))
2507 disks->readwrite = 1;
2508 else
2509 disks->readwrite = 0;
2510 type = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/device-type", libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/%s/frontend", be_path_tap, *l))));
2511 disks->is_cdrom = !strcmp(type, "cdrom");
2514 libxl__free_all(&gc);
2515 return ret;
2518 int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
2519 libxl_device_disk *disk, libxl_diskinfo *diskinfo)
2521 libxl_gc gc = LIBXL_INIT_GC(ctx);
2522 char *dompath, *diskpath;
2523 char *val;
2525 dompath = libxl__xs_get_dompath(&gc, domid);
2526 diskinfo->devid = libxl__device_disk_dev_number(disk->virtpath);
2528 /* tap devices entries in xenstore are written as vbd devices. */
2529 diskpath = libxl__sprintf(&gc, "%s/device/vbd/%d", dompath, diskinfo->devid);
2530 diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
2531 libxl__sprintf(&gc, "%s/backend", diskpath), NULL);
2532 if (!diskinfo->backend) {
2533 libxl__free_all(&gc);
2534 return ERROR_FAIL;
2536 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/backend-id", diskpath));
2537 diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
2538 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/state", diskpath));
2539 diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
2540 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/event-channel", diskpath));
2541 diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
2542 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/ring-ref", diskpath));
2543 diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
2544 diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
2545 libxl__sprintf(&gc, "%s/frontend", diskinfo->backend), NULL);
2546 val = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/frontend-id", diskinfo->backend));
2547 diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
2549 libxl__free_all(&gc);
2550 return 0;
2553 int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
2555 int num, i;
2556 uint32_t stubdomid;
2557 libxl_device_disk *disks;
2558 int ret = ERROR_FAIL;
2560 if (!disk->physpath) {
2561 disk->physpath = "";
2562 disk->phystype = PHYSTYPE_PHY;
2564 disks = libxl_device_disk_list(ctx, domid, &num);
2565 for (i = 0; i < num; i++) {
2566 if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath))
2567 /* found */
2568 break;
2570 if (i == num) {
2571 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Virtual device not found");
2572 goto out;
2575 ret = 0;
2577 libxl_device_disk_del(ctx, disks + i, 1);
2578 libxl_device_disk_add(ctx, domid, disk);
2579 stubdomid = libxl_get_stubdom_id(ctx, domid);
2580 if (stubdomid) {
2581 disks[i].domid = stubdomid;
2582 libxl_device_disk_del(ctx, disks + i, 1);
2583 disk->domid = stubdomid;
2584 libxl_device_disk_add(ctx, stubdomid, disk);
2585 disk->domid = domid;
2587 out:
2588 for (i = 0; i < num; i++)
2589 libxl_device_disk_destroy(&disks[i]);
2590 free(disks);
2591 return ret;
2594 /******************************************************************************/
2595 static int libxl_build_xenpv_qemu_args(libxl_gc *gc,
2596 uint32_t domid,
2597 libxl_device_vfb *vfb,
2598 libxl_device_model_info *info)
2600 libxl_ctx *ctx = libxl_gc_owner(gc);
2601 memset(info, 0x00, sizeof(libxl_device_model_info));
2603 if (vfb != NULL) {
2604 info->vnc = vfb->vnc;
2605 if (vfb->vnclisten)
2606 info->vnclisten = libxl__strdup(gc, vfb->vnclisten);
2607 info->vncdisplay = vfb->vncdisplay;
2608 info->vncunused = vfb->vncunused;
2609 if (vfb->vncpasswd)
2610 info->vncpasswd = vfb->vncpasswd;
2611 if (vfb->keymap)
2612 info->keymap = libxl__strdup(gc, vfb->keymap);
2613 info->sdl = vfb->sdl;
2614 info->opengl = vfb->opengl;
2615 } else
2616 info->nographic = 1;
2617 info->domid = domid;
2618 info->dom_name = libxl_domid_to_name(ctx, domid);
2619 info->device_model = libxl__abs_path(gc, "qemu-dm", libxl_libexec_path());
2620 info->type = XENPV;
2621 return 0;
2624 int libxl_create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb,
2625 libxl_device_model_starting **starting_r)
2627 libxl_gc gc = LIBXL_INIT_GC(ctx);
2628 libxl_device_model_info info;
2630 libxl_build_xenpv_qemu_args(&gc, domid, vfb, &info);
2631 libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r);
2632 libxl__free_all(&gc);
2633 return 0;
2636 int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
2638 libxl_gc gc = LIBXL_INIT_GC(ctx);
2639 flexarray_t *front;
2640 flexarray_t *back;
2641 unsigned int boffset = 0;
2642 unsigned int foffset = 0;
2643 libxl_device device;
2644 int rc;
2646 front = flexarray_make(16, 1);
2647 if (!front) {
2648 rc = ERROR_NOMEM;
2649 goto out;
2651 back = flexarray_make(16, 1);
2652 if (!back) {
2653 rc = ERROR_NOMEM;
2654 goto out_free;
2657 device.backend_devid = vfb->devid;
2658 device.backend_domid = vfb->backend_domid;
2659 device.backend_kind = DEVICE_VFB;
2660 device.devid = vfb->devid;
2661 device.domid = vfb->domid;
2662 device.kind = DEVICE_VFB;
2664 flexarray_set(back, boffset++, "frontend-id");
2665 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->domid));
2666 flexarray_set(back, boffset++, "online");
2667 flexarray_set(back, boffset++, "1");
2668 flexarray_set(back, boffset++, "state");
2669 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", 1));
2670 flexarray_set(back, boffset++, "domain");
2671 flexarray_set(back, boffset++, libxl__domid_to_name(&gc, domid));
2672 flexarray_set(back, boffset++, "vnc");
2673 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->vnc));
2674 flexarray_set(back, boffset++, "vnclisten");
2675 flexarray_set(back, boffset++, vfb->vnclisten);
2676 flexarray_set(back, boffset++, "vncpasswd");
2677 flexarray_set(back, boffset++, vfb->vncpasswd);
2678 flexarray_set(back, boffset++, "vncdisplay");
2679 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->vncdisplay));
2680 flexarray_set(back, boffset++, "vncunused");
2681 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->vncunused));
2682 flexarray_set(back, boffset++, "sdl");
2683 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->sdl));
2684 flexarray_set(back, boffset++, "opengl");
2685 flexarray_set(back, boffset++, libxl__sprintf(&gc, "%d", vfb->opengl));
2686 if (vfb->xauthority) {
2687 flexarray_set(back, boffset++, "xauthority");
2688 flexarray_set(back, boffset++, vfb->xauthority);
2690 if (vfb->display) {
2691 flexarray_set(back, boffset++, "display");
2692 flexarray_set(back, boffset++, vfb->display);
2695 flexarray_set(front, foffset++, "backend-id");
2696 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", vfb->backend_domid));
2697 flexarray_set(front, foffset++, "state");
2698 flexarray_set(front, foffset++, libxl__sprintf(&gc, "%d", 1));
2700 libxl__device_generic_add(ctx, &device,
2701 libxl__xs_kvs_of_flexarray(&gc, back, boffset),
2702 libxl__xs_kvs_of_flexarray(&gc, front, foffset));
2703 rc = 0;
2704 out_free:
2705 flexarray_free(front);
2706 flexarray_free(back);
2707 out:
2708 libxl__free_all(&gc);
2709 return rc;
2712 int libxl_device_vfb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
2714 return ERROR_NI;
2717 int libxl_device_vfb_hard_shutdown(libxl_ctx *ctx, uint32_t domid)
2719 return ERROR_NI;
2722 /******************************************************************************/
2724 int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb)
2726 libxl_gc gc = LIBXL_INIT_GC(ctx);
2727 char *mem, *endptr;
2728 uint32_t memorykb;
2729 char *dompath = libxl__xs_get_dompath(&gc, domid);
2730 int rc = 1;
2732 mem = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/memory/target", dompath));
2733 if (!mem) {
2734 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot get memory info from %s/memory/target\n", dompath);
2735 goto out;
2737 memorykb = strtoul(mem, &endptr, 10);
2738 if (*endptr != '\0') {
2739 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "invalid memory %s from %s/memory/target\n", mem, dompath);
2740 goto out;
2743 if (max_memkb < memorykb) {
2744 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "memory_static_max must be greater than or or equal to memory_dynamic_max\n");
2745 goto out;
2748 if (domid != 0)
2749 libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/memory/static-max", dompath), "%"PRIu32, max_memkb);
2751 rc = 0;
2752 out:
2753 libxl__free_all(&gc);
2754 return rc;
2757 int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb, int enforce)
2759 libxl_gc gc = LIBXL_INIT_GC(ctx);
2760 int rc = 1;
2761 uint32_t memorykb = 0, videoram = 0;
2762 char *memmax, *endptr, *videoram_s = NULL;
2763 char *dompath = libxl__xs_get_dompath(&gc, domid);
2764 xc_domaininfo_t info;
2765 libxl_dominfo ptr;
2766 char *uuid;
2768 if (domid) {
2769 memmax = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/memory/static-max", dompath));
2770 if (!memmax) {
2771 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
2772 "cannot get memory info from %s/memory/static-max\n", dompath);
2773 goto out;
2775 memorykb = strtoul(memmax, &endptr, 10);
2776 if (*endptr != '\0') {
2777 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
2778 "invalid max memory %s from %s/memory/static-max\n", memmax, dompath);
2779 goto out;
2782 if (target_memkb > memorykb) {
2783 LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
2784 "memory_dynamic_max must be less than or equal to memory_static_max\n");
2785 goto out;
2789 videoram_s = libxl__xs_read(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/memory/videoram", dompath));
2790 videoram = videoram_s ? atoi(videoram_s) : 0;
2792 libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/memory/target", dompath), "%"PRIu32, target_memkb);
2794 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
2795 if (rc != 1 || info.domain != domid)
2796 goto out;
2797 xcinfo2xlinfo(&info, &ptr);
2798 uuid = libxl__uuid2string(&gc, ptr.uuid);
2799 libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "/vm/%s/memory", uuid), "%"PRIu32, target_memkb / 1024);
2801 if (enforce || !domid)
2802 memorykb = target_memkb;
2803 rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb + LIBXL_MAXMEM_CONSTANT);
2804 if (rc != 0)
2805 goto out;
2806 rc = xc_domain_memory_set_pod_target(ctx->xch, domid, (target_memkb - videoram) / 4, NULL, NULL, NULL);
2808 out:
2809 libxl__free_all(&gc);
2810 return rc;
2813 int libxl_button_press(libxl_ctx *ctx, uint32_t domid, libxl_button button)
2815 int rc = -1;
2817 switch (button) {
2818 case POWER_BUTTON:
2819 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_POWER, 0);
2820 break;
2821 case SLEEP_BUTTON:
2822 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_SLEEP, 0);
2823 break;
2824 default:
2825 break;
2828 return rc;
2831 int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
2833 xc_physinfo_t xcphysinfo = { 0 };
2834 int rc;
2836 rc = xc_physinfo(ctx->xch, &xcphysinfo);
2837 if (rc != 0) {
2838 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting physinfo");
2839 return ERROR_FAIL;
2841 physinfo->threads_per_core = xcphysinfo.threads_per_core;
2842 physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
2843 physinfo->max_cpu_id = xcphysinfo.max_cpu_id;
2844 physinfo->nr_cpus = xcphysinfo.nr_cpus;
2845 physinfo->cpu_khz = xcphysinfo.cpu_khz;
2846 physinfo->total_pages = xcphysinfo.total_pages;
2847 physinfo->free_pages = xcphysinfo.free_pages;
2848 physinfo->scrub_pages = xcphysinfo.scrub_pages;
2849 physinfo->nr_nodes = xcphysinfo.nr_nodes;
2850 memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap));
2851 physinfo->phys_cap = xcphysinfo.capabilities;
2853 return 0;
2856 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx)
2858 union {
2859 xen_extraversion_t xen_extra;
2860 xen_compile_info_t xen_cc;
2861 xen_changeset_info_t xen_chgset;
2862 xen_capabilities_info_t xen_caps;
2863 xen_platform_parameters_t p_parms;
2864 xen_commandline_t xen_commandline;
2865 } u;
2866 long xen_version;
2867 libxl_version_info *info = &ctx->version_info;
2869 if (info->xen_version_extra != NULL)
2870 return info;
2872 xen_version = xc_version(ctx->xch, XENVER_version, NULL);
2873 info->xen_version_major = xen_version >> 16;
2874 info->xen_version_minor = xen_version & 0xFF;
2876 xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra);
2877 info->xen_version_extra = strdup(u.xen_extra);
2879 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
2880 info->compiler = strdup(u.xen_cc.compiler);
2881 info->compile_by = strdup(u.xen_cc.compile_by);
2882 info->compile_domain = strdup(u.xen_cc.compile_domain);
2883 info->compile_date = strdup(u.xen_cc.compile_date);
2885 xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps);
2886 info->capabilities = strdup(u.xen_caps);
2888 xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset);
2889 info->changeset = strdup(u.xen_chgset);
2891 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
2892 info->virt_start = u.p_parms.virt_start;
2894 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
2896 xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline);
2897 info->commandline = strdup(u.xen_commandline);
2899 return info;
2902 libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
2903 int *nb_vcpu, int *nrcpus)
2905 libxl_vcpuinfo *ptr, *ret;
2906 xc_domaininfo_t domaininfo;
2907 xc_vcpuinfo_t vcpuinfo;
2908 xc_physinfo_t physinfo = { 0 };
2909 unsigned num_cpuwords;
2911 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
2912 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting infolist");
2913 return NULL;
2915 if (xc_physinfo(ctx->xch, &physinfo) == -1) {
2916 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting physinfo");
2917 return NULL;
2919 *nrcpus = physinfo.max_cpu_id + 1;
2920 ret = ptr = calloc(domaininfo.max_vcpu_id + 1, sizeof (libxl_vcpuinfo));
2921 if (!ptr) {
2922 return NULL;
2925 num_cpuwords = ((physinfo.max_cpu_id + 64) / 64);
2926 for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) {
2927 ptr->cpumap = malloc(num_cpuwords * sizeof(*ptr->cpumap));
2928 if (!ptr->cpumap) {
2929 return NULL;
2931 if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) {
2932 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting vcpu info");
2933 return NULL;
2935 if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu,
2936 ptr->cpumap, ((*nrcpus) + 7) / 8) == -1) {
2937 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting vcpu affinity");
2938 return NULL;
2940 ptr->vcpuid = *nb_vcpu;
2941 ptr->cpu = vcpuinfo.cpu;
2942 ptr->online = !!vcpuinfo.online;
2943 ptr->blocked = !!vcpuinfo.blocked;
2944 ptr->running = !!vcpuinfo.running;
2945 ptr->vcpu_time = vcpuinfo.cpu_time;
2947 return ret;
2950 int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
2951 uint64_t *cpumap, int nrcpus)
2953 if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap, (nrcpus + 7) / 8)) {
2954 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting vcpu affinity");
2955 return ERROR_FAIL;
2957 return 0;
2960 int libxl_set_vcpuonline(libxl_ctx *ctx, uint32_t domid, uint32_t bitmask)
2962 libxl_gc gc = LIBXL_INIT_GC(ctx);
2963 libxl_dominfo info;
2964 char *dompath;
2965 xs_transaction_t t;
2966 int i, rc = ERROR_FAIL;
2968 if (libxl_domain_info(ctx, &info, domid) < 0) {
2969 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting domain info list");
2970 goto out;
2972 if (!(dompath = libxl__xs_get_dompath(&gc, domid)))
2973 goto out;
2975 retry_transaction:
2976 t = xs_transaction_start(ctx->xsh);
2977 for (i = 0; i <= info.vcpu_max_id; i++)
2978 libxl__xs_write(&gc, t,
2979 libxl__sprintf(&gc, "%s/cpu/%u/availability", dompath, i),
2980 "%s", ((1 << i) & bitmask) ? "online" : "offline");
2981 if (!xs_transaction_end(ctx->xsh, t, 0)) {
2982 if (errno == EAGAIN)
2983 goto retry_transaction;
2984 } else
2985 rc = 0;
2986 out:
2987 libxl__free_all(&gc);
2988 return rc;
2991 /*
2992 * returns one of the XEN_SCHEDULER_* constants from public/domctl.h
2993 */
2994 int libxl_get_sched_id(libxl_ctx *ctx)
2996 int sched, ret;
2998 if ((ret = xc_sched_id(ctx->xch, &sched)) != 0) {
2999 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting domain info list");
3000 return ERROR_FAIL;
3002 return sched;
3005 int libxl_sched_credit_domain_get(libxl_ctx *ctx, uint32_t domid, libxl_sched_credit *scinfo)
3007 struct xen_domctl_sched_credit sdom;
3008 int rc;
3010 rc = xc_sched_credit_domain_get(ctx->xch, domid, &sdom);
3011 if (rc != 0) {
3012 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting domain sched credit");
3013 return ERROR_FAIL;
3016 scinfo->weight = sdom.weight;
3017 scinfo->cap = sdom.cap;
3019 return 0;
3022 int libxl_sched_credit_domain_set(libxl_ctx *ctx, uint32_t domid, libxl_sched_credit *scinfo)
3024 struct xen_domctl_sched_credit sdom;
3025 xc_domaininfo_t domaininfo;
3026 int rc;
3028 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo);
3029 if (rc < 0) {
3030 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "getting domain info list");
3031 return ERROR_FAIL;
3033 if (rc != 1 || domaininfo.domain != domid)
3034 return ERROR_INVAL;
3037 if (scinfo->weight < 1 || scinfo->weight > 65535) {
3038 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
3039 "Cpu weight out of range, valid values are within range from 1 to 65535");
3040 return ERROR_INVAL;
3043 if (scinfo->cap < 0 || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) {
3044 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
3045 "Cpu cap out of range, valid range is from 0 to %d for specified number of vcpus",
3046 ((domaininfo.max_vcpu_id + 1) * 100));
3047 return ERROR_INVAL;
3050 sdom.weight = scinfo->weight;
3051 sdom.cap = scinfo->cap;
3053 rc = xc_sched_credit_domain_set(ctx->xch, domid, &sdom);
3054 if ( rc < 0 ) {
3055 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting domain sched credit");
3056 return ERROR_FAIL;
3059 return 0;
3062 static int trigger_type_from_string(char *trigger_name)
3064 if (!strcmp(trigger_name, "nmi"))
3065 return XEN_DOMCTL_SENDTRIGGER_NMI;
3066 else if (!strcmp(trigger_name, "reset"))
3067 return XEN_DOMCTL_SENDTRIGGER_RESET;
3068 else if (!strcmp(trigger_name, "init"))
3069 return XEN_DOMCTL_SENDTRIGGER_INIT;
3070 else if (!strcmp(trigger_name, "power"))
3071 return XEN_DOMCTL_SENDTRIGGER_POWER;
3072 else if (!strcmp(trigger_name, "sleep"))
3073 return XEN_DOMCTL_SENDTRIGGER_SLEEP;
3074 else
3075 return -1;
3078 int libxl_send_trigger(libxl_ctx *ctx, uint32_t domid, char *trigger_name, uint32_t vcpuid)
3080 int rc = -1;
3081 int trigger_type = trigger_type_from_string(trigger_name);
3083 if (trigger_type == -1) {
3084 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, -1,
3085 "Invalid trigger, valid triggers are <nmi|reset|init|power|sleep>");
3086 return ERROR_INVAL;
3089 rc = xc_domain_send_trigger(ctx->xch, domid, trigger_type, vcpuid);
3090 if (rc != 0) {
3091 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
3092 "Send trigger '%s' failed", trigger_name);
3093 return ERROR_FAIL;
3096 return 0;
3099 int libxl_send_sysrq(libxl_ctx *ctx, uint32_t domid, char sysrq)
3101 libxl_gc gc = LIBXL_INIT_GC(ctx);
3102 char *dompath = libxl__xs_get_dompath(&gc, domid);
3104 libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/control/sysrq", dompath), "%c", sysrq);
3106 libxl__free_all(&gc);
3107 return 0;
3110 int libxl_send_debug_keys(libxl_ctx *ctx, char *keys)
3112 int ret;
3113 ret = xc_send_debug_keys(ctx->xch, keys);
3114 if ( ret < 0 ) {
3115 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "sending debug keys");
3116 return ERROR_FAIL;
3118 return 0;
3121 libxl_xen_console_reader *
3122 libxl_xen_console_read_start(libxl_ctx *ctx, int clear)
3124 libxl_xen_console_reader *cr;
3125 unsigned int size = 16384;
3126 char *buf = malloc(size);
3128 if (!buf) {
3129 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot malloc buffer for libxl_xen_console_reader,"
3130 " size is %u", size);
3131 return NULL;
3134 cr = malloc(sizeof(libxl_xen_console_reader));
3135 if (!cr) {
3136 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "cannot malloc libxl_xen_console_reader");
3137 return NULL;
3140 memset(cr, 0, sizeof(libxl_xen_console_reader));
3141 cr->buffer = buf;
3142 cr->size = size;
3143 cr->count = size;
3144 cr->clear = clear;
3145 cr->incremental = 1;
3147 return cr;
3150 /* return values: *line_r
3151 * 1 success, whole line obtained from buffer non-0
3152 * 0 no more lines available right now 0
3153 * negative error code ERROR_* 0
3154 * On success *line_r is updated to point to a nul-terminated
3155 * string which is valid until the next call on the same console
3156 * reader. The libxl caller may overwrite parts of the string
3157 * if it wishes. */
3158 int libxl_xen_console_read_line(libxl_ctx *ctx,
3159 libxl_xen_console_reader *cr,
3160 char **line_r)
3162 int ret;
3164 memset(cr->buffer, 0, cr->size);
3165 ret = xc_readconsolering(ctx->xch, &cr->buffer, &cr->count,
3166 cr->clear, cr->incremental, &cr->index);
3167 if (ret < 0) {
3168 LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "reading console ring buffer");
3169 return ERROR_FAIL;
3171 if (!ret) {
3172 if (cr->count) {
3173 *line_r = cr->buffer;
3174 ret = 1;
3175 } else {
3176 *line_r = NULL;
3177 ret = 0;
3181 return ret;
3184 void libxl_xen_console_read_finish(libxl_ctx *ctx,
3185 libxl_xen_console_reader *cr)
3187 free(cr->buffer);
3188 free(cr);
3191 uint32_t libxl_vm_get_start_time(libxl_ctx *ctx, uint32_t domid)
3193 libxl_gc gc = LIBXL_INIT_GC(ctx);
3194 char *dompath = libxl__xs_get_dompath(&gc, domid);
3195 char *vm_path, *start_time;
3196 uint32_t ret;
3198 vm_path = libxl__xs_read(
3199 &gc, XBT_NULL, libxl__sprintf(&gc, "%s/vm", dompath));
3200 start_time = libxl__xs_read(
3201 &gc, XBT_NULL, libxl__sprintf(&gc, "%s/start_time", vm_path));
3202 if (start_time == NULL) {
3203 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, -1,
3204 "Can't get start time of domain '%d'", domid);
3205 ret = -1;
3206 }else{
3207 ret = strtoul(start_time, NULL, 10);
3209 libxl__free_all(&gc);
3210 return ret;
3213 char *libxl_tmem_list(libxl_ctx *ctx, uint32_t domid, int use_long)
3215 int rc;
3216 char _buf[32768];
3218 rc = xc_tmem_control(ctx->xch, -1, TMEMC_LIST, domid, 32768, use_long,
3219 0, _buf);
3220 if (rc < 0) {
3221 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
3222 "Can not get tmem list");
3223 return NULL;
3226 return strdup(_buf);
3229 int libxl_tmem_freeze(libxl_ctx *ctx, uint32_t domid)
3231 int rc;
3233 rc = xc_tmem_control(ctx->xch, -1, TMEMC_FREEZE, domid, 0, 0,
3234 0, NULL);
3235 if (rc < 0) {
3236 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
3237 "Can not freeze tmem pools");
3238 return ERROR_FAIL;
3241 return rc;
3244 int libxl_tmem_destroy(libxl_ctx *ctx, uint32_t domid)
3246 int rc;
3248 rc = xc_tmem_control(ctx->xch, -1, TMEMC_DESTROY, domid, 0, 0,
3249 0, NULL);
3250 if (rc < 0) {
3251 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
3252 "Can not destroy tmem pools");
3253 return ERROR_FAIL;
3256 return rc;
3259 int libxl_tmem_thaw(libxl_ctx *ctx, uint32_t domid)
3261 int rc;
3263 rc = xc_tmem_control(ctx->xch, -1, TMEMC_THAW, domid, 0, 0,
3264 0, NULL);
3265 if (rc < 0) {
3266 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
3267 "Can not thaw tmem pools");
3268 return ERROR_FAIL;
3271 return rc;
3274 static int32_t tmem_setop_from_string(char *set_name)
3276 if (!strcmp(set_name, "weight"))
3277 return TMEMC_SET_WEIGHT;
3278 else if (!strcmp(set_name, "cap"))
3279 return TMEMC_SET_CAP;
3280 else if (!strcmp(set_name, "compress"))
3281 return TMEMC_SET_COMPRESS;
3282 else
3283 return -1;
3286 int libxl_tmem_set(libxl_ctx *ctx, uint32_t domid, char* name, uint32_t set)
3288 int rc;
3289 int32_t subop = tmem_setop_from_string(name);
3291 if (subop == -1) {
3292 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, -1,
3293 "Invalid set, valid sets are <weight|cap|compress>");
3294 return ERROR_INVAL;
3296 rc = xc_tmem_control(ctx->xch, -1, subop, domid, set, 0, 0, NULL);
3297 if (rc < 0) {
3298 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
3299 "Can not set tmem %s", name);
3300 return ERROR_FAIL;
3303 return rc;
3306 int libxl_tmem_shared_auth(libxl_ctx *ctx, uint32_t domid,
3307 char* uuid, int auth)
3309 int rc;
3311 rc = xc_tmem_auth(ctx->xch, domid, uuid, auth);
3312 if (rc < 0) {
3313 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
3314 "Can not set tmem shared auth");
3315 return ERROR_FAIL;
3318 return rc;
3321 int libxl_tmem_freeable(libxl_ctx *ctx)
3323 int rc;
3325 rc = xc_tmem_control(ctx->xch, -1, TMEMC_QUERY_FREEABLE_MB, -1, 0, 0, 0, 0);
3326 if (rc < 0) {
3327 LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc,
3328 "Can not get tmem freeable memory");
3329 return ERROR_FAIL;
3332 return rc;
3335 void libxl_file_reference_destroy(libxl_file_reference *f)
3337 libxl__file_reference_unmap(f);
3338 free(f->path);