debuggers.hg

annotate tools/libxl/libxl.c @ 21892:e23302fcb83c

libxl: consistent handling of libxc errors

Lots of places in libxl return -1 as an error which is inconsistent with
libxl error codes since that is ERROR_VERSION. Also in other places the
xc_* function to implement a command is called but the return value is
either never checked or not passed on.

This patch makes callers of libxc functions use XL_LOG_ERRNO to log a
suitable message including the contents of errno, before returning
ERROR_FAIL, if an xc call fails. (Except for pci device removals and
domain destroys where release of resources ought to continue even if
an error occurs in an early step. In this case the error is still
logged at least.)

Also a bug is fixed where a caller depends on errno being set but is
cleared by cleanup code which calls in to library functions which modify
errno as a side-effect.


This is version 2 of the patch previously applied as 91c486918e02.
Changed since then: Removed mapping from libxc error codes to libxl -
this is redundant because libxl ought to return -1 with errno set to a
meaningful value.


Signed-off-by: Gianni Tedesco <gianni.tedesco@citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
Committed-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Gianni Tedesco <gianni.tedesco@citrix.com>
date Fri Jul 23 17:26:28 2010 +0100 (2010-07-23)
parents 098dacea3ae0
children 267ddd7fa11f
rev   line source
keir@20462 1 /*
keir@20462 2 * Copyright (C) 2009 Citrix Ltd.
keir@20462 3 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
keir@20462 4 * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
keir@20462 5 *
keir@20462 6 * This program is free software; you can redistribute it and/or modify
keir@20462 7 * it under the terms of the GNU Lesser General Public License as published
keir@20462 8 * by the Free Software Foundation; version 2.1 only. with the special
keir@20462 9 * exception on linking described in file LICENSE.
keir@20462 10 *
keir@20462 11 * This program is distributed in the hope that it will be useful,
keir@20462 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
keir@20462 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
keir@20462 14 * GNU Lesser General Public License for more details.
keir@20462 15 */
keir@20462 16
keir@20513 17 #include "libxl_osdeps.h"
keir@20513 18
keir@20462 19 #include <stdio.h>
keir@20462 20 #include <string.h>
keir@20462 21 #include <stdlib.h>
keir@20462 22 #include <sys/types.h>
keir@20462 23 #include <fcntl.h>
keir@20462 24 #include <sys/select.h>
Ian@21848 25 #include <sys/mman.h>
keir@20514 26 #include <sys/wait.h>
keir@20462 27 #include <signal.h>
keir@20468 28 #include <unistd.h> /* for write, unlink and close */
keir@20509 29 #include <stdint.h>
keir@20509 30 #include <inttypes.h>
keir@20514 31 #include <assert.h>
keir@20513 32
keir@20462 33 #include "libxl.h"
keir@20462 34 #include "libxl_utils.h"
keir@20462 35 #include "libxl_internal.h"
keir@20462 36 #include "flexarray.h"
keir@20462 37
keir@20860 38 #define PAGE_TO_MEMKB(pages) ((pages) * 4)
keir@20860 39
keir@21532 40 int libxl_ctx_init(struct libxl_ctx *ctx, int version, xentoollog_logger *lg)
keir@20462 41 {
keir@20788 42 if (version != LIBXL_VERSION)
keir@20788 43 return ERROR_VERSION;
keir@20462 44 memset(ctx, 0, sizeof(struct libxl_ctx));
keir@21532 45 ctx->lg = lg;
keir@20462 46 ctx->alloc_maxsize = 256;
keir@20462 47 ctx->alloc_ptrs = calloc(ctx->alloc_maxsize, sizeof(void *));
keir@20462 48 if (!ctx->alloc_ptrs)
keir@20462 49 return ERROR_NOMEM;
keir@21266 50 memset(&ctx->version_info, 0, sizeof(libxl_version_info));
keir@20462 51
keir@21532 52 ctx->xch = xc_interface_open(lg,lg,0);
keir@21529 53 if (!ctx->xch) {
keir@21681 54 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
keir@21681 55 "cannot open libxc handle");
keir@20819 56 free(ctx->alloc_ptrs);
keir@20819 57 return ERROR_FAIL;
keir@20819 58 }
keir@20819 59
keir@20462 60 ctx->xsh = xs_daemon_open();
keir@20819 61 if (!ctx->xsh) {
keir@21681 62 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
keir@21681 63 "cannot connect to xenstore");
keir@20819 64 xc_interface_close(ctx->xch);
keir@20819 65 free(ctx->alloc_ptrs);
keir@20819 66 return ERROR_FAIL;
keir@20819 67 }
keir@20462 68 return 0;
keir@20462 69 }
keir@20462 70
keir@20462 71 int libxl_ctx_free(struct libxl_ctx *ctx)
keir@20462 72 {
keir@20462 73 libxl_free_all(ctx);
keir@20462 74 free(ctx->alloc_ptrs);
keir@20462 75 xc_interface_close(ctx->xch);
keir@21186 76 if (ctx->xsh) xs_daemon_close(ctx->xsh);
keir@20462 77 return 0;
keir@20462 78 }
keir@20462 79
keir@20462 80 /******************************************************************************/
keir@20462 81
keir@20462 82 int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info,
keir@20462 83 uint32_t *domid)
keir@20462 84 {
keir@21184 85 int flags, ret, i, rc;
keir@20468 86 char *uuid_string;
keir@20646 87 char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"};
keir@20462 88 char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
keir@20646 89 "control", "attr", "messages" };
keir@20462 90 char *dom_path, *vm_path, *vss_path;
keir@20462 91 struct xs_permissions roperm[2];
keir@20462 92 struct xs_permissions rwperm[1];
keir@20462 93 xs_transaction_t t;
keir@20468 94 xen_domain_handle_t handle;
keir@20462 95
keir@21188 96 uuid_string = libxl_uuid2string(ctx, info->uuid);
keir@21188 97 if (!uuid_string) return ERROR_NOMEM;
keir@20462 98
keir@20462 99 flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
keir@20462 100 flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
keir@21274 101 flags |= info->oos ? 0 : XEN_DOMCTL_CDF_oos_off;
keir@20824 102 *domid = -1;
keir@20462 103
keir@20580 104 /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
keir@20580 105 memcpy(handle, info->uuid, sizeof(xen_domain_handle_t));
keir@20468 106
keir@20468 107 ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
keir@20462 108 if (ret < 0) {
keir@20512 109 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain creation fail");
keir@20462 110 return ERROR_FAIL;
keir@20462 111 }
keir@20462 112
keir@21368 113 ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid);
keir@21368 114 if (ret < 0) {
keir@21368 115 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain move fail");
keir@21368 116 return ERROR_FAIL;
keir@21368 117 }
keir@21368 118
keir@20462 119 dom_path = libxl_xs_get_dompath(ctx, *domid);
keir@20512 120 if (!dom_path)
keir@20512 121 return ERROR_FAIL;
keir@20512 122
keir@20462 123 vm_path = libxl_sprintf(ctx, "/vm/%s", uuid_string);
keir@20462 124 vss_path = libxl_sprintf(ctx, "/vss/%s", uuid_string);
keir@20512 125 if (!vm_path || !vss_path) {
keir@20462 126 XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate create paths");
keir@20462 127 return ERROR_FAIL;
keir@20462 128 }
keir@20462 129
keir@20462 130 roperm[0].id = 0;
keir@20462 131 roperm[0].perms = XS_PERM_NONE;
keir@20462 132 roperm[1].id = *domid;
keir@20462 133 roperm[1].perms = XS_PERM_READ;
keir@20462 134 rwperm[0].id = *domid;
keir@20462 135 rwperm[0].perms = XS_PERM_NONE;
keir@20462 136
keir@20462 137 retry_transaction:
keir@20462 138 t = xs_transaction_start(ctx->xsh);
keir@20462 139 xs_rm(ctx->xsh, t, dom_path);
keir@20462 140 xs_mkdir(ctx->xsh, t, dom_path);
keir@20462 141 xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm));
keir@20462 142
keir@20462 143 xs_rm(ctx->xsh, t, vm_path);
keir@20462 144 xs_mkdir(ctx->xsh, t, vm_path);
keir@20462 145 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
keir@20462 146
keir@20462 147 xs_rm(ctx->xsh, t, vss_path);
keir@20462 148 xs_mkdir(ctx->xsh, t, vss_path);
keir@20462 149 xs_set_permissions(ctx->xsh, t, vss_path, rwperm, ARRAY_SIZE(rwperm));
keir@20462 150
keir@20462 151 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vm", dom_path), vm_path, strlen(vm_path));
keir@20462 152 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vss", dom_path), vss_path, strlen(vss_path));
keir@21184 153 rc = libxl_domain_rename(ctx, *domid, 0, info->name, t);
keir@21184 154 if (rc) return rc;
keir@20462 155
keir@20462 156 for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
keir@20462 157 char *path = libxl_sprintf(ctx, "%s/%s", dom_path, rw_paths[i]);
keir@20462 158 xs_mkdir(ctx->xsh, t, path);
keir@20462 159 xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm));
keir@20462 160 libxl_free(ctx, path);
keir@20462 161 }
keir@20462 162 for (i = 0; i < ARRAY_SIZE(ro_paths); i++) {
keir@20462 163 char *path = libxl_sprintf(ctx, "%s/%s", dom_path, ro_paths[i]);
keir@20462 164 xs_mkdir(ctx->xsh, t, path);
keir@20462 165 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
keir@20462 166 libxl_free(ctx, path);
keir@20462 167 }
keir@20462 168
keir@20462 169 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
keir@20462 170 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", vm_path), info->name, strlen(info->name));
keir@21389 171 if (info->poolname)
keir@21389 172 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/pool_name", vm_path), info->poolname, strlen(info->poolname));
keir@20462 173
keir@20462 174 libxl_xs_writev(ctx, t, dom_path, info->xsdata);
keir@20462 175 libxl_xs_writev(ctx, t, libxl_sprintf(ctx, "%s/platform", dom_path), info->platformdata);
keir@20462 176
keir@20462 177 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
keir@20462 178
keir@20462 179 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20462 180 if (errno == EAGAIN)
keir@20462 181 goto retry_transaction;
keir@20462 182 return 0;
keir@20462 183 }
keir@20462 184
keir@21184 185 int libxl_domain_rename(struct libxl_ctx *ctx, uint32_t domid,
keir@21184 186 const char *old_name, const char *new_name,
keir@21184 187 xs_transaction_t trans) {
keir@21184 188 char *dom_path = 0;
keir@21184 189 const char *name_path;
keir@21184 190 char *got_old_name;
keir@21184 191 unsigned int got_old_len;
keir@21184 192 xs_transaction_t our_trans = 0;
keir@21184 193 int rc;
keir@21184 194
keir@21184 195 dom_path = libxl_xs_get_dompath(ctx, domid);
keir@21184 196 if (!dom_path) goto x_nomem;
keir@21184 197
keir@21184 198 name_path= libxl_sprintf(ctx, "%s/name", dom_path);
keir@21184 199 if (!name_path) goto x_nomem;
keir@21184 200
keir@21184 201 retry_transaction:
keir@21184 202 if (!trans) {
keir@21184 203 trans = our_trans = xs_transaction_start(ctx->xsh);
keir@21184 204 if (!our_trans) {
keir@21184 205 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
keir@21184 206 "create xs transaction for domain (re)name");
keir@21184 207 goto x_fail;
keir@21184 208 }
keir@21184 209 }
keir@21184 210
keir@21184 211 if (old_name) {
keir@21184 212 got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len);
keir@21184 213 if (!got_old_name) {
keir@21184 214 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, "check old name"
keir@21184 215 " for domain %"PRIu32" allegedly named `%s'",
keir@21184 216 domid, old_name);
keir@21184 217 goto x_fail;
keir@21184 218 }
keir@21184 219 if (strcmp(old_name, got_old_name)) {
keir@21184 220 XL_LOG(ctx, XL_LOG_ERROR, "domain %"PRIu32" allegedly named "
keir@21184 221 "`%s' is actually named `%s' - racing ?",
keir@21184 222 domid, old_name, got_old_name);
keir@21184 223 free(got_old_name);
keir@21184 224 goto x_fail;
keir@21184 225 }
keir@21184 226 free(got_old_name);
keir@21184 227 }
keir@21184 228 if (!xs_write(ctx->xsh, trans, name_path,
keir@21184 229 new_name, strlen(new_name))) {
keir@21184 230 XL_LOG(ctx, XL_LOG_ERROR, "failed to write new name `%s'"
keir@21184 231 " for domain %"PRIu32" previously named `%s'",
keir@21531 232 new_name, domid, old_name);
keir@21184 233 goto x_fail;
keir@21184 234 }
keir@21184 235
keir@21184 236 if (our_trans) {
keir@21184 237 if (!xs_transaction_end(ctx->xsh, our_trans, 0)) {
keir@21184 238 trans = our_trans = 0;
keir@21184 239 if (errno != EAGAIN) {
keir@21184 240 XL_LOG(ctx, XL_LOG_ERROR, "failed to commit new name `%s'"
keir@21184 241 " for domain %"PRIu32" previously named `%s'",
keir@21531 242 new_name, domid, old_name);
keir@21184 243 goto x_fail;
keir@21184 244 }
keir@21184 245 XL_LOG(ctx, XL_LOG_DEBUG, "need to retry rename transaction"
keir@21184 246 " for domain %"PRIu32" (name_path=\"%s\", new_name=\"%s\")",
keir@21184 247 domid, name_path, new_name);
keir@21184 248 goto retry_transaction;
keir@21184 249 }
keir@21184 250 our_trans = 0;
keir@21184 251 }
keir@21184 252
keir@21184 253 rc = 0;
keir@21184 254 x_rc:
keir@21184 255 if (dom_path) libxl_free(ctx, dom_path);
keir@21184 256 if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
keir@21184 257 return rc;
keir@21184 258
keir@21184 259 x_fail: rc = ERROR_FAIL; goto x_rc;
keir@21184 260 x_nomem: rc = ERROR_NOMEM; goto x_rc;
keir@21184 261 }
keir@21184 262
keir@20516 263 int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, libxl_domain_build_state *state)
keir@20462 264 {
keir@20462 265 char **vments = NULL, **localents = NULL;
keir@21438 266 struct timeval start_time;
keir@20829 267 int i, ret;
keir@20829 268
keir@20829 269 ret = build_pre(ctx, domid, info, state);
keir@20829 270 if (ret) goto out;
keir@20462 271
keir@21438 272 gettimeofday(&start_time, NULL);
keir@21438 273
keir@20462 274 if (info->hvm) {
keir@20829 275 ret = build_hvm(ctx, domid, info, state);
keir@20829 276 if (ret) goto out;
keir@20829 277
keir@21438 278 vments = libxl_calloc(ctx, 7, sizeof(char *));
keir@20516 279 vments[0] = "rtc/timeoffset";
keir@20516 280 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
keir@20516 281 vments[2] = "image/ostype";
keir@20516 282 vments[3] = "hvm";
keir@21438 283 vments[4] = "start_time";
keir@21438 284 vments[5] = libxl_sprintf(ctx, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
keir@20462 285 } else {
keir@20829 286 ret = build_pv(ctx, domid, info, state);
keir@20829 287 if (ret) goto out;
keir@20829 288
keir@21438 289 vments = libxl_calloc(ctx, 11, sizeof(char *));
keir@20578 290 i = 0;
keir@20578 291 vments[i++] = "image/ostype";
keir@20578 292 vments[i++] = "linux";
keir@20578 293 vments[i++] = "image/kernel";
Ian@21848 294 vments[i++] = (char*) info->kernel.path;
keir@21438 295 vments[i++] = "start_time";
keir@21438 296 vments[i++] = libxl_sprintf(ctx, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
Ian@21848 297 if (info->u.pv.ramdisk.path) {
keir@20578 298 vments[i++] = "image/ramdisk";
Ian@21848 299 vments[i++] = (char*) info->u.pv.ramdisk.path;
keir@20578 300 }
keir@20578 301 if (info->u.pv.cmdline) {
keir@20578 302 vments[i++] = "image/cmdline";
keir@20578 303 vments[i++] = (char*) info->u.pv.cmdline;
keir@20578 304 }
keir@20462 305 }
keir@20829 306 ret = build_post(ctx, domid, info, state, vments, localents);
keir@20829 307 out:
Ian@21848 308 libxl_file_reference_unmap(ctx, &info->kernel);
Ian@21848 309 if (!info->hvm)
Ian@21848 310 libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
Ian@21848 311
keir@20829 312 return ret;
keir@20462 313 }
keir@20462 314
keir@20462 315 int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info,
keir@20565 316 uint32_t domid, int fd, libxl_domain_build_state *state,
keir@20565 317 libxl_device_model_info *dm_info)
keir@20462 318 {
keir@20462 319 char **vments = NULL, **localents = NULL;
keir@21438 320 struct timeval start_time;
keir@21183 321 int i, ret, esave, flags;
keir@20462 322
keir@20829 323 ret = build_pre(ctx, domid, info, state);
keir@20829 324 if (ret) goto out;
keir@20829 325
keir@20829 326 ret = restore_common(ctx, domid, info, state, fd);
keir@20829 327 if (ret) goto out;
keir@20829 328
keir@21438 329 gettimeofday(&start_time, NULL);
keir@21438 330
keir@20462 331 if (info->hvm) {
keir@21438 332 vments = libxl_calloc(ctx, 7, sizeof(char *));
keir@20516 333 vments[0] = "rtc/timeoffset";
keir@20516 334 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
keir@20565 335 vments[2] = "image/ostype";
keir@20565 336 vments[3] = "hvm";
keir@21438 337 vments[4] = "start_time";
keir@21438 338 vments[5] = libxl_sprintf(ctx, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
keir@20462 339 } else {
keir@21438 340 vments = libxl_calloc(ctx, 11, sizeof(char *));
keir@20627 341 i = 0;
keir@20627 342 vments[i++] = "image/ostype";
keir@20627 343 vments[i++] = "linux";
keir@20627 344 vments[i++] = "image/kernel";
Ian@21848 345 vments[i++] = (char*) info->kernel.path;
keir@21438 346 vments[i++] = "start_time";
keir@21438 347 vments[i++] = libxl_sprintf(ctx, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
Ian@21848 348 if (info->u.pv.ramdisk.path) {
keir@20627 349 vments[i++] = "image/ramdisk";
Ian@21848 350 vments[i++] = (char*) info->u.pv.ramdisk.path;
keir@20627 351 }
keir@20627 352 if (info->u.pv.cmdline) {
keir@20627 353 vments[i++] = "image/cmdline";
keir@20627 354 vments[i++] = (char*) info->u.pv.cmdline;
keir@20627 355 }
keir@20462 356 }
keir@20829 357 ret = build_post(ctx, domid, info, state, vments, localents);
keir@20829 358 if (ret) goto out;
keir@20829 359
keir@21417 360 dm_info->saved_state = NULL;
keir@21417 361 if (info->hvm) {
keir@21417 362 ret = asprintf(&dm_info->saved_state,
keir@21417 363 "/var/lib/xen/qemu-save.%d", domid);
keir@21417 364 ret = (ret < 0) ? ERROR_FAIL : 0;
keir@21417 365 }
keir@21417 366
keir@20829 367 out:
Ian@21848 368 libxl_file_reference_unmap(ctx, &info->kernel);
Ian@21848 369 if (!info->hvm)
Ian@21848 370 libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
Ian@21848 371
keir@21183 372 esave = errno;
keir@21183 373
keir@21183 374 flags = fcntl(fd, F_GETFL);
keir@21183 375 if (flags == -1) {
keir@21183 376 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to get flags on restore fd");
keir@21183 377 } else {
keir@21183 378 flags &= ~O_NONBLOCK;
keir@21183 379 if (fcntl(fd, F_SETFL, flags) == -1)
keir@21183 380 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to put restore fd"
keir@21183 381 " back to blocking mode");
keir@21183 382 }
keir@21183 383
keir@21183 384 errno = esave;
keir@20829 385 return ret;
keir@20462 386 }
keir@20462 387
keir@20629 388 int libxl_domain_resume(struct libxl_ctx *ctx, uint32_t domid)
keir@20629 389 {
keir@20629 390 if (is_hvm(ctx, domid)) {
keir@20629 391 XL_LOG(ctx, XL_LOG_DEBUG, "Called domain_resume on "
keir@20629 392 "non-cooperative hvm domain %u", domid);
keir@20629 393 return ERROR_NI;
keir@20629 394 }
keir@20629 395 if (xc_domain_resume(ctx->xch, domid, 1)) {
keir@20629 396 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@20629 397 "xc_domain_resume failed for domain %u",
keir@20629 398 domid);
keir@20629 399 return ERROR_FAIL;
keir@20629 400 }
keir@20629 401 if (!xs_resume_domain(ctx->xsh, domid)) {
keir@20629 402 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@20629 403 "xs_resume_domain failed for domain %u",
keir@20629 404 domid);
keir@20629 405 return ERROR_FAIL;
keir@20629 406 }
keir@20629 407 return 0;
keir@20629 408 }
keir@20629 409
keir@21189 410 static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo,
keir@21189 411 struct libxl_dominfo *xlinfo) {
keir@21189 412 memcpy(&(xlinfo->uuid), xcinfo->handle, sizeof(xen_domain_handle_t));
keir@21189 413 xlinfo->domid = xcinfo->domain;
keir@21189 414
keir@21189 415 if (xcinfo->flags & XEN_DOMINF_dying)
keir@21189 416 xlinfo->dying = 1;
keir@21189 417 else if (xcinfo->flags & XEN_DOMINF_paused)
keir@21189 418 xlinfo->paused = 1;
keir@21189 419 else if (xcinfo->flags & XEN_DOMINF_blocked ||
keir@21189 420 xcinfo->flags & XEN_DOMINF_running)
keir@21189 421 xlinfo->running = 1;
keir@21189 422 xlinfo->max_memkb = PAGE_TO_MEMKB(xcinfo->tot_pages);
keir@21189 423 xlinfo->cpu_time = xcinfo->cpu_time;
keir@21189 424 xlinfo->vcpu_max_id = xcinfo->max_vcpu_id;
keir@21189 425 xlinfo->vcpu_online = xcinfo->nr_online_vcpus;
keir@21189 426 }
keir@21189 427
keir@20860 428 struct libxl_dominfo * libxl_list_domain(struct libxl_ctx *ctx, int *nb_domain)
keir@20462 429 {
keir@20462 430 struct libxl_dominfo *ptr;
keir@20867 431 int i, ret;
keir@20822 432 xc_domaininfo_t info[1024];
keir@20822 433 int size = 1024;
keir@20462 434
keir@20516 435 ptr = calloc(size, sizeof(struct libxl_dominfo));
gianni@21892 436 if (!ptr) {
gianni@21892 437 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "allocating domain info");
gianni@21892 438 return NULL;
gianni@21892 439 }
keir@20822 440
keir@20860 441 ret = xc_domain_getinfolist(ctx->xch, 0, 1024, info);
gianni@21892 442 if (ret<0) {
gianni@21892 443 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "geting domain info list");
gianni@21892 444 return NULL;
gianni@21892 445 }
keir@20784 446
keir@21189 447 for (i = 0; i < ret; i++) {
keir@21189 448 xcinfo2xlinfo(&info[i], &ptr[i]);
keir@20462 449 }
keir@20867 450 *nb_domain = ret;
keir@20462 451 return ptr;
keir@20462 452 }
keir@20462 453
keir@21189 454 int libxl_domain_info(struct libxl_ctx *ctx, struct libxl_dominfo *info_r,
keir@21189 455 uint32_t domid) {
keir@21189 456 xc_domaininfo_t xcinfo;
keir@21189 457 int ret;
keir@21189 458
keir@21189 459 ret = xc_domain_getinfolist(ctx->xch, domid, 1, &xcinfo);
gianni@21892 460 if (ret<0) {
gianni@21892 461 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "geting domain info list");
gianni@21892 462 return ERROR_FAIL;
gianni@21892 463 }
keir@21189 464 if (ret==0 || xcinfo.domain != domid) return ERROR_INVAL;
keir@21189 465
keir@21189 466 xcinfo2xlinfo(&xcinfo, info_r);
keir@21189 467 return 0;
keir@21189 468 }
keir@21189 469
keir@21368 470 struct libxl_poolinfo * libxl_list_pool(struct libxl_ctx *ctx, int *nb_pool)
keir@21368 471 {
keir@21368 472 struct libxl_poolinfo *ptr;
keir@21368 473 int i, ret;
keir@21368 474 xc_cpupoolinfo_t info[256];
keir@21368 475 int size = 256;
keir@21368 476
keir@21368 477 ptr = calloc(size, sizeof(struct libxl_poolinfo));
gianni@21892 478 if (!ptr) {
gianni@21892 479 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "allocating cpupool info");
gianni@21892 480 return NULL;
gianni@21892 481 }
keir@21368 482
keir@21368 483 ret = xc_cpupool_getinfo(ctx->xch, 0, 256, info);
gianni@21892 484 if (ret<0) {
gianni@21892 485 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting cpupool info");
gianni@21892 486 return NULL;
gianni@21892 487 }
keir@21368 488
keir@21368 489 for (i = 0; i < ret; i++) {
keir@21368 490 ptr[i].poolid = info[i].cpupool_id;
keir@21368 491 }
keir@21368 492 *nb_pool = ret;
keir@21368 493 return ptr;
keir@21368 494 }
keir@21368 495
keir@20860 496 /* this API call only list VM running on this host. a VM can be an aggregate of multiple domains. */
keir@20860 497 struct libxl_vminfo * libxl_list_vm(struct libxl_ctx *ctx, int *nb_vm)
keir@20860 498 {
keir@20860 499 struct libxl_vminfo *ptr;
keir@20860 500 int index, i, ret;
keir@20860 501 xc_domaininfo_t info[1024];
keir@20860 502 int size = 1024;
keir@20860 503
keir@20860 504 ptr = calloc(size, sizeof(struct libxl_dominfo));
keir@20860 505 if (!ptr)
keir@20860 506 return NULL;
keir@20860 507
keir@20860 508 ret = xc_domain_getinfolist(ctx->xch, 1, 1024, info);
gianni@21892 509 if (ret<0) {
gianni@21892 510 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "geting domain info list");
gianni@21892 511 return NULL;
gianni@21892 512 }
keir@20860 513 for (index = i = 0; i < ret; i++) {
keir@20860 514 if (libxl_is_stubdom(ctx, info[i].domain, NULL))
keir@20860 515 continue;
keir@20860 516 memcpy(&(ptr[index].uuid), info[i].handle, sizeof(xen_domain_handle_t));
keir@20860 517 ptr[index].domid = info[i].domain;
keir@20860 518
keir@20860 519 index++;
keir@20860 520 }
keir@20860 521 *nb_vm = index;
keir@20860 522 return ptr;
keir@20860 523 }
keir@20860 524
keir@20462 525 int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info *info,
keir@20462 526 uint32_t domid, int fd)
keir@20462 527 {
keir@20565 528 int hvm = is_hvm(ctx, domid);
keir@20565 529 int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
keir@21543 530 int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG;
keir@20462 531
keir@20462 532 core_suspend(ctx, domid, fd, hvm, live, debug);
keir@20565 533 if (hvm)
keir@21417 534 return save_device_model(ctx, domid, fd);
keir@20462 535 return 0;
keir@20462 536 }
keir@20462 537
keir@20462 538 int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 539 {
gianni@21892 540 int ret;
gianni@21892 541 ret = xc_domain_pause(ctx->xch, domid);
gianni@21892 542 if (ret<0) {
gianni@21892 543 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "pausing domain %d", domid);
gianni@21892 544 return ERROR_FAIL;
gianni@21892 545 }
Ian@21888 546 return 0;
keir@20462 547 }
keir@20462 548
gianni@21892 549 int libxl_domain_core_dump(struct libxl_ctx *ctx, uint32_t domid,
gianni@21892 550 const char *filename)
sstabellini@21870 551 {
gianni@21892 552 int ret;
gianni@21892 553 ret = xc_domain_dumpcore(ctx->xch, domid, filename);
gianni@21892 554 if (ret<0) {
gianni@21892 555 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "core dumping domain %d to %s",
gianni@21892 556 domid, filename);
Ian@21888 557 return ERROR_FAIL;
gianni@21892 558 }
Ian@21888 559 return 0;
sstabellini@21870 560 }
sstabellini@21870 561
keir@20462 562 int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 563 {
keir@20779 564 char *path;
keir@20565 565 char *state;
gianni@21892 566 int ret;
keir@20565 567
keir@20565 568 if (is_hvm(ctx, domid)) {
keir@20779 569 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20565 570 state = libxl_xs_read(ctx, XBT_NULL, path);
keir@20565 571 if (state != NULL && !strcmp(state, "paused")) {
Ian@21844 572 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid), "continue");
keir@20565 573 libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL);
keir@20565 574 }
keir@20565 575 }
gianni@21892 576 ret = xc_domain_unpause(ctx->xch, domid);
gianni@21892 577 if (ret<0) {
gianni@21892 578 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unpausing domain %d", domid);
gianni@21892 579 return ERROR_FAIL;
gianni@21892 580 }
Ian@21888 581 return 0;
keir@20462 582 }
keir@20462 583
keir@20462 584 static char *req_table[] = {
keir@20462 585 [0] = "poweroff",
keir@20462 586 [1] = "reboot",
keir@20462 587 [2] = "suspend",
keir@20462 588 [3] = "crash",
keir@20462 589 [4] = "halt",
keir@20462 590 };
keir@20462 591
keir@20462 592 int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req)
keir@20462 593 {
keir@20462 594 char *shutdown_path;
keir@20462 595 char *dom_path;
keir@20462 596
keir@20462 597 if (req > ARRAY_SIZE(req_table))
keir@20462 598 return ERROR_INVAL;
keir@20462 599
keir@20462 600 dom_path = libxl_xs_get_dompath(ctx, domid);
keir@20512 601 if (!dom_path)
keir@20512 602 return ERROR_FAIL;
keir@20512 603
keir@20462 604 shutdown_path = libxl_sprintf(ctx, "%s/control/shutdown", dom_path);
keir@20462 605
keir@20462 606 xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], strlen(req_table[req]));
keir@21552 607 if (is_hvm(ctx,domid)) {
keir@20462 608 unsigned long acpi_s_state = 0;
keir@20462 609 unsigned long pvdriver = 0;
gianni@21892 610 int ret;
gianni@21892 611 ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, &acpi_s_state);
gianni@21892 612 if (ret<0) {
gianni@21892 613 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting ACPI S-state");
gianni@21892 614 return ERROR_FAIL;
gianni@21892 615 }
gianni@21892 616 ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
gianni@21892 617 if (ret<0) {
gianni@21892 618 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting HVM callback IRQ");
gianni@21892 619 return ERROR_FAIL;
gianni@21892 620 }
gianni@21892 621 if (!pvdriver || acpi_s_state != 0) {
gianni@21892 622 ret = xc_domain_shutdown(ctx->xch, domid, req);
gianni@21892 623 if (ret<0) {
gianni@21892 624 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unpausing domain");
gianni@21892 625 return ERROR_FAIL;
gianni@21892 626 }
gianni@21892 627 }
keir@20462 628 }
Ian@21888 629 return 0;
keir@20462 630 }
keir@20462 631
keir@20637 632 int libxl_get_wait_fd(struct libxl_ctx *ctx, int *fd)
keir@20545 633 {
keir@20545 634 *fd = xs_fileno(ctx->xsh);
keir@20545 635 return 0;
keir@20545 636 }
keir@20545 637
keir@20637 638 int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, libxl_waiter *waiter)
keir@20637 639 {
keir@20637 640 waiter->path = strdup("@releaseDomain");
keir@21417 641 if (asprintf(&(waiter->token), "%d", DOMAIN_DEATH) < 0)
keir@21417 642 return -1;
keir@20637 643 if (!xs_watch(ctx->xsh, waiter->path, waiter->token))
keir@20637 644 return -1;
keir@20637 645 return 0;
keir@20637 646 }
keir@20637 647
keir@20637 648 int libxl_wait_for_disk_ejects(struct libxl_ctx *ctx, uint32_t guest_domid, libxl_device_disk *disks, int num_disks, libxl_waiter *waiter)
keir@20637 649 {
keir@20637 650 int i;
keir@20637 651 uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
keir@20637 652
keir@20637 653 if (!domid)
keir@20637 654 domid = guest_domid;
keir@20637 655
keir@20637 656 for (i = 0; i < num_disks; i++) {
keir@21417 657 if (asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject",
keir@21417 658 libxl_xs_get_dompath(ctx, domid),
keir@21417 659 device_disk_dev_number(disks[i].virtpath)) < 0)
keir@21417 660 return -1;
keir@21417 661 if (asprintf(&(waiter[i].token), "%d", DISK_EJECT) < 0)
keir@21417 662 return -1;
keir@20637 663 xs_watch(ctx->xsh, waiter->path, waiter->token);
keir@20637 664 }
keir@20637 665 return 0;
keir@20637 666 }
keir@20637 667
keir@20637 668 int libxl_get_event(struct libxl_ctx *ctx, libxl_event *event)
keir@20545 669 {
keir@20545 670 unsigned int num;
keir@20637 671 char **events = xs_read_watch(ctx->xsh, &num);
keir@20637 672 if (num != 2) {
keir@20637 673 free(events);
gianni@21892 674 return ERROR_FAIL;
keir@20637 675 }
keir@20637 676 event->path = strdup(events[XS_WATCH_PATH]);
keir@20637 677 event->token = strdup(events[XS_WATCH_TOKEN]);
keir@20637 678 event->type = atoi(event->token);
keir@20637 679 free(events);
keir@20637 680 return 0;
keir@20637 681 }
keir@20637 682
keir@20637 683 int libxl_stop_waiting(struct libxl_ctx *ctx, libxl_waiter *waiter)
keir@20637 684 {
keir@20637 685 if (!xs_unwatch(ctx->xsh, waiter->path, waiter->token))
gianni@21892 686 return ERROR_FAIL;
keir@20637 687 else
keir@20637 688 return 0;
keir@20637 689 }
keir@20637 690
keir@20637 691 int libxl_free_event(libxl_event *event)
keir@20637 692 {
keir@20637 693 free(event->path);
keir@20637 694 free(event->token);
keir@20637 695 return 0;
keir@20637 696 }
keir@20637 697
keir@20637 698 int libxl_free_waiter(libxl_waiter *waiter)
keir@20637 699 {
keir@20637 700 free(waiter->path);
keir@20637 701 free(waiter->token);
keir@20637 702 return 0;
keir@20637 703 }
keir@20637 704
keir@20785 705 int libxl_event_get_domain_death_info(struct libxl_ctx *ctx, uint32_t domid, libxl_event *event, xc_domaininfo_t *info)
keir@20637 706 {
keir@20785 707 int rc = 0, ret;
keir@20545 708
keir@20637 709 if (event && event->type == DOMAIN_DEATH) {
keir@20785 710 ret = xc_domain_getinfolist(ctx->xch, domid, 1, info);
keir@20785 711 if (ret == 1 && info->domain == domid) {
keir@20785 712 if (info->flags & XEN_DOMINF_running ||
keir@20785 713 (!(info->flags & XEN_DOMINF_shutdown) && !(info->flags & XEN_DOMINF_dying)))
keir@20545 714 goto out;
keir@20545 715 rc = 1;
keir@20545 716 goto out;
keir@20545 717 }
keir@20785 718 memset(info, 0, sizeof(xc_dominfo_t));
keir@20545 719 rc = 1;
keir@20545 720 goto out;
keir@20545 721 }
keir@20545 722 out:
keir@20545 723 return rc;
keir@20545 724 }
keir@20545 725
keir@20637 726 int libxl_event_get_disk_eject_info(struct libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_device_disk *disk)
keir@20637 727 {
keir@20637 728 if (event && event->type == DISK_EJECT) {
keir@20637 729 char *path;
keir@20637 730 char *backend;
keir@20637 731 char *value = libxl_xs_read(ctx, XBT_NULL, event->path);
keir@20637 732
keir@20637 733 if (!value || strcmp(value, "eject"))
keir@20637 734 return 0;
keir@20637 735
keir@20637 736 path = strdup(event->path);
keir@20637 737 path[strlen(path) - 6] = '\0';
keir@20637 738 backend = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend", path));
keir@20637 739
keir@20637 740 disk->backend_domid = 0;
keir@20637 741 disk->domid = domid;
keir@20637 742 disk->physpath = NULL;
keir@20637 743 disk->phystype = 0;
keir@20637 744 /* this value is returned to the user: do not free right away */
keir@20637 745 disk->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev", backend));
keir@20637 746 disk->unpluggable = 1;
keir@20637 747 disk->readwrite = 0;
keir@20637 748 disk->is_cdrom = 1;
keir@20637 749
keir@20637 750 free(path);
keir@20637 751 return 1;
keir@20637 752 }
keir@20637 753 return 0;
keir@20637 754 }
keir@20637 755
keir@20462 756 static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 757 {
keir@20462 758 char *pid;
keir@20462 759 int ret;
keir@20462 760
keir@20462 761 pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/image/device-model-pid", domid));
keir@20462 762 if (!pid) {
keir@20542 763 int stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20542 764 if (!stubdomid) {
keir@20542 765 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't find device model's pid");
gianni@21892 766 return ERROR_INVAL;
keir@20542 767 }
keir@20542 768 XL_LOG(ctx, XL_LOG_ERROR, "Device model is a stubdom, domid=%d\n", stubdomid);
keir@20542 769 return libxl_domain_destroy(ctx, stubdomid, 0);
keir@20462 770 }
keir@20462 771 xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", domid));
keir@20462 772
keir@20462 773 ret = kill(atoi(pid), SIGHUP);
keir@20462 774 if (ret < 0 && errno == ESRCH) {
keir@20512 775 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model already exited");
keir@20462 776 ret = 0;
keir@20462 777 } else if (ret == 0) {
keir@20512 778 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model signaled");
keir@20462 779 ret = 0;
keir@20462 780 } else {
keir@20512 781 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to kill Device Model [%d]",
keir@20512 782 atoi(pid));
keir@20462 783 }
keir@20462 784 return ret;
keir@20462 785 }
keir@20462 786
keir@20462 787 int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force)
keir@20462 788 {
keir@20801 789 char *dom_path;
keir@20779 790 char *vm_path, *vss_path, *xapi_path;
keir@20628 791 int rc, dm_present;
keir@20628 792
keir@20628 793 if (is_hvm(ctx, domid)) {
keir@20628 794 dm_present = 1;
keir@20628 795 } else {
keir@20628 796 char *pid;
keir@20628 797 pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/image/device-model-pid", domid));
keir@20628 798 dm_present = (pid != NULL);
keir@20628 799 libxl_free(ctx, pid);
keir@20628 800 }
keir@20462 801
keir@20462 802 dom_path = libxl_xs_get_dompath(ctx, domid);
keir@20512 803 if (!dom_path)
gianni@21892 804 return ERROR_FAIL;
keir@20512 805
keir@20482 806 if (libxl_device_pci_shutdown(ctx, domid) < 0)
keir@20512 807 XL_LOG(ctx, XL_LOG_ERROR, "pci shutdown failed for domid %d", domid);
keir@20628 808 if (dm_present) {
keir@20628 809 xs_write(ctx->xsh, XBT_NULL,
keir@20628 810 libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid),
keir@20628 811 "shutdown", strlen("shutdown"));
keir@20628 812 }
keir@20512 813 rc = xc_domain_pause(ctx->xch, domid);
keir@20512 814 if (rc < 0) {
keir@20512 815 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_pause failed for %d", domid);
keir@20462 816 }
keir@20628 817 if (dm_present) {
keir@20628 818 if (libxl_destroy_device_model(ctx, domid) < 0)
keir@20628 819 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_device_model failed for %d", domid);
keir@20628 820 }
keir@20462 821 if (libxl_devices_destroy(ctx, domid, force) < 0)
keir@20512 822 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d", domid);
ian@21891 823
ian@21891 824 vm_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vm", dom_path));
keir@20823 825 if (vm_path)
keir@20823 826 if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
keir@20823 827 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vm_path);
keir@20779 828
ian@21891 829 vss_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vss", dom_path));
keir@20823 830 if (vss_path)
keir@20823 831 if (!xs_rm(ctx->xsh, XBT_NULL, vss_path))
keir@20823 832 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vss_path);
keir@20779 833
ian@21891 834 if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
ian@21891 835 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", dom_path);
ian@21891 836
keir@20779 837 xapi_path = libxl_sprintf(ctx, "/xapi/%u", domid);
keir@20823 838 if (xapi_path)
keir@20823 839 if (!xs_rm(ctx->xsh, XBT_NULL, xapi_path))
keir@20823 840 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", xapi_path);
keir@20779 841
keir@21190 842 libxl__userdata_destroyall(ctx, domid);
keir@21190 843
keir@20545 844 rc = xc_domain_destroy(ctx->xch, domid);
keir@20545 845 if (rc < 0) {
keir@20545 846 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
gianni@21892 847 return ERROR_FAIL;
keir@20545 848 }
keir@20462 849 return 0;
keir@20462 850 }
keir@20462 851
Ian@21847 852 int libxl_console_exec(struct libxl_ctx *ctx, uint32_t domid, int cons_num)
keir@20564 853 {
Ian@21847 854 char *p = libxl_sprintf(ctx, "%s/xenconsole", libxl_private_bindir_path());
Ian@21847 855 char *domid_s = libxl_sprintf(ctx, "%d", domid);
Ian@21847 856 char *cons_num_s = libxl_sprintf(ctx, "%d", cons_num);
Ian@21847 857 return execl(p, p, domid_s, "--num", cons_num_s, (void *)NULL) == 0 ? 0 : ERROR_FAIL;
keir@20564 858 }
keir@20564 859
sstabellini@21867 860 int libxl_primary_console_exec(struct libxl_ctx *ctx, uint32_t domid_vm)
sstabellini@21867 861 {
sstabellini@21867 862 uint32_t stubdomid = libxl_get_stubdom_id(ctx, domid_vm);
sstabellini@21867 863 if (stubdomid)
sstabellini@21867 864 return libxl_console_exec(ctx, stubdomid, 1);
sstabellini@21867 865 else
sstabellini@21867 866 return libxl_console_exec(ctx, domid_vm, 0);
sstabellini@21867 867 }
sstabellini@21867 868
sstabellini@21879 869 int libxl_vncviewer_exec(struct libxl_ctx *ctx, uint32_t domid, int autopass)
sstabellini@21879 870 {
sstabellini@21879 871 const char *vnc_port, *vfb_back;
sstabellini@21879 872 const char *vnc_listen = NULL, *vnc_pass = NULL;
sstabellini@21879 873 int port = 0, autopass_fd = -1;
sstabellini@21879 874 char *vnc_bin, *args[] = {
sstabellini@21879 875 "vncviewer",
sstabellini@21879 876 NULL, /* hostname:display */
sstabellini@21879 877 NULL, /* -autopass */
sstabellini@21879 878 NULL,
sstabellini@21879 879 };
sstabellini@21879 880
sstabellini@21879 881 vnc_port = libxl_xs_read(ctx, XBT_NULL,
sstabellini@21879 882 libxl_sprintf(ctx,
sstabellini@21879 883 "/local/domain/%d/console/vnc-port", domid));
sstabellini@21879 884 if ( vnc_port )
sstabellini@21879 885 port = atoi(vnc_port) - 5900;
sstabellini@21879 886
sstabellini@21879 887 vfb_back = libxl_xs_read(ctx, XBT_NULL,
sstabellini@21879 888 libxl_sprintf(ctx,
sstabellini@21879 889 "/local/domain/%d/device/vfb/0/backend", domid));
sstabellini@21879 890 if ( vfb_back ) {
sstabellini@21879 891 vnc_listen = libxl_xs_read(ctx, XBT_NULL,
sstabellini@21879 892 libxl_sprintf(ctx,
sstabellini@21879 893 "/local/domain/%d/console/vnc-listen", domid));
sstabellini@21879 894 if ( autopass )
sstabellini@21879 895 vnc_pass = libxl_xs_read(ctx, XBT_NULL,
sstabellini@21879 896 libxl_sprintf(ctx,
sstabellini@21879 897 "/local/domain/%d/console/vnc-pass", domid));
sstabellini@21879 898 }
sstabellini@21879 899
sstabellini@21879 900 if ( NULL == vnc_listen )
sstabellini@21879 901 vnc_listen = "localhost";
sstabellini@21879 902
sstabellini@21879 903 if ( (vnc_bin = getenv("VNCVIEWER")) )
sstabellini@21879 904 args[0] = vnc_bin;
sstabellini@21879 905
sstabellini@21879 906 args[1] = libxl_sprintf(ctx, "%s:%d", vnc_listen, port);
sstabellini@21879 907
sstabellini@21879 908 if ( vnc_pass ) {
sstabellini@21879 909 char tmpname[] = "/tmp/vncautopass.XXXXXX";
sstabellini@21879 910 autopass_fd = mkstemp(tmpname);
sstabellini@21879 911 if ( autopass_fd < 0 )
sstabellini@21879 912 goto skip_autopass;
sstabellini@21879 913
sstabellini@21879 914 if ( unlink(tmpname) )
sstabellini@21879 915 /* should never happen */
sstabellini@21879 916 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unlink %s failed", tmpname);
sstabellini@21879 917
sstabellini@21879 918 if ( libxl_write_exactly(ctx, autopass_fd, vnc_pass, strlen(vnc_pass),
sstabellini@21879 919 tmpname, "vnc password") ) {
sstabellini@21879 920 do { close(autopass_fd); } while(errno == EINTR);
sstabellini@21879 921 goto skip_autopass;
sstabellini@21879 922 }
sstabellini@21879 923
sstabellini@21879 924 args[2] = "-autopass";
sstabellini@21879 925 }
sstabellini@21879 926
sstabellini@21879 927 skip_autopass:
sstabellini@21879 928 libxl_exec(autopass_fd, -1, -1, args[0], args);
sstabellini@21879 929 return 0;
sstabellini@21879 930 }
sstabellini@21879 931
keir@20462 932 static char ** libxl_build_device_model_args(struct libxl_ctx *ctx,
keir@20462 933 libxl_device_model_info *info,
keir@20462 934 libxl_device_nic *vifs,
keir@20462 935 int num_vifs)
keir@20462 936 {
keir@20462 937 int num = 0, i;
keir@20462 938 flexarray_t *dm_args;
keir@20462 939 dm_args = flexarray_make(16, 1);
keir@20462 940 if (!dm_args)
keir@20462 941 return NULL;
keir@20462 942
keir@20516 943 flexarray_set(dm_args, num++, "qemu-dm");
keir@20516 944 flexarray_set(dm_args, num++, "-d");
keir@20462 945
keir@20462 946 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->domid));
keir@20462 947
keir@20462 948 if (info->dom_name) {
keir@20516 949 flexarray_set(dm_args, num++, "-domain-name");
keir@20516 950 flexarray_set(dm_args, num++, info->dom_name);
keir@20462 951 }
keir@20462 952 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
keir@20516 953 flexarray_set(dm_args, num++, "-vnc");
keir@20462 954 if (info->vncdisplay) {
keir@20462 955 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
keir@21362 956 flexarray_set(
keir@21362 957 dm_args, num++,
keir@21362 958 libxl_sprintf(ctx, "%s:%d%s",
keir@21362 959 info->vnclisten,
keir@21362 960 info->vncdisplay,
keir@21362 961 info->vncpasswd ? ",password" : ""));
keir@20462 962 } else {
keir@20462 963 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "127.0.0.1:%d", info->vncdisplay));
keir@20462 964 }
keir@20462 965 } else if (info->vnclisten) {
keir@20462 966 if (strchr(info->vnclisten, ':') != NULL) {
keir@20516 967 flexarray_set(dm_args, num++, info->vnclisten);
keir@20462 968 } else {
keir@20462 969 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:0", info->vnclisten));
keir@20462 970 }
keir@20462 971 } else {
keir@20516 972 flexarray_set(dm_args, num++, "127.0.0.1:0");
keir@20462 973 }
keir@20462 974 if (info->vncunused) {
keir@20516 975 flexarray_set(dm_args, num++, "-vncunused");
keir@20462 976 }
keir@20462 977 }
keir@21378 978 if (info->sdl) {
keir@20516 979 flexarray_set(dm_args, num++, "-sdl");
keir@20462 980 if (info->opengl) {
keir@20516 981 flexarray_set(dm_args, num++, "-disable-opengl");
keir@20462 982 }
keir@20462 983 }
keir@20462 984 if (info->keymap) {
keir@20516 985 flexarray_set(dm_args, num++, "-k");
keir@20516 986 flexarray_set(dm_args, num++, info->keymap);
keir@20462 987 }
keir@20462 988 if (info->nographic && (!info->sdl && !info->vnc)) {
keir@20516 989 flexarray_set(dm_args, num++, "-nographic");
keir@20462 990 }
keir@20462 991 if (info->serial) {
keir@20516 992 flexarray_set(dm_args, num++, "-serial");
keir@20516 993 flexarray_set(dm_args, num++, info->serial);
keir@20462 994 }
keir@20509 995 if (info->type == XENFV) {
Ian@21733 996 int ioemu_vifs = 0;
Ian@21733 997
keir@20509 998 if (info->videoram) {
keir@20516 999 flexarray_set(dm_args, num++, "-videoram");
keir@20509 1000 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->videoram));
keir@20509 1001 }
keir@20509 1002 if (info->stdvga) {
keir@20516 1003 flexarray_set(dm_args, num++, "-std-vga");
keir@20509 1004 }
keir@20509 1005
keir@20509 1006 if (info->boot) {
keir@20516 1007 flexarray_set(dm_args, num++, "-boot");
keir@20516 1008 flexarray_set(dm_args, num++, info->boot);
keir@20509 1009 }
stefano@21890 1010 if (info->usb || info->usbdevice) {
keir@20516 1011 flexarray_set(dm_args, num++, "-usb");
keir@20509 1012 if (info->usbdevice) {
keir@20516 1013 flexarray_set(dm_args, num++, "-usbdevice");
keir@20516 1014 flexarray_set(dm_args, num++, info->usbdevice);
keir@20509 1015 }
keir@20509 1016 }
Ian@21801 1017 if (info->soundhw) {
Ian@21801 1018 flexarray_set(dm_args, num++, "-soundhw");
Ian@21801 1019 flexarray_set(dm_args, num++, info->soundhw);
Ian@21801 1020 }
keir@20509 1021 if (info->apic) {
keir@20516 1022 flexarray_set(dm_args, num++, "-acpi");
keir@20509 1023 }
keir@21570 1024 if (info->vcpus > 1) {
keir@21570 1025 flexarray_set(dm_args, num++, "-vcpus");
keir@21570 1026 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->vcpus));
keir@21570 1027 }
keir@21570 1028 if (info->vcpu_avail) {
keir@21570 1029 flexarray_set(dm_args, num++, "-vcpu_avail");
keir@21570 1030 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "0x%x", info->vcpu_avail));
keir@21570 1031 }
keir@20509 1032 for (i = 0; i < num_vifs; i++) {
keir@20509 1033 if (vifs[i].nictype == NICTYPE_IOEMU) {
keir@20780 1034 char *smac = libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20780 1035 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
keir@20780 1036 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
keir@20781 1037 if (!vifs[i].ifname)
keir@20781 1038 vifs[i].ifname = libxl_sprintf(ctx, "tap%d.%d", info->domid, vifs[i].devid - 1);
keir@20516 1039 flexarray_set(dm_args, num++, "-net");
keir@20509 1040 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "nic,vlan=%d,macaddr=%s,model=%s",
keir@20780 1041 vifs[i].devid, smac, vifs[i].model));
keir@20516 1042 flexarray_set(dm_args, num++, "-net");
keir@20509 1043 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "tap,vlan=%d,ifname=%s,bridge=%s",
keir@20509 1044 vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
Ian@21733 1045 ioemu_vifs++;
keir@20509 1046 }
keir@20462 1047 }
Ian@21733 1048 /* If we have no emulated nics, tell qemu not to create any */
Ian@21733 1049 if ( ioemu_vifs == 0 ) {
Ian@21733 1050 flexarray_set(dm_args, num++, "-net");
Ian@21733 1051 flexarray_set(dm_args, num++, "none");
Ian@21733 1052 }
keir@20462 1053 }
keir@20565 1054 if (info->saved_state) {
keir@20565 1055 flexarray_set(dm_args, num++, "-loadvm");
keir@20565 1056 flexarray_set(dm_args, num++, info->saved_state);
keir@20565 1057 }
keir@20509 1058 for (i = 0; info->extra && info->extra[i] != NULL; i++)
keir@20509 1059 flexarray_set(dm_args, num++, info->extra[i]);
keir@20516 1060 flexarray_set(dm_args, num++, "-M");
keir@20509 1061 if (info->type == XENPV)
keir@20516 1062 flexarray_set(dm_args, num++, "xenpv");
keir@20509 1063 else
keir@20516 1064 flexarray_set(dm_args, num++, "xenfv");
keir@20462 1065 flexarray_set(dm_args, num++, NULL);
keir@20462 1066
keir@20462 1067 return (char **) flexarray_contents(dm_args);
keir@20462 1068 }
keir@20462 1069
keir@20834 1070 void dm_xenstore_record_pid(void *for_spawn, pid_t innerchild)
keir@20834 1071 {
keir@20514 1072 struct libxl_device_model_starting *starting = for_spawn;
keir@20514 1073 char *kvs[3];
keir@20820 1074 int rc;
keir@20820 1075 struct xs_handle *xsh;
keir@20514 1076
keir@20820 1077 xsh = xs_daemon_open();
keir@20514 1078 /* we mustn't use the parent's handle in the child */
keir@20514 1079
keir@20514 1080 kvs[0] = "image/device-model-pid";
keir@21417 1081 if (asprintf(&kvs[1], "%d", innerchild) < 0)
keir@21417 1082 return;
keir@20514 1083 kvs[2] = NULL;
keir@20820 1084
keir@20820 1085 rc = xs_writev(xsh, XBT_NULL, starting->dom_path, kvs);
keir@20820 1086 if (rc)
keir@20820 1087 return;
keir@20820 1088 xs_daemon_close(xsh);
keir@20514 1089 }
keir@20514 1090
keir@20542 1091 static int libxl_vfb_and_vkb_from_device_model_info(struct libxl_ctx *ctx,
keir@20542 1092 libxl_device_model_info *info,
keir@20542 1093 libxl_device_vfb *vfb,
keir@20542 1094 libxl_device_vkb *vkb)
keir@20542 1095 {
keir@20542 1096 memset(vfb, 0x00, sizeof(libxl_device_vfb));
keir@20542 1097 memset(vkb, 0x00, sizeof(libxl_device_vkb));
keir@20542 1098
keir@20542 1099 vfb->backend_domid = 0;
keir@20542 1100 vfb->devid = 0;
keir@20542 1101 vfb->vnc = info->vnc;
keir@20542 1102 vfb->vnclisten = info->vnclisten;
keir@20542 1103 vfb->vncdisplay = info->vncdisplay;
keir@20542 1104 vfb->vncunused = info->vncunused;
keir@21362 1105 vfb->vncpasswd = info->vncpasswd;
keir@20542 1106 vfb->keymap = info->keymap;
keir@20542 1107 vfb->sdl = info->sdl;
keir@20542 1108 vfb->opengl = info->opengl;
keir@20542 1109
keir@20542 1110 vkb->backend_domid = 0;
keir@20542 1111 vkb->devid = 0;
keir@20542 1112 return 0;
keir@20542 1113 }
keir@20542 1114
keir@20542 1115 static int libxl_write_dmargs(struct libxl_ctx *ctx, int domid, int guest_domid, char **args)
keir@20542 1116 {
keir@20542 1117 int i;
keir@20542 1118 char *vm_path;
keir@20542 1119 char *dmargs, *path;
keir@20542 1120 int dmargs_size;
keir@20542 1121 struct xs_permissions roperm[2];
keir@20542 1122 xs_transaction_t t;
keir@20542 1123
keir@20542 1124 roperm[0].id = 0;
keir@20542 1125 roperm[0].perms = XS_PERM_NONE;
keir@20542 1126 roperm[1].id = domid;
keir@20542 1127 roperm[1].perms = XS_PERM_READ;
keir@20542 1128
keir@20542 1129 vm_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/vm", guest_domid));
keir@20542 1130
keir@20542 1131 i = 0;
keir@20542 1132 dmargs_size = 0;
keir@20542 1133 while (args[i] != NULL) {
keir@20542 1134 dmargs_size = dmargs_size + strlen(args[i]) + 1;
keir@20542 1135 i++;
keir@20542 1136 }
keir@20542 1137 dmargs_size++;
keir@20542 1138 dmargs = (char *) malloc(dmargs_size);
keir@20542 1139 i = 1;
keir@20542 1140 dmargs[0] = '\0';
keir@20542 1141 while (args[i] != NULL) {
keir@20542 1142 if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) {
keir@20542 1143 strcat(dmargs, " ");
keir@20542 1144 strcat(dmargs, args[i]);
keir@20542 1145 }
keir@20542 1146 i++;
keir@20542 1147 }
keir@20542 1148 path = libxl_sprintf(ctx, "%s/image/dmargs", vm_path);
keir@20542 1149
keir@20542 1150 retry_transaction:
keir@20542 1151 t = xs_transaction_start(ctx->xsh);
keir@20542 1152 xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs));
keir@20542 1153 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
keir@20542 1154 xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm));
keir@20542 1155 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 1156 if (errno == EAGAIN)
keir@20542 1157 goto retry_transaction;
keir@20542 1158 free(dmargs);
keir@20542 1159 return 0;
keir@20542 1160 }
keir@20542 1161
keir@20542 1162 static int libxl_create_stubdom(struct libxl_ctx *ctx,
keir@20542 1163 libxl_device_model_info *info,
keir@20542 1164 libxl_device_disk *disks, int num_disks,
keir@20542 1165 libxl_device_nic *vifs, int num_vifs,
keir@20542 1166 libxl_device_vfb *vfb,
keir@20542 1167 libxl_device_vkb *vkb,
keir@20542 1168 libxl_device_model_starting **starting_r)
keir@20542 1169 {
keir@20843 1170 int i, num_console = 1, ret;
keir@20570 1171 libxl_device_console *console;
keir@20542 1172 libxl_domain_create_info c_info;
keir@20542 1173 libxl_domain_build_info b_info;
keir@20542 1174 libxl_domain_build_state state;
keir@20542 1175 uint32_t domid;
keir@20542 1176 char **args;
keir@20542 1177 struct xs_permissions perm[2];
keir@20542 1178 xs_transaction_t t;
keir@20594 1179 libxl_device_model_starting *dm_starting = 0;
keir@20542 1180
keir@20542 1181 args = libxl_build_device_model_args(ctx, info, vifs, num_vifs);
keir@20542 1182 if (!args)
keir@20542 1183 return ERROR_FAIL;
keir@20542 1184
keir@20542 1185 memset(&c_info, 0x00, sizeof(libxl_domain_create_info));
keir@20542 1186 c_info.hvm = 0;
keir@20542 1187 c_info.name = libxl_sprintf(ctx, "%s-dm", libxl_domid_to_name(ctx, info->domid));
keir@20801 1188 for (i = 0; i < 16; i++)
keir@20801 1189 c_info.uuid[i] = info->uuid[i];
keir@20542 1190
keir@20542 1191 memset(&b_info, 0x00, sizeof(libxl_domain_build_info));
keir@20542 1192 b_info.max_vcpus = 1;
keir@20542 1193 b_info.max_memkb = 32 * 1024;
keir@20647 1194 b_info.target_memkb = b_info.max_memkb;
Ian@21848 1195 b_info.kernel.path = libxl_abs_path(ctx, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path());
keir@20542 1196 b_info.u.pv.cmdline = libxl_sprintf(ctx, " -d %d", info->domid);
Ian@21848 1197 b_info.u.pv.ramdisk.path = "";
keir@20542 1198 b_info.u.pv.features = "";
keir@20542 1199 b_info.hvm = 0;
keir@20542 1200
keir@20843 1201 ret = libxl_domain_make(ctx, &c_info, &domid);
keir@20843 1202 if (ret) return ret;
keir@20843 1203 ret = libxl_domain_build(ctx, &b_info, domid, &state);
keir@20843 1204 if (ret) return ret;
keir@20542 1205
keir@20542 1206 libxl_write_dmargs(ctx, domid, info->domid, args);
keir@20843 1207 libxl_xs_write(ctx, XBT_NULL,
keir@20843 1208 libxl_sprintf(ctx, "%s/image/device-model-domid", libxl_xs_get_dompath(ctx, info->domid)),
keir@20843 1209 "%d", domid);
keir@20843 1210 libxl_xs_write(ctx, XBT_NULL,
keir@20843 1211 libxl_sprintf(ctx, "%s/target", libxl_xs_get_dompath(ctx, domid)),
keir@20843 1212 "%d", info->domid);
gianni@21892 1213 ret = xc_domain_set_target(ctx->xch, domid, info->domid);
gianni@21892 1214 if (ret<0) {
gianni@21892 1215 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting target domain %d -> %d", domid, info->domid);
gianni@21892 1216 return ERROR_FAIL;
gianni@21892 1217 }
keir@20542 1218 xs_set_target(ctx->xsh, domid, info->domid);
keir@20542 1219
keir@20542 1220 perm[0].id = domid;
keir@20542 1221 perm[0].perms = XS_PERM_NONE;
keir@20542 1222 perm[1].id = info->domid;
keir@20542 1223 perm[1].perms = XS_PERM_READ;
keir@20542 1224 retry_transaction:
keir@20542 1225 t = xs_transaction_start(ctx->xsh);
keir@20542 1226 xs_mkdir(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid));
keir@20542 1227 xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm));
keir@20635 1228 xs_mkdir(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/%d/device/vfs", domid));
keir@20635 1229 xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm));
keir@20542 1230 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 1231 if (errno == EAGAIN)
keir@20542 1232 goto retry_transaction;
keir@20542 1233
keir@20542 1234 for (i = 0; i < num_disks; i++) {
keir@20781 1235 disks[i].domid = domid;
keir@20843 1236 ret = libxl_device_disk_add(ctx, domid, &disks[i]);
keir@20843 1237 if (ret) return ret;
keir@20542 1238 }
keir@20542 1239 for (i = 0; i < num_vifs; i++) {
keir@20781 1240 vifs[i].domid = domid;
keir@20843 1241 ret = libxl_device_nic_add(ctx, domid, &vifs[i]);
keir@20843 1242 if (ret) return ret;
keir@20542 1243 }
keir@20781 1244 vfb->domid = domid;
keir@20843 1245 ret = libxl_device_vfb_add(ctx, domid, vfb);
keir@20843 1246 if (ret) return ret;
keir@20781 1247 vkb->domid = domid;
keir@20843 1248 ret = libxl_device_vkb_add(ctx, domid, vkb);
keir@20843 1249 if (ret) return ret;
keir@20542 1250
keir@20570 1251 if (info->serial)
keir@20570 1252 num_console++;
keir@20843 1253
keir@20570 1254 console = libxl_calloc(ctx, num_console, sizeof(libxl_device_console));
keir@20843 1255 if (!console)
keir@20843 1256 return ERROR_NOMEM;
keir@20843 1257
keir@20570 1258 for (i = 0; i < num_console; i++) {
keir@20781 1259 console[i].devid = i;
keir@20781 1260 console[i].constype = CONSTYPE_IOEMU;
keir@20781 1261 console[i].domid = domid;
keir@20570 1262 if (!i)
keir@20781 1263 console[i].build_state = &state;
keir@20843 1264 ret = libxl_device_console_add(ctx, domid, &console[i]);
keir@20843 1265 if (ret) return ret;
keir@20570 1266 }
keir@20594 1267 if (libxl_create_xenpv_qemu(ctx, vfb, num_console, console, &dm_starting) < 0) {
keir@20594 1268 free(args);
gianni@21892 1269 return ERROR_FAIL;
keir@20594 1270 }
keir@20594 1271 if (libxl_confirm_device_model_startup(ctx, dm_starting) < 0) {
keir@20594 1272 free(args);
gianni@21892 1273 return ERROR_FAIL;
keir@20594 1274 }
keir@20542 1275
keir@20542 1276 libxl_domain_unpause(ctx, domid);
keir@20542 1277
keir@20594 1278 if (starting_r) {
keir@20594 1279 *starting_r = libxl_calloc(ctx, sizeof(libxl_device_model_starting), 1);
keir@20598 1280 (*starting_r)->domid = info->domid;
keir@20594 1281 (*starting_r)->dom_path = libxl_xs_get_dompath(ctx, info->domid);
keir@20594 1282 (*starting_r)->for_spawn = NULL;
keir@20594 1283 }
keir@20594 1284
keir@20542 1285 free(args);
keir@20542 1286 return 0;
keir@20542 1287 }
keir@20542 1288
keir@20462 1289 int libxl_create_device_model(struct libxl_ctx *ctx,
keir@20462 1290 libxl_device_model_info *info,
keir@20542 1291 libxl_device_disk *disks, int num_disks,
keir@20514 1292 libxl_device_nic *vifs, int num_vifs,
keir@20514 1293 libxl_device_model_starting **starting_r)
keir@20462 1294 {
keir@20546 1295 char *path, *logfile;
keir@20514 1296 int logfile_w, null;
keir@20546 1297 int rc;
keir@20462 1298 char **args;
keir@20594 1299 struct libxl_device_model_starting buf_starting, *p;
keir@21362 1300 xs_transaction_t t;
keir@21362 1301 char *vm_path;
keir@21362 1302 char **pass_stuff;
keir@20514 1303
keir@20542 1304 if (strstr(info->device_model, "stubdom-dm")) {
keir@20542 1305 libxl_device_vfb vfb;
keir@20542 1306 libxl_device_vkb vkb;
keir@20542 1307
keir@20542 1308 libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb);
keir@20542 1309 return libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r);
keir@20542 1310 }
keir@20542 1311
keir@20462 1312 args = libxl_build_device_model_args(ctx, info, vifs, num_vifs);
keir@20462 1313 if (!args)
keir@20462 1314 return ERROR_FAIL;
keir@20462 1315
keir@20462 1316 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid);
keir@20462 1317 xs_mkdir(ctx->xsh, XBT_NULL, path);
keir@21599 1318 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/disable_pf", path), "%d", !info->xen_platform_pci);
keir@20462 1319
keir@20546 1320 libxl_create_logfile(ctx, libxl_sprintf(ctx, "qemu-dm-%s", info->dom_name), &logfile);
keir@20467 1321 logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
keir@20546 1322 free(logfile);
keir@20462 1323 null = open("/dev/null", O_RDONLY);
keir@20514 1324
keir@20514 1325 if (starting_r) {
keir@20516 1326 rc = ERROR_NOMEM;
keir@20594 1327 *starting_r = libxl_calloc(ctx, sizeof(libxl_device_model_starting), 1);
keir@20516 1328 if (!*starting_r) goto xit;
keir@20594 1329 p = *starting_r;
keir@20611 1330 p->for_spawn = libxl_calloc(ctx, sizeof(struct libxl_spawn_starting), 1);
keir@20594 1331 } else {
keir@20594 1332 p = &buf_starting;
keir@20594 1333 p->for_spawn = NULL;
keir@20594 1334 }
keir@20514 1335
keir@20594 1336 p->domid = info->domid;
keir@20594 1337 p->dom_path = libxl_xs_get_dompath(ctx, info->domid);
keir@20594 1338 if (!p->dom_path) { libxl_free(ctx, p); return ERROR_FAIL; }
keir@20594 1339
keir@21362 1340 if (info->vncpasswd) {
keir@21362 1341 retry_transaction:
keir@21362 1342 /* Find uuid and the write the vnc password to xenstore for qemu. */
keir@21362 1343 t = xs_transaction_start(ctx->xsh);
keir@21362 1344 vm_path = libxl_xs_read(ctx,t,libxl_sprintf(ctx, "%s/vm", p->dom_path));
keir@21362 1345 if (vm_path) {
keir@21362 1346 /* Now write the vncpassword into it. */
keir@21362 1347 pass_stuff = libxl_calloc(ctx, 2, sizeof(char *));
keir@21362 1348 pass_stuff[0] = "vncpasswd";
keir@21362 1349 pass_stuff[1] = info->vncpasswd;
keir@21362 1350 libxl_xs_writev(ctx,t,vm_path,pass_stuff);
keir@21362 1351 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@21362 1352 if (errno == EAGAIN)
keir@21362 1353 goto retry_transaction;
keir@21362 1354 }
keir@21362 1355 }
keir@21362 1356
keir@20594 1357 rc = libxl_spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid);
keir@20514 1358 if (rc < 0) goto xit;
keir@20514 1359 if (!rc) { /* inner child */
keir@20833 1360 libxl_exec(null, logfile_w, logfile_w,
keir@21353 1361 libxl_abs_path(ctx, info->device_model, libxl_private_bindir_path()),
keir@21353 1362 args);
keir@20514 1363 }
keir@20514 1364
keir@20514 1365 rc = 0;
keir@20514 1366 xit:
keir@20516 1367 free(args);
keir@20462 1368 close(null);
keir@20462 1369 close(logfile_w);
keir@20462 1370
keir@20514 1371 return rc;
keir@20514 1372 }
keir@20514 1373
keir@20514 1374 int libxl_detach_device_model(struct libxl_ctx *ctx,
keir@20779 1375 libxl_device_model_starting *starting)
keir@20779 1376 {
keir@20514 1377 int rc;
keir@20594 1378 rc = libxl_spawn_detach(ctx, starting->for_spawn);
keir@20594 1379 if (starting->for_spawn) libxl_free(ctx, starting->for_spawn);
keir@20514 1380 libxl_free(ctx, starting);
keir@20514 1381 return rc;
keir@20514 1382 }
keir@20462 1383
keir@20514 1384
keir@20514 1385 int libxl_confirm_device_model_startup(struct libxl_ctx *ctx,
keir@20779 1386 libxl_device_model_starting *starting)
keir@20779 1387 {
keir@20514 1388 int problem = libxl_wait_for_device_model(ctx, starting->domid, "running",
keir@20514 1389 libxl_spawn_check,
keir@20594 1390 starting->for_spawn);
keir@20514 1391 int detach = libxl_detach_device_model(ctx, starting);
keir@20514 1392 return problem ? problem : detach;
keir@20542 1393 return 0;
keir@20462 1394 }
keir@20462 1395
keir@20514 1396
keir@20462 1397 /******************************************************************************/
keir@20566 1398
keir@20462 1399 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20462 1400 {
keir@20462 1401 flexarray_t *front;
keir@20462 1402 flexarray_t *back;
keir@20462 1403 char *backend_type;
keir@20462 1404 unsigned int boffset = 0;
keir@20462 1405 unsigned int foffset = 0;
keir@20462 1406 int devid;
keir@20462 1407 libxl_device device;
keir@20566 1408 int major, minor;
keir@20462 1409
keir@20462 1410 front = flexarray_make(16, 1);
keir@20462 1411 if (!front)
keir@20462 1412 return ERROR_NOMEM;
keir@20462 1413 back = flexarray_make(16, 1);
keir@20462 1414 if (!back) /* leaks front if error */
keir@20462 1415 return ERROR_NOMEM;
keir@20462 1416
keir@20462 1417 backend_type = device_disk_backend_type_of_phystype(disk->phystype);
keir@20462 1418 devid = device_disk_dev_number(disk->virtpath);
keir@20947 1419 if (devid==-1) {
keir@20947 1420 XL_LOG(ctx, XL_LOG_ERROR, "Invalid or unuspported"
keir@20947 1421 " virtual disk identifier %s", disk->virtpath);
keir@20947 1422 return ERROR_INVAL;
keir@20947 1423 }
keir@20462 1424
keir@20462 1425 device.backend_devid = devid;
keir@20462 1426 device.backend_domid = disk->backend_domid;
keir@20462 1427 device.devid = devid;
keir@20462 1428 device.domid = disk->domid;
keir@20462 1429 device.kind = DEVICE_VBD;
keir@20462 1430
keir@20462 1431 switch (disk->phystype) {
keir@20462 1432 case PHYSTYPE_PHY: {
keir@20462 1433
keir@20509 1434 device_physdisk_major_minor(disk->physpath, &major, &minor);
keir@20516 1435 flexarray_set(back, boffset++, "physical-device");
keir@20462 1436 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, minor));
keir@20462 1437
keir@20516 1438 flexarray_set(back, boffset++, "params");
keir@20516 1439 flexarray_set(back, boffset++, disk->physpath);
keir@20462 1440
keir@20462 1441 device.backend_kind = DEVICE_VBD;
keir@20462 1442 break;
keir@20462 1443 }
keir@20566 1444 case PHYSTYPE_FILE:
keir@20566 1445 /* let's pretend is tap:aio for the moment */
keir@20566 1446 disk->phystype = PHYSTYPE_AIO;
Christoph@21889 1447 case PHYSTYPE_AIO:
Christoph@21889 1448 case PHYSTYPE_QCOW:
Christoph@21889 1449 case PHYSTYPE_QCOW2:
Christoph@21889 1450 case PHYSTYPE_VHD:
Christoph@21889 1451 if (libxl_blktap_enabled(ctx)) {
Christoph@21889 1452 const char *dev = libxl_blktap_devpath(ctx,
Christoph@21889 1453 disk->physpath, disk->phystype);
keir@21632 1454 if (!dev)
gianni@21892 1455 return ERROR_FAIL;
keir@20566 1456 flexarray_set(back, boffset++, "tapdisk-params");
keir@20566 1457 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20566 1458 flexarray_set(back, boffset++, "params");
Ian@21845 1459 flexarray_set(back, boffset++, libxl_strdup(ctx, dev));
keir@20566 1460 backend_type = "phy";
keir@20566 1461 device_physdisk_major_minor(dev, &major, &minor);
keir@20566 1462 flexarray_set(back, boffset++, "physical-device");
keir@20566 1463 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, minor));
keir@20566 1464 device.backend_kind = DEVICE_VBD;
keir@20566 1465
keir@20566 1466 break;
keir@20566 1467 }
keir@20516 1468 flexarray_set(back, boffset++, "params");
keir@20462 1469 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s",
keir@20462 1470 device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20462 1471
keir@20462 1472 device.backend_kind = DEVICE_TAP;
keir@20462 1473 break;
Christoph@21889 1474
keir@20846 1475 default:
keir@20846 1476 XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", disk->phystype);
keir@20846 1477 return ERROR_INVAL;
keir@20462 1478 }
keir@20462 1479
keir@20516 1480 flexarray_set(back, boffset++, "frontend-id");
keir@20462 1481 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", disk->domid));
keir@20516 1482 flexarray_set(back, boffset++, "online");
keir@20516 1483 flexarray_set(back, boffset++, "1");
keir@20516 1484 flexarray_set(back, boffset++, "removable");
keir@20462 1485 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", (disk->unpluggable) ? 1 : 0));
keir@20516 1486 flexarray_set(back, boffset++, "bootable");
keir@20509 1487 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1488 flexarray_set(back, boffset++, "state");
keir@20462 1489 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1490 flexarray_set(back, boffset++, "dev");
keir@20516 1491 flexarray_set(back, boffset++, disk->virtpath);
keir@20516 1492 flexarray_set(back, boffset++, "type");
keir@20516 1493 flexarray_set(back, boffset++, backend_type);
keir@20516 1494 flexarray_set(back, boffset++, "mode");
keir@20516 1495 flexarray_set(back, boffset++, disk->readwrite ? "w" : "r");
keir@20462 1496
keir@20516 1497 flexarray_set(front, foffset++, "backend-id");
keir@20462 1498 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", disk->backend_domid));
keir@20516 1499 flexarray_set(front, foffset++, "state");
keir@20462 1500 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1501 flexarray_set(front, foffset++, "virtual-device");
keir@20462 1502 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", devid));
keir@20516 1503 flexarray_set(front, foffset++, "device-type");
keir@20516 1504 flexarray_set(front, foffset++, disk->is_cdrom ? "cdrom" : "disk");
keir@20462 1505
keir@20462 1506 if (0 /* protocol != native*/) {
keir@20516 1507 flexarray_set(front, foffset++, "protocol");
keir@20516 1508 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
keir@20462 1509 }
keir@20462 1510
keir@20462 1511 libxl_device_generic_add(ctx, &device,
keir@20462 1512 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20462 1513 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20516 1514 flexarray_free(back);
keir@20516 1515 flexarray_free(front);
keir@20462 1516 return 0;
keir@20462 1517 }
keir@20462 1518
keir@20626 1519 int libxl_device_disk_del(struct libxl_ctx *ctx,
keir@20626 1520 libxl_device_disk *disk, int wait)
keir@20462 1521 {
keir@20626 1522 libxl_device device;
keir@20626 1523 int devid;
keir@20462 1524
keir@20626 1525 devid = device_disk_dev_number(disk->virtpath);
keir@20626 1526 device.backend_domid = disk->backend_domid;
keir@20626 1527 device.backend_devid = devid;
keir@20626 1528 device.backend_kind =
keir@20626 1529 (disk->phystype == PHYSTYPE_PHY) ? DEVICE_VBD : DEVICE_TAP;
keir@20626 1530 device.domid = disk->domid;
keir@20626 1531 device.devid = devid;
keir@20626 1532 device.kind = DEVICE_VBD;
keir@20626 1533 return libxl_device_del(ctx, &device, wait);
keir@20462 1534 }
keir@20462 1535
Ian@21849 1536 const char * libxl_device_disk_local_attach(struct libxl_ctx *ctx, libxl_device_disk *disk)
Ian@21849 1537 {
Christoph@21889 1538 const char *dev = NULL;
Ian@21849 1539 int phystype = disk->phystype;
Ian@21849 1540 switch (phystype) {
Ian@21849 1541 case PHYSTYPE_PHY: {
Ian@21849 1542 fprintf(stderr, "attaching PHY disk %s to domain 0\n", disk->physpath);
Ian@21849 1543 dev = disk->physpath;
Ian@21849 1544 break;
Ian@21849 1545 }
Ian@21849 1546 case PHYSTYPE_FILE:
Ian@21849 1547 /* let's pretend is tap:aio for the moment */
Ian@21849 1548 phystype = PHYSTYPE_AIO;
Christoph@21889 1549 case PHYSTYPE_AIO:
Christoph@21889 1550 case PHYSTYPE_QCOW:
Christoph@21889 1551 case PHYSTYPE_QCOW2:
Christoph@21889 1552 case PHYSTYPE_VHD:
Christoph@21889 1553 if (libxl_blktap_enabled(ctx))
Christoph@21889 1554 dev = libxl_blktap_devpath(ctx, disk->physpath, phystype);
Ian@21849 1555 break;
Christoph@21889 1556
Ian@21849 1557 default:
Ian@21849 1558 XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", phystype);
Ian@21849 1559 break;
Ian@21849 1560 }
Ian@21849 1561 return dev;
Ian@21849 1562 }
Ian@21849 1563
Ian@21849 1564 int libxl_device_disk_local_detach(struct libxl_ctx *ctx, libxl_device_disk *disk)
Ian@21849 1565 {
Ian@21849 1566 /* Nothing to do for PHYSTYPE_PHY. */
Ian@21849 1567
Ian@21849 1568 /*
Ian@21849 1569 * For other device types assume that the blktap2 process is
Ian@21849 1570 * needed by the soon to be started domain and do nothing.
Ian@21849 1571 */
Ian@21849 1572
Ian@21849 1573 return 0;
Ian@21849 1574 }
Ian@21849 1575
keir@20462 1576 /******************************************************************************/
keir@20462 1577 int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
keir@20462 1578 {
keir@20462 1579 flexarray_t *front;
keir@20462 1580 flexarray_t *back;
keir@20462 1581 unsigned int boffset = 0;
keir@20462 1582 unsigned int foffset = 0;
keir@20462 1583 libxl_device device;
keir@21407 1584 char *dompath, **l;
keir@21407 1585 unsigned int nb;
keir@20462 1586
keir@20462 1587 front = flexarray_make(16, 1);
keir@20462 1588 if (!front)
keir@20462 1589 return ERROR_NOMEM;
keir@20462 1590 back = flexarray_make(16, 1);
keir@20462 1591 if (!back)
keir@20462 1592 return ERROR_NOMEM;
keir@20462 1593
keir@21407 1594 if (nic->devid == -1) {
keir@21407 1595 if (!(dompath = libxl_xs_get_dompath(ctx, domid))) {
keir@21407 1596 return ERROR_FAIL;
keir@21407 1597 }
keir@21407 1598 if (!(l = libxl_xs_directory(ctx, XBT_NULL,
keir@21407 1599 libxl_sprintf(ctx, "%s/device/vif", dompath), &nb))) {
keir@21407 1600 nic->devid = 0;
keir@21407 1601 } else {
keir@21407 1602 nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
keir@21407 1603 libxl_free(ctx, l);
keir@21407 1604 }
keir@21407 1605 }
keir@21407 1606
keir@20462 1607 device.backend_devid = nic->devid;
keir@20462 1608 device.backend_domid = nic->backend_domid;
keir@20462 1609 device.backend_kind = DEVICE_VIF;
keir@20462 1610 device.devid = nic->devid;
keir@20462 1611 device.domid = nic->domid;
keir@20462 1612 device.kind = DEVICE_VIF;
keir@20462 1613
keir@20516 1614 flexarray_set(back, boffset++, "frontend-id");
keir@20462 1615 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->domid));
keir@20516 1616 flexarray_set(back, boffset++, "online");
keir@20516 1617 flexarray_set(back, boffset++, "1");
keir@20516 1618 flexarray_set(back, boffset++, "state");
keir@20462 1619 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1620 flexarray_set(back, boffset++, "script");
keir@20516 1621 flexarray_set(back, boffset++, nic->script);
keir@20516 1622 flexarray_set(back, boffset++, "mac");
keir@20462 1623 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1624 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1625 nic->mac[3], nic->mac[4], nic->mac[5]));
Ian@21732 1626 flexarray_set(back, boffset++, "bridge");
Ian@21845 1627 flexarray_set(back, boffset++, libxl_strdup(ctx, nic->bridge));
keir@20516 1628 flexarray_set(back, boffset++, "handle");
keir@20462 1629 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->devid));
keir@20462 1630
keir@20516 1631 flexarray_set(front, foffset++, "backend-id");
keir@20462 1632 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->backend_domid));
keir@20516 1633 flexarray_set(front, foffset++, "state");
keir@20462 1634 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1635 flexarray_set(front, foffset++, "handle");
keir@20462 1636 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->devid));
keir@20516 1637 flexarray_set(front, foffset++, "mac");
keir@20462 1638 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1639 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1640 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20462 1641 if (0 /* protocol != native*/) {
keir@20516 1642 flexarray_set(front, foffset++, "protocol");
keir@20516 1643 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
keir@20462 1644 }
keir@20462 1645
keir@20462 1646 libxl_device_generic_add(ctx, &device,
keir@20462 1647 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20462 1648 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20462 1649
keir@20462 1650 /* FIXME: wait for plug */
keir@20516 1651 flexarray_free(back);
keir@20516 1652 flexarray_free(front);
keir@20462 1653 return 0;
keir@20462 1654 }
keir@20462 1655
keir@20626 1656 int libxl_device_nic_del(struct libxl_ctx *ctx,
keir@20626 1657 libxl_device_nic *nic, int wait)
keir@20462 1658 {
keir@20626 1659 libxl_device device;
keir@20462 1660
keir@20626 1661 device.backend_devid = nic->devid;
keir@20626 1662 device.backend_domid = nic->backend_domid;
keir@20626 1663 device.backend_kind = DEVICE_VIF;
keir@20626 1664 device.devid = nic->devid;
keir@20626 1665 device.domid = nic->domid;
keir@20626 1666 device.kind = DEVICE_VIF;
keir@20626 1667
keir@20626 1668 return libxl_device_del(ctx, &device, wait);
keir@20462 1669 }
keir@20462 1670
keir@21408 1671 libxl_nicinfo *libxl_list_nics(struct libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
keir@21408 1672 {
keir@21408 1673 char *dompath, *nic_path_fe;
keir@21408 1674 char **l;
keir@21408 1675 char *val, *tok;
keir@21408 1676 unsigned int nb_nics, i;
keir@21408 1677 libxl_nicinfo *res, *nics;
keir@21408 1678
keir@21408 1679 dompath = libxl_xs_get_dompath(ctx, domid);
keir@21408 1680 if (!dompath) {
keir@21408 1681 return NULL;
keir@21408 1682 }
keir@21408 1683 l = libxl_xs_directory(ctx, XBT_NULL,
keir@21408 1684 libxl_sprintf(ctx, "%s/device/vif", dompath), &nb_nics);
keir@21408 1685 if (!l) {
keir@21408 1686 return NULL;
keir@21408 1687 }
keir@21408 1688 res = libxl_calloc(ctx, nb_nics, sizeof (libxl_device_nic));
keir@21408 1689 if (!res) {
keir@21408 1690 libxl_free(ctx, l);
keir@21408 1691 return NULL;
keir@21408 1692 }
keir@21408 1693 nics = res;
keir@21408 1694 for (*nb = nb_nics; nb_nics > 0; --nb_nics, ++l, ++nics) {
keir@21408 1695 nic_path_fe = libxl_sprintf(ctx, "%s/device/vif/%s", dompath, *l);
keir@21408 1696
keir@21408 1697 nics->backend = libxl_xs_read(ctx, XBT_NULL,
keir@21408 1698 libxl_sprintf(ctx, "%s/backend", nic_path_fe));
keir@21408 1699 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", nic_path_fe));
keir@21408 1700 nics->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21408 1701
keir@21408 1702 nics->devid = strtoul(*l, NULL, 10);
keir@21408 1703 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", nic_path_fe));
keir@21408 1704 nics->state = val ? strtoul(val, NULL, 10) : -1;
keir@21408 1705 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", nic_path_fe));
keir@21408 1706 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21408 1707 ++i, tok = strtok(NULL, ":")) {
keir@21408 1708 nics->mac[i] = strtoul(tok, NULL, 16);
keir@21408 1709 }
keir@21408 1710 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/event-channel", nic_path_fe));
keir@21408 1711 nics->evtch = val ? strtol(val, NULL, 10) : -1;
keir@21408 1712 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/tx-ring-ref", nic_path_fe));
keir@21408 1713 nics->rref_tx = val ? strtol(val, NULL, 10) : -1;
keir@21408 1714 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/rx-ring-ref", nic_path_fe));
keir@21408 1715 nics->rref_rx = val ? strtol(val, NULL, 10) : -1;
keir@21408 1716 nics->frontend = libxl_xs_read(ctx, XBT_NULL,
keir@21408 1717 libxl_sprintf(ctx, "%s/frontend", nics->backend));
keir@21408 1718 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", nics->backend));
keir@21408 1719 nics->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21408 1720 nics->script = libxl_xs_read(ctx, XBT_NULL,
keir@21408 1721 libxl_sprintf(ctx, "%s/script", nics->backend));
keir@21408 1722
keir@21408 1723 libxl_free(ctx, nic_path_fe);
keir@21408 1724 }
keir@21408 1725
keir@21408 1726 libxl_free(ctx, l);
keir@21408 1727 return res;
keir@21408 1728 }
keir@21408 1729
keir@21580 1730 /******************************************************************************/
keir@21580 1731 int libxl_device_net2_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2)
keir@21580 1732 {
keir@21580 1733 flexarray_t *front, *back;
keir@21580 1734 unsigned int boffset = 0, foffset = 0;
keir@21580 1735 libxl_device device;
keir@21580 1736 char *dompath, *dom, **l;
keir@21580 1737 unsigned int nb;
keir@21580 1738
keir@21580 1739 front = flexarray_make(16, 1);
keir@21580 1740 if (!front)
keir@21580 1741 return ERROR_NOMEM;
keir@21580 1742 back = flexarray_make(16, 1);
keir@21580 1743 if (!back)
keir@21580 1744 return ERROR_NOMEM;
keir@21580 1745
keir@21580 1746 if (!(dompath = libxl_xs_get_dompath(ctx, domid))) {
keir@21580 1747 return ERROR_FAIL;
keir@21580 1748 }
keir@21580 1749 dom = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/name", dompath));
keir@21580 1750
keir@21580 1751 if (net2->devid == -1) {
keir@21580 1752 if (!(l = libxl_xs_directory(ctx, XBT_NULL,
keir@21580 1753 libxl_sprintf(ctx, "%s/device/vif2", dompath), &nb))) {
keir@21580 1754 net2->devid = 0;
keir@21580 1755 } else {
keir@21580 1756 net2->devid = strtoul(l[nb - 1], NULL, 10) + 1;
keir@21580 1757 libxl_free(ctx, l);
keir@21580 1758 }
keir@21580 1759 }
keir@21580 1760
keir@21580 1761 device.backend_devid = net2->devid;
keir@21580 1762 device.backend_domid = net2->backend_domid;
keir@21580 1763 device.backend_kind = DEVICE_VIF2;
keir@21580 1764 device.devid = net2->devid;
keir@21580 1765 device.domid = net2->domid;
keir@21580 1766 device.kind = DEVICE_VIF2;
keir@21580 1767
keir@21580 1768 flexarray_set(back, boffset++, "domain");
keir@21580 1769 flexarray_set(back, boffset++, dom);
keir@21580 1770 flexarray_set(back, boffset++, "frontend-id");
keir@21580 1771 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->domid));
keir@21580 1772
keir@21580 1773 flexarray_set(back, boffset++, "local-trusted");
keir@21580 1774 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->back_trusted));
keir@21580 1775 flexarray_set(back, boffset++, "mac");
keir@21580 1776 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1777 net2->back_mac[0], net2->back_mac[1],
keir@21580 1778 net2->back_mac[2], net2->back_mac[3],
keir@21580 1779 net2->back_mac[4], net2->back_mac[5]));
keir@21580 1780
keir@21580 1781 flexarray_set(back, boffset++, "remote-trusted");
keir@21580 1782 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->trusted));
keir@21580 1783 flexarray_set(back, boffset++, "remote-mac");
keir@21580 1784 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1785 net2->front_mac[0], net2->front_mac[1],
keir@21580 1786 net2->front_mac[2], net2->front_mac[3],
keir@21580 1787 net2->front_mac[4], net2->front_mac[5]));
keir@21580 1788
keir@21580 1789 flexarray_set(back, boffset++, "max-bypasses");
keir@21580 1790 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->max_bypasses));
keir@21580 1791 flexarray_set(back, boffset++, "filter-mac");
keir@21580 1792 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", !!(net2->filter_mac)));
keir@21580 1793 flexarray_set(back, boffset++, "handle");
keir@21580 1794 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->devid));
keir@21580 1795 flexarray_set(back, boffset++, "online");
keir@21580 1796 flexarray_set(back, boffset++, "1");
keir@21580 1797 flexarray_set(back, boffset++, "state");
keir@21580 1798 flexarray_set(back, boffset++, "1");
keir@21580 1799
keir@21580 1800 flexarray_set(front, foffset++, "backend-id");
keir@21580 1801 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->backend_domid));
keir@21580 1802
keir@21580 1803 flexarray_set(front, foffset++, "local-trusted");
keir@21580 1804 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->trusted));
keir@21580 1805 flexarray_set(front, foffset++, "mac");
keir@21580 1806 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1807 net2->front_mac[0], net2->front_mac[1],
keir@21580 1808 net2->front_mac[2], net2->front_mac[3],
keir@21580 1809 net2->front_mac[4], net2->front_mac[5]));
keir@21580 1810
keir@21580 1811 flexarray_set(front, foffset++, "remote-trusted");
keir@21580 1812 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->back_trusted));
keir@21580 1813 flexarray_set(front, foffset++, "remote-mac");
keir@21580 1814 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1815 net2->back_mac[0], net2->back_mac[1],
keir@21580 1816 net2->back_mac[2], net2->back_mac[3],
keir@21580 1817 net2->back_mac[4], net2->back_mac[5]));
keir@21580 1818
keir@21580 1819 flexarray_set(front, foffset++, "filter-mac");
keir@21580 1820 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", !!(net2->filter_mac)));
keir@21580 1821 flexarray_set(front, foffset++, "state");
keir@21580 1822 flexarray_set(front, foffset++, "1");
keir@21580 1823
keir@21580 1824 libxl_device_generic_add(ctx, &device,
keir@21580 1825 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@21580 1826 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@21580 1827
keir@21580 1828 /* FIXME: wait for plug */
keir@21580 1829 flexarray_free(back);
keir@21580 1830 flexarray_free(front);
keir@21580 1831 return 0;
keir@21580 1832 }
keir@21408 1833
keir@21581 1834 libxl_net2info *libxl_device_net2_list(struct libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
keir@21581 1835 {
keir@21581 1836 char *dompath, *net2_path_fe;
keir@21581 1837 char **l;
keir@21581 1838 char *val, *tok;
keir@21581 1839 unsigned int nb_net2s, i;
keir@21581 1840 libxl_net2info *res, *net2s;
keir@21581 1841
keir@21581 1842 dompath = libxl_xs_get_dompath(ctx, domid);
keir@21581 1843 if (!dompath) {
keir@21581 1844 return NULL;
keir@21581 1845 }
keir@21581 1846 l = libxl_xs_directory(ctx, XBT_NULL,
keir@21581 1847 libxl_sprintf(ctx, "%s/device/vif2", dompath), &nb_net2s);
keir@21581 1848 if (!l) {
keir@21581 1849 return NULL;
keir@21581 1850 }
keir@21581 1851 res = libxl_calloc(ctx, nb_net2s, sizeof (libxl_net2info));
keir@21581 1852 if (!res) {
keir@21581 1853 libxl_free(ctx, l);
keir@21581 1854 return NULL;
keir@21581 1855 }
keir@21581 1856 net2s = res;
keir@21581 1857 for (*nb = nb_net2s; nb_net2s > 0; --nb_net2s, ++l, ++net2s) {
keir@21581 1858 net2_path_fe = libxl_sprintf(ctx, "%s/device/vif2/%s", dompath, *l);
keir@21581 1859
keir@21581 1860 net2s->backend = libxl_xs_read(ctx, XBT_NULL,
keir@21581 1861 libxl_sprintf(ctx, "%s/backend", net2_path_fe));
keir@21581 1862 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", net2_path_fe));
keir@21581 1863 net2s->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1864
keir@21581 1865 net2s->devid = strtoul(*l, NULL, 10);
keir@21581 1866 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", net2_path_fe));
keir@21581 1867 net2s->state = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1868
keir@21581 1869 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", net2_path_fe));
keir@21581 1870 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21581 1871 ++i, tok = strtok(NULL, ":")) {
keir@21581 1872 net2s->mac[i] = strtoul(tok, NULL, 16);
keir@21581 1873 }
keir@21581 1874 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/remote-trusted", net2_path_fe));
keir@21581 1875 net2s->trusted = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1876
keir@21581 1877 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/remote-mac", net2_path_fe));
keir@21581 1878 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21581 1879 ++i, tok = strtok(NULL, ":")) {
keir@21581 1880 net2s->back_mac[i] = strtoul(tok, NULL, 16);
keir@21581 1881 }
keir@21581 1882 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/filter-mac", net2_path_fe));
keir@21581 1883 net2s->filter_mac = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1884
keir@21581 1885 net2s->frontend = libxl_xs_read(ctx, XBT_NULL,
keir@21581 1886 libxl_sprintf(ctx, "%s/frontend", net2s->backend));
keir@21581 1887 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", net2s->backend));
keir@21581 1888 net2s->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1889 libxl_free(ctx, net2_path_fe);
keir@21581 1890 }
keir@21581 1891
keir@21581 1892 libxl_free(ctx, l);
keir@21581 1893 return res;
keir@21581 1894 }
keir@21581 1895
keir@21582 1896 int libxl_device_net2_del(struct libxl_ctx *ctx, libxl_device_net2 *net2, int wait)
keir@21582 1897 {
keir@21582 1898 libxl_device device;
keir@21582 1899
keir@21582 1900 device.backend_devid = net2->devid;
keir@21582 1901 device.backend_domid = net2->backend_domid;
keir@21582 1902 device.backend_kind = DEVICE_VIF2;
keir@21582 1903 device.devid = net2->devid;
keir@21582 1904 device.domid = net2->domid;
keir@21582 1905 device.kind = DEVICE_VIF2;
keir@21582 1906
keir@21582 1907 return libxl_device_del(ctx, &device, wait);
keir@21582 1908 }
keir@21582 1909
keir@21581 1910
keir@20462 1911 /******************************************************************************/
keir@20509 1912 int libxl_device_console_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
keir@20462 1913 {
keir@20509 1914 flexarray_t *front;
keir@20509 1915 flexarray_t *back;
keir@20509 1916 unsigned int boffset = 0;
keir@20509 1917 unsigned int foffset = 0;
keir@20509 1918 libxl_device device;
keir@20509 1919
keir@20509 1920 if (console->build_state) {
keir@20509 1921 xs_transaction_t t;
keir@20509 1922 char **ents = (char **) libxl_calloc(ctx, 9, sizeof(char *));
keir@20516 1923 ents[0] = "console/port";
keir@20509 1924 ents[1] = libxl_sprintf(ctx, "%"PRIu32, console->build_state->console_port);
keir@20516 1925 ents[2] = "console/ring-ref";
keir@20509 1926 ents[3] = libxl_sprintf(ctx, "%lu", console->build_state->console_mfn);
keir@20516 1927 ents[4] = "console/limit";
keir@20509 1928 ents[5] = libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT);
keir@20516 1929 ents[6] = "console/type";
keir@20509 1930 if (console->constype == CONSTYPE_XENCONSOLED)
keir@20509 1931 ents[7] = "xenconsoled";
keir@20509 1932 else
keir@20509 1933 ents[7] = "ioemu";
keir@20509 1934 retry_transaction:
keir@20509 1935 t = xs_transaction_start(ctx->xsh);
keir@20516 1936 libxl_xs_writev(ctx, t, libxl_xs_get_dompath(ctx, console->domid), ents);
keir@20509 1937 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20509 1938 if (errno == EAGAIN)
keir@20509 1939 goto retry_transaction;
keir@20509 1940 }
keir@20509 1941
keir@20509 1942 front = flexarray_make(16, 1);
keir@20509 1943 if (!front)
keir@20509 1944 return ERROR_NOMEM;
keir@20509 1945 back = flexarray_make(16, 1);
keir@20509 1946 if (!back)
keir@20509 1947 return ERROR_NOMEM;
keir@20509 1948
keir@20509 1949 device.backend_devid = console->devid;
keir@20509 1950 device.backend_domid = console->backend_domid;
keir@20509 1951 device.backend_kind = DEVICE_CONSOLE;
keir@20509 1952 device.devid = console->devid;
keir@20509 1953 device.domid = console->domid;
keir@20509 1954 device.kind = DEVICE_CONSOLE;
keir@20509 1955
keir@20516 1956 flexarray_set(back, boffset++, "frontend-id");
keir@20509 1957 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", console->domid));
keir@20516 1958 flexarray_set(back, boffset++, "online");
keir@20516 1959 flexarray_set(back, boffset++, "1");
keir@20516 1960 flexarray_set(back, boffset++, "state");
keir@20509 1961 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1962 flexarray_set(back, boffset++, "domain");
keir@20516 1963 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20516 1964 flexarray_set(back, boffset++, "protocol");
keir@20516 1965 flexarray_set(back, boffset++, LIBXL_XENCONSOLE_PROTOCOL);
keir@20509 1966
keir@20516 1967 flexarray_set(front, foffset++, "backend-id");
keir@20509 1968 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", console->backend_domid));
keir@20516 1969 flexarray_set(front, foffset++, "state");
keir@20509 1970 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1971 flexarray_set(front, foffset++, "limit");
keir@20509 1972 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT));
keir@20516 1973 flexarray_set(front, foffset++, "protocol");
keir@20516 1974 flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL);
keir@20516 1975 flexarray_set(front, foffset++, "type");
keir@20509 1976 if (console->constype == CONSTYPE_XENCONSOLED)
keir@20516 1977 flexarray_set(front, foffset++, "xenconsoled");
keir@20509 1978 else
keir@20516 1979 flexarray_set(front, foffset++, "ioemu");
keir@20509 1980
keir@20509 1981 libxl_device_generic_add(ctx, &device,
keir@20509 1982 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 1983 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20516 1984 flexarray_free(back);
keir@20516 1985 flexarray_free(front);
keir@20509 1986
keir@20509 1987 return 0;
keir@20509 1988 }
keir@20509 1989
keir@20509 1990 /******************************************************************************/
keir@20509 1991 int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
keir@20509 1992 {
keir@20509 1993 flexarray_t *front;
keir@20509 1994 flexarray_t *back;
keir@20509 1995 unsigned int boffset = 0;
keir@20509 1996 unsigned int foffset = 0;
keir@20509 1997 libxl_device device;
keir@20509 1998
keir@20509 1999 front = flexarray_make(16, 1);
keir@20509 2000 if (!front)
keir@20509 2001 return ERROR_NOMEM;
keir@20509 2002 back = flexarray_make(16, 1);
keir@20509 2003 if (!back)
keir@20509 2004 return ERROR_NOMEM;
keir@20509 2005
keir@20509 2006 device.backend_devid = vkb->devid;
keir@20509 2007 device.backend_domid = vkb->backend_domid;
keir@20509 2008 device.backend_kind = DEVICE_VKBD;
keir@20509 2009 device.devid = vkb->devid;
keir@20509 2010 device.domid = vkb->domid;
keir@20509 2011 device.kind = DEVICE_VKBD;
keir@20509 2012
keir@20516 2013 flexarray_set(back, boffset++, "frontend-id");
keir@20509 2014 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vkb->domid));
keir@20516 2015 flexarray_set(back, boffset++, "online");
keir@20516 2016 flexarray_set(back, boffset++, "1");
keir@20516 2017 flexarray_set(back, boffset++, "state");
keir@20509 2018 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 2019 flexarray_set(back, boffset++, "domain");
keir@20516 2020 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20509 2021
keir@20516 2022 flexarray_set(front, foffset++, "backend-id");
keir@20509 2023 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vkb->backend_domid));
keir@20516 2024 flexarray_set(front, foffset++, "state");
keir@20509 2025 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 2026
keir@20509 2027 libxl_device_generic_add(ctx, &device,
keir@20509 2028 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 2029 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20516 2030 flexarray_free(back);
keir@20516 2031 flexarray_free(front);
keir@20509 2032
keir@20509 2033 return 0;
keir@20462 2034 }
keir@20462 2035
keir@20462 2036 int libxl_device_vkb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 2037 {
keir@20462 2038 return ERROR_NI;
keir@20462 2039 }
keir@20462 2040
keir@20462 2041 int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 2042 {
keir@20462 2043 return ERROR_NI;
keir@20462 2044 }
keir@20462 2045
keir@20637 2046 libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t domid, int *num)
keir@20637 2047 {
keir@20637 2048 char *be_path_tap, *be_path_vbd;
keir@21411 2049 libxl_device_disk *dend, *disks, *ret = NULL;
keir@21411 2050 char **b, **l = NULL;
keir@20637 2051 unsigned int numl;
keir@20637 2052 char *type;
keir@20637 2053
keir@20637 2054 be_path_vbd = libxl_sprintf(ctx, "%s/backend/vbd/%d", libxl_xs_get_dompath(ctx, 0), domid);
keir@20637 2055 be_path_tap = libxl_sprintf(ctx, "%s/backend/tap/%d", libxl_xs_get_dompath(ctx, 0), domid);
keir@20637 2056
keir@21411 2057 b = l = libxl_xs_directory(ctx, XBT_NULL, be_path_vbd, &numl);
keir@20637 2058 if (l) {
keir@21411 2059 ret = realloc(ret, sizeof(libxl_device_disk) * numl);
keir@21411 2060 disks = ret;
keir@21411 2061 *num = numl;
keir@21411 2062 dend = ret + *num;
keir@21411 2063 for (; disks < dend; ++disks, ++l) {
keir@21411 2064 disks->backend_domid = 0;
keir@21411 2065 disks->domid = domid;
keir@21411 2066 disks->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/params", be_path_vbd, *l));
keir@21411 2067 libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/type", be_path_vbd, *l)), &(disks->phystype));
keir@21411 2068 disks->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/dev", be_path_vbd, *l));
keir@21411 2069 disks->unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/removable", be_path_vbd, *l)));
keir@21411 2070 if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/mode", be_path_vbd, *l)), "w"))
keir@21411 2071 disks->readwrite = 1;
keir@20637 2072 else
keir@21411 2073 disks->readwrite = 0;
keir@21411 2074 type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/frontend", be_path_vbd, *l))));
keir@21411 2075 disks->is_cdrom = !strcmp(type, "cdrom");
keir@20637 2076 }
keir@21411 2077 libxl_free(ctx, b);
keir@20637 2078 }
keir@21411 2079 b = l = libxl_xs_directory(ctx, XBT_NULL, be_path_tap, &numl);
keir@20637 2080 if (l) {
keir@21411 2081 ret = realloc(ret, sizeof(libxl_device_disk) * (*num + numl));
keir@21411 2082 disks = ret + *num;
keir@21411 2083 *num += numl;
keir@21411 2084 for (dend = ret + *num; disks < dend; ++disks, ++l) {
keir@21411 2085 disks->backend_domid = 0;
keir@21411 2086 disks->domid = domid;
keir@21411 2087 disks->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/params", be_path_tap, *l));
keir@21411 2088 libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/type", be_path_tap, *l)), &(disks->phystype));
keir@21411 2089 disks->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/dev", be_path_tap, *l));
keir@21411 2090 disks->unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/removable", be_path_tap, *l)));
keir@21411 2091 if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/mode", be_path_tap, *l)), "w"))
keir@21411 2092 disks->readwrite = 1;
keir@20637 2093 else
keir@21411 2094 disks->readwrite = 0;
keir@21411 2095 type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/frontend", be_path_tap, *l))));
keir@21411 2096 disks->is_cdrom = !strcmp(type, "cdrom");
keir@20637 2097 }
keir@21411 2098 libxl_free(ctx, b);
keir@20637 2099 }
keir@21411 2100 return ret;
keir@21411 2101 }
keir@21411 2102
keir@21411 2103 int libxl_device_disk_getinfo(struct libxl_ctx *ctx, uint32_t domid,
keir@21411 2104 libxl_device_disk *disk, libxl_diskinfo *diskinfo)
keir@21411 2105 {
keir@21411 2106 char *dompath, *diskpath;
keir@21411 2107 char *val;
keir@21411 2108
keir@21411 2109 dompath = libxl_xs_get_dompath(ctx, domid);
keir@21411 2110 diskinfo->devid = device_disk_dev_number(disk->virtpath);
keir@21411 2111
keir@21411 2112 /* tap devices entries in xenstore are written as vbd devices. */
keir@21411 2113 diskpath = libxl_sprintf(ctx, "%s/device/vbd/%d", dompath, diskinfo->devid);
keir@21411 2114 diskinfo->backend = libxl_xs_read(ctx, XBT_NULL,
keir@21411 2115 libxl_sprintf(ctx, "%s/backend", diskpath));
keir@21411 2116 if (!diskinfo->backend) {
keir@21411 2117 return ERROR_FAIL;
keir@21411 2118 }
keir@21411 2119 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", diskpath));
keir@21411 2120 diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21411 2121 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", diskpath));
keir@21411 2122 diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
keir@21411 2123 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/event-channel", diskpath));
keir@21411 2124 diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
keir@21411 2125 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/ring-ref", diskpath));
keir@21411 2126 diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
keir@21411 2127 diskinfo->frontend = libxl_xs_read(ctx, XBT_NULL,
keir@21411 2128 libxl_sprintf(ctx, "%s/frontend", diskinfo->backend));
keir@21411 2129 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", diskinfo->backend));
keir@21411 2130 diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21411 2131
keir@21411 2132 return 0;
keir@20637 2133 }
keir@20637 2134
keir@20637 2135 int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20637 2136 {
keir@20637 2137 int num, i;
keir@20637 2138 uint32_t stubdomid;
keir@20637 2139 libxl_device_disk *disks;
keir@20637 2140
keir@20637 2141 if (!disk->physpath) {
keir@20637 2142 disk->physpath = "";
keir@20637 2143 disk->phystype = PHYSTYPE_PHY;
keir@20637 2144 }
keir@20637 2145 disks = libxl_device_disk_list(ctx, domid, &num);
keir@20637 2146 for (i = 0; i < num; i++) {
keir@20637 2147 if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath))
keir@20637 2148 /* found */
keir@20637 2149 break;
keir@20637 2150 }
keir@20637 2151 if (i == num) {
keir@20637 2152 XL_LOG(ctx, XL_LOG_ERROR, "Virtual device not found");
gianni@21892 2153 return ERROR_FAIL;
keir@20637 2154 }
keir@20637 2155 libxl_device_disk_del(ctx, disks + i, 1);
keir@20637 2156 libxl_device_disk_add(ctx, domid, disk);
keir@20637 2157 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20637 2158 if (stubdomid) {
keir@20781 2159 disks[i].domid = stubdomid;
keir@20637 2160 libxl_device_disk_del(ctx, disks + i, 1);
keir@20781 2161 disk->domid = stubdomid;
keir@20637 2162 libxl_device_disk_add(ctx, stubdomid, disk);
keir@20781 2163 disk->domid = domid;
keir@20637 2164 }
keir@20637 2165 return 0;
keir@20637 2166 }
keir@20637 2167
keir@20462 2168 /******************************************************************************/
keir@20509 2169 static int libxl_build_xenpv_qemu_args(struct libxl_ctx *ctx,
keir@20509 2170 libxl_device_vfb *vfb,
keir@20509 2171 int num_console,
keir@20509 2172 libxl_device_console *console,
keir@20860 2173 libxl_device_model_info *info)
keir@20860 2174 {
keir@20509 2175 int i = 0, j = 0, num = 0;
keir@20509 2176 memset(info, 0x00, sizeof(libxl_device_model_info));
keir@20509 2177
keir@20509 2178 info->vnc = vfb->vnc;
keir@20509 2179 if (vfb->vnclisten)
Ian@21845 2180 info->vnclisten = libxl_strdup(ctx, vfb->vnclisten);
keir@20509 2181 info->vncdisplay = vfb->vncdisplay;
keir@20509 2182 info->vncunused = vfb->vncunused;
keir@21362 2183 if (vfb->vncpasswd)
keir@21362 2184 info->vncpasswd = vfb->vncpasswd;
keir@20509 2185 if (vfb->keymap)
Ian@21845 2186 info->keymap = libxl_strdup(ctx, vfb->keymap);
keir@20509 2187 info->sdl = vfb->sdl;
keir@20509 2188 info->opengl = vfb->opengl;
keir@20509 2189 for (i = 0; i < num_console; i++) {
keir@20509 2190 if (console->constype == CONSTYPE_IOEMU)
keir@20509 2191 num++;
keir@20509 2192 }
keir@20509 2193 if (num > 0) {
keir@20860 2194 uint32_t guest_domid;
keir@20860 2195 if (libxl_is_stubdom(ctx, vfb->domid, &guest_domid)) {
keir@20599 2196 char *filename;
keir@20599 2197 char *name = libxl_sprintf(ctx, "qemu-dm-%s", libxl_domid_to_name(ctx, guest_domid));
keir@20599 2198 libxl_create_logfile(ctx, name, &filename);
keir@20599 2199 info->serial = libxl_sprintf(ctx, "file:%s", filename);
keir@20599 2200 free(filename);
keir@20599 2201 } else {
keir@20599 2202 info->serial = "pty";
keir@20599 2203 }
keir@20509 2204 num--;
keir@20509 2205 }
keir@20509 2206 if (num > 0) {
keir@20509 2207 info->extra = (char **) libxl_calloc(ctx, num * 2 + 1, sizeof(char *));
keir@20509 2208 for (j = 0; j < num * 2; j = j + 2) {
keir@20509 2209 info->extra[j] = "-serial";
keir@20509 2210 info->extra[j + 1] = "pty";
keir@20509 2211 }
keir@20509 2212 info->extra[j] = NULL;
keir@20509 2213 }
keir@20509 2214 info->domid = vfb->domid;
keir@20509 2215 info->dom_name = libxl_domid_to_name(ctx, vfb->domid);
keir@21376 2216 info->device_model = libxl_abs_path(ctx, "qemu-dm", libxl_libexec_path());
keir@20509 2217 info->type = XENPV;
keir@20509 2218 return 0;
keir@20509 2219 }
keir@20509 2220
keir@20509 2221 int libxl_create_xenpv_qemu(struct libxl_ctx *ctx, libxl_device_vfb *vfb,
keir@20514 2222 int num_console, libxl_device_console *console,
keir@20514 2223 struct libxl_device_model_starting **starting_r)
keir@20509 2224 {
keir@20509 2225 libxl_device_model_info info;
keir@20509 2226
keir@20509 2227 libxl_build_xenpv_qemu_args(ctx, vfb, num_console, console, &info);
keir@20542 2228 libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r);
keir@20509 2229 return 0;
keir@20509 2230 }
keir@20509 2231
keir@20509 2232 int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
keir@20462 2233 {
keir@20509 2234 flexarray_t *front;
keir@20509 2235 flexarray_t *back;
keir@20509 2236 unsigned int boffset = 0;
keir@20509 2237 unsigned int foffset = 0;
keir@20509 2238 libxl_device device;
keir@20509 2239
keir@20509 2240 front = flexarray_make(16, 1);
keir@20509 2241 if (!front)
keir@20509 2242 return ERROR_NOMEM;
keir@20509 2243 back = flexarray_make(16, 1);
keir@20509 2244 if (!back)
keir@20509 2245 return ERROR_NOMEM;
keir@20509 2246
keir@20509 2247 device.backend_devid = vfb->devid;
keir@20509 2248 device.backend_domid = vfb->backend_domid;
keir@20509 2249 device.backend_kind = DEVICE_VFB;
keir@20509 2250 device.devid = vfb->devid;
keir@20509 2251 device.domid = vfb->domid;
keir@20509 2252 device.kind = DEVICE_VFB;
keir@20509 2253
keir@20516 2254 flexarray_set(back, boffset++, "frontend-id");
keir@20509 2255 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->domid));
keir@20516 2256 flexarray_set(back, boffset++, "online");
keir@20516 2257 flexarray_set(back, boffset++, "1");
keir@20516 2258 flexarray_set(back, boffset++, "state");
keir@20509 2259 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 2260 flexarray_set(back, boffset++, "domain");
keir@20516 2261 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20516 2262 flexarray_set(back, boffset++, "vnc");
keir@20509 2263 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vnc));
keir@20516 2264 flexarray_set(back, boffset++, "vnclisten");
keir@20516 2265 flexarray_set(back, boffset++, vfb->vnclisten);
keir@21362 2266 flexarray_set(back, boffset++, "vncpasswd");
keir@21362 2267 flexarray_set(back, boffset++, vfb->vncpasswd);
keir@20516 2268 flexarray_set(back, boffset++, "vncdisplay");
keir@20509 2269 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncdisplay));
keir@20516 2270 flexarray_set(back, boffset++, "vncunused");
keir@20509 2271 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncunused));
keir@20516 2272 flexarray_set(back, boffset++, "sdl");
keir@20509 2273 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->sdl));
keir@20516 2274 flexarray_set(back, boffset++, "opengl");
keir@20509 2275 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->opengl));
keir@20509 2276 if (vfb->xauthority) {
keir@20516 2277 flexarray_set(back, boffset++, "xauthority");
keir@20516 2278 flexarray_set(back, boffset++, vfb->xauthority);
keir@20509 2279 }
keir@20509 2280 if (vfb->display) {
keir@20516 2281 flexarray_set(back, boffset++, "display");
keir@20516 2282 flexarray_set(back, boffset++, vfb->display);
keir@20509 2283 }
keir@20509 2284
keir@20516 2285 flexarray_set(front, foffset++, "backend-id");
keir@20509 2286 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vfb->backend_domid));
keir@20516 2287 flexarray_set(front, foffset++, "state");
keir@20509 2288 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 2289
keir@20509 2290 libxl_device_generic_add(ctx, &device,
keir@20509 2291 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 2292 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20509 2293 flexarray_free(front);
keir@20509 2294 flexarray_free(back);
keir@20509 2295
keir@20509 2296 return 0;
keir@20462 2297 }
keir@20462 2298
keir@20462 2299 int libxl_device_vfb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 2300 {
keir@20462 2301 return ERROR_NI;
keir@20462 2302 }
keir@20462 2303
keir@20462 2304 int libxl_device_vfb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 2305 {
keir@20462 2306 return ERROR_NI;
keir@20462 2307 }
keir@20462 2308
keir@20462 2309 /******************************************************************************/
keir@20482 2310
keir@20482 2311 int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
keir@20482 2312 unsigned int bus, unsigned int dev,
keir@20482 2313 unsigned int func, unsigned int vdevfn)
keir@20482 2314 {
keir@20482 2315 pcidev->domain = domain;
keir@20482 2316 pcidev->bus = bus;
keir@20482 2317 pcidev->dev = dev;
keir@20482 2318 pcidev->func = func;
keir@20482 2319 pcidev->vdevfn = vdevfn;
keir@20482 2320 return 0;
keir@20482 2321 }
keir@20482 2322
keir@20482 2323 static int libxl_create_pci_backend(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev, int num)
keir@20482 2324 {
keir@20482 2325 flexarray_t *front;
keir@20482 2326 flexarray_t *back;
keir@20482 2327 unsigned int boffset = 0;
keir@20482 2328 unsigned int foffset = 0;
keir@20482 2329 libxl_device device;
keir@20482 2330 int i;
keir@20482 2331
keir@20482 2332 front = flexarray_make(16, 1);
keir@20482 2333 if (!front)
keir@20482 2334 return ERROR_NOMEM;
keir@20482 2335 back = flexarray_make(16, 1);
keir@20482 2336 if (!back)
keir@20482 2337 return ERROR_NOMEM;
keir@20482 2338
keir@20512 2339 XL_LOG(ctx, XL_LOG_DEBUG, "Creating pci backend");
keir@20482 2340
keir@20482 2341 /* add pci device */
keir@20482 2342 device.backend_devid = 0;
keir@20482 2343 device.backend_domid = 0;
keir@20482 2344 device.backend_kind = DEVICE_PCI;
keir@20482 2345 device.devid = 0;
keir@20482 2346 device.domid = domid;
keir@20482 2347 device.kind = DEVICE_PCI;
keir@20482 2348
keir@20516 2349 flexarray_set(back, boffset++, "frontend-id");
keir@20482 2350 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", domid));
keir@20516 2351 flexarray_set(back, boffset++, "online");
keir@20516 2352 flexarray_set(back, boffset++, "1");
keir@20516 2353 flexarray_set(back, boffset++, "state");
keir@20482 2354 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 2355 flexarray_set(back, boffset++, "domain");
keir@20516 2356 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20482 2357 for (i = 0; i < num; i++) {
keir@20482 2358 flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", i));
keir@20482 2359 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 2360 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", i));
keir@20482 2361 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 2362 if (pcidev->vdevfn) {
keir@20482 2363 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", i));
keir@20482 2364 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", pcidev->vdevfn));
keir@20482 2365 }
keir@20482 2366 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", i));
keir@20482 2367 flexarray_set(back, boffset++, libxl_sprintf(ctx, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
keir@20482 2368 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", i));
keir@20482 2369 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20482 2370 }
keir@20516 2371 flexarray_set(back, boffset++, "num_devs");
keir@20482 2372 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num));
keir@20482 2373
keir@20516 2374 flexarray_set(front, foffset++, "backend-id");
keir@20482 2375 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 0));
keir@20516 2376 flexarray_set(front, foffset++, "state");
keir@20482 2377 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20482 2378
keir@20482 2379 libxl_device_generic_add(ctx, &device,
keir@20482 2380 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20482 2381 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20482 2382
keir@20482 2383 flexarray_free(back);
keir@20482 2384 flexarray_free(front);
keir@20482 2385 return 0;
keir@20482 2386 }
keir@20482 2387
keir@20482 2388 static int libxl_device_pci_add_xenstore(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 2389 {
keir@20482 2390 flexarray_t *back;
keir@20482 2391 char *num_devs, *be_path;
keir@20482 2392 int num = 0;
keir@20482 2393 unsigned int boffset = 0;
keir@20482 2394 xs_transaction_t t;
keir@20482 2395
keir@20516 2396 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid);
keir@20482 2397 num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", be_path));
keir@20482 2398 if (!num_devs)
keir@20482 2399 return libxl_create_pci_backend(ctx, domid, pcidev, 1);
keir@20482 2400
keir@20482 2401 if (!is_hvm(ctx, domid)) {
keir@20482 2402 if (libxl_wait_for_backend(ctx, be_path, "4") < 0)
gianni@21892 2403 return ERROR_FAIL;
keir@20482 2404 }
keir@20482 2405
keir@20482 2406 back = flexarray_make(16, 1);
keir@20482 2407 if (!back)
keir@20482 2408 return ERROR_NOMEM;
keir@20482 2409
keir@20512 2410 XL_LOG(ctx, XL_LOG_DEBUG, "Adding new pci device to xenstore");
keir@20482 2411 num = atoi(num_devs);
keir@20482 2412 flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", num));
keir@20482 2413 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 2414 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", num));
keir@20482 2415 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 2416 if (pcidev->vdevfn) {
keir@20482 2417 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", num));
keir@20482 2418 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", pcidev->vdevfn));
keir@20482 2419 }
keir@20482 2420 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", num));
keir@20482 2421 flexarray_set(back, boffset++, libxl_sprintf(ctx, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
keir@20482 2422 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", num));
keir@20482 2423 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 2424 flexarray_set(back, boffset++, "num_devs");
keir@20482 2425 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num + 1));
keir@20516 2426 flexarray_set(back, boffset++, "state");
keir@20482 2427 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 7));
keir@20482 2428
keir@20482 2429 retry_transaction:
keir@20482 2430 t = xs_transaction_start(ctx->xsh);
keir@20482 2431 libxl_xs_writev(ctx, t, be_path,
keir@20482 2432 libxl_xs_kvs_of_flexarray(ctx, back, boffset));
keir@20482 2433 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20482 2434 if (errno == EAGAIN)
keir@20482 2435 goto retry_transaction;
keir@20482 2436
keir@20482 2437 flexarray_free(back);
keir@20482 2438 return 0;
keir@20482 2439 }
keir@20482 2440
keir@20482 2441 static int libxl_device_pci_remove_xenstore(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20482 2442 {
keir@20542 2443 char *be_path, *num_devs_path, *num_devs, *xsdev, *tmp, *tmppath;
keir@20542 2444 int num, i, j;
keir@20482 2445 xs_transaction_t t;
keir@20482 2446 unsigned int domain = 0, bus = 0, dev = 0, func = 0;
keir@20482 2447
keir@20516 2448 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid);
keir@20482 2449 num_devs_path = libxl_sprintf(ctx, "%s/num_devs", be_path);
keir@20482 2450 num_devs = libxl_xs_read(ctx, XBT_NULL, num_devs_path);
keir@20482 2451 if (!num_devs)
gianni@21892 2452 return ERROR_INVAL;
keir@20482 2453 num = atoi(num_devs);
keir@20482 2454
keir@20482 2455 if (!is_hvm(ctx, domid)) {
keir@20482 2456 if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
keir@20542 2457 XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", be_path);
gianni@21892 2458 return ERROR_FAIL;
keir@20482 2459 }
keir@20482 2460 }
keir@20482 2461
keir@20482 2462 for (i = 0; i < num; i++) {
keir@20482 2463 xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20482 2464 sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
keir@20482 2465 if (domain == pcidev->domain && bus == pcidev->bus &&
keir@20482 2466 pcidev->dev == dev && pcidev->func == func) {
keir@20482 2467 break;
keir@20482 2468 }
keir@20482 2469 }
keir@20482 2470 if (i == num) {
keir@20512 2471 XL_LOG(ctx, XL_LOG_ERROR, "Couldn't find the device on xenstore");
gianni@21892 2472 return ERROR_INVAL;
keir@20482 2473 }
keir@20482 2474
keir@20482 2475 retry_transaction:
keir@20482 2476 t = xs_transaction_start(ctx->xsh);
keir@20542 2477 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i), "5", strlen("5"));
keir@20482 2478 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state", be_path), "7", strlen("7"));
keir@20482 2479 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20482 2480 if (errno == EAGAIN)
keir@20482 2481 goto retry_transaction;
keir@20542 2482
keir@20542 2483 if (!is_hvm(ctx, domid)) {
keir@20542 2484 if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
keir@20542 2485 XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", be_path);
gianni@21892 2486 return ERROR_FAIL;
keir@20542 2487 }
keir@20542 2488 }
keir@20542 2489
keir@20542 2490 retry_transaction2:
keir@20542 2491 t = xs_transaction_start(ctx->xsh);
keir@20542 2492 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i));
keir@20542 2493 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, i));
keir@20542 2494 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20542 2495 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, i));
keir@20542 2496 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
keir@20542 2497 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
keir@20542 2498 libxl_xs_write(ctx, t, num_devs_path, "%d", num - 1);
keir@20542 2499 for (j = i + 1; j < num; j++) {
keir@20542 2500 tmppath = libxl_sprintf(ctx, "%s/state-%d", be_path, j);
keir@20542 2501 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2502 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2503 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2504 tmppath = libxl_sprintf(ctx, "%s/dev-%d", be_path, j);
keir@20542 2505 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2506 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2507 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2508 tmppath = libxl_sprintf(ctx, "%s/key-%d", be_path, j);
keir@20542 2509 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2510 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2511 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2512 tmppath = libxl_sprintf(ctx, "%s/vdev-%d", be_path, j);
keir@20542 2513 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2514 if (tmp) {
keir@20542 2515 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2516 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2517 }
keir@20542 2518 tmppath = libxl_sprintf(ctx, "%s/opts-%d", be_path, j);
keir@20542 2519 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2520 if (tmp) {
keir@20542 2521 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2522 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2523 }
keir@20542 2524 tmppath = libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j);
keir@20542 2525 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2526 if (tmp) {
keir@20542 2527 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2528 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2529 }
keir@20542 2530 }
keir@20542 2531 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 2532 if (errno == EAGAIN)
keir@20542 2533 goto retry_transaction2;
keir@20542 2534
keir@20542 2535 if (num == 1) {
keir@20542 2536 char *fe_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend", be_path));
keir@20542 2537 libxl_device_destroy(ctx, be_path, 1);
keir@20542 2538 xs_rm(ctx->xsh, XBT_NULL, be_path);
keir@20542 2539 xs_rm(ctx->xsh, XBT_NULL, fe_path);
keir@20542 2540 return 0;
keir@20542 2541 }
keir@20542 2542
keir@20482 2543 return 0;
keir@20462 2544 }
keir@20462 2545
keir@20482 2546 int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 2547 {
keir@20779 2548 char *path;
keir@20482 2549 char *state, *vdevfn;
keir@20482 2550 int rc, hvm;
keir@20542 2551 int stubdomid = 0;
keir@20482 2552
keir@20482 2553 /* TODO: check if the device can be assigned */
keir@20482 2554
Ian@21711 2555 libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2556
keir@20779 2557 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20779 2558 if (stubdomid != 0) {
keir@20542 2559 libxl_device_pci pcidev_s = *pcidev;
keir@20542 2560 libxl_device_pci_add(ctx, stubdomid, &pcidev_s);
keir@20542 2561 }
keir@20542 2562
keir@20482 2563 hvm = is_hvm(ctx, domid);
keir@20482 2564 if (hvm) {
keir@20831 2565 if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 0) {
gianni@21892 2566 return ERROR_FAIL;
keir@20482 2567 }
keir@20779 2568 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 2569 state = libxl_xs_read(ctx, XBT_NULL, path);
keir@20779 2570 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 2571 if (pcidev->vdevfn)
keir@20482 2572 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF_VDEVFN, pcidev->domain,
keir@20482 2573 pcidev->bus, pcidev->dev, pcidev->func, pcidev->vdevfn);
keir@20482 2574 else
keir@20482 2575 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
keir@20482 2576 pcidev->bus, pcidev->dev, pcidev->func);
keir@20779 2577 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid);
keir@20482 2578 xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins"));
keir@20831 2579 if (libxl_wait_for_device_model(ctx, domid, "pci-inserted", NULL, NULL) < 0)
keir@20512 2580 XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
keir@20779 2581 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 2582 vdevfn = libxl_xs_read(ctx, XBT_NULL, path);
keir@20482 2583 sscanf(vdevfn + 2, "%x", &pcidev->vdevfn);
keir@20779 2584 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 2585 xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
keir@20482 2586 } else {
keir@20542 2587 char *sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
keir@20482 2588 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2589 FILE *f = fopen(sysfs_path, "r");
keir@21517 2590 unsigned long long start = 0, end = 0, flags = 0, size = 0;
keir@20482 2591 int irq = 0;
keir@20482 2592 int i;
keir@20482 2593
keir@20482 2594 if (f == NULL) {
keir@20512 2595 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
gianni@21892 2596 return ERROR_FAIL;
keir@20482 2597 }
keir@20482 2598 for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
keir@21517 2599 if (fscanf(f, "0x%llx 0x%llx 0x%llx\n", &start, &end, &flags) != 3)
keir@21466 2600 continue;
keir@20482 2601 size = end - start + 1;
keir@20482 2602 if (start) {
keir@20482 2603 if (flags & PCI_BAR_IO) {
keir@20482 2604 rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 1);
gianni@21892 2605 if (rc < 0) {
keir@21517 2606 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_ioport_permission error 0x%llx/0x%llx", start, size);
gianni@21892 2607 fclose(f);
gianni@21892 2608 return ERROR_FAIL;
gianni@21892 2609 }
keir@20482 2610 } else {
keir@20482 2611 rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT,
keir@20482 2612 (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 1);
gianni@21892 2613 if (rc < 0) {
keir@21537 2614 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_iomem_permission error 0x%llx/0x%llx", start, size);
gianni@21892 2615 fclose(f);
gianni@21892 2616 return ERROR_FAIL;
gianni@21892 2617 }
keir@20482 2618 }
keir@20482 2619 }
keir@20482 2620 }
keir@20482 2621 fclose(f);
keir@20542 2622 sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", pcidev->domain,
keir@20482 2623 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2624 f = fopen(sysfs_path, "r");
keir@20482 2625 if (f == NULL) {
keir@20512 2626 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 2627 goto out;
keir@20482 2628 }
keir@21466 2629 if ((fscanf(f, "%u", &irq) == 1) && irq) {
keir@20482 2630 rc = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
keir@20482 2631 if (rc < 0) {
keir@20512 2632 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_physdev_map_pirq irq=%d", irq);
gianni@21892 2633 fclose(f);
gianni@21892 2634 return ERROR_FAIL;
keir@20482 2635 }
keir@20482 2636 rc = xc_domain_irq_permission(ctx->xch, domid, irq, 1);
keir@20482 2637 if (rc < 0) {
keir@20512 2638 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_irq_permission irq=%d", irq);
gianni@21892 2639 fclose(f);
gianni@21892 2640 return ERROR_FAIL;
keir@20482 2641 }
keir@20482 2642 }
keir@20482 2643 fclose(f);
keir@20482 2644 }
keir@20482 2645 out:
keir@20860 2646 if (!libxl_is_stubdom(ctx, domid, NULL)) {
keir@20779 2647 rc = xc_assign_device(ctx->xch, domid, pcidev->value);
gianni@21892 2648 if (rc < 0) {
keir@20542 2649 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_assign_device failed");
gianni@21892 2650 return ERROR_FAIL;
gianni@21892 2651 }
keir@20542 2652 }
keir@20482 2653
keir@20482 2654 libxl_device_pci_add_xenstore(ctx, domid, pcidev);
keir@20482 2655 return 0;
keir@20462 2656 }
keir@20462 2657
keir@20482 2658 int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 2659 {
keir@20779 2660 char *path;
keir@20482 2661 char *state;
keir@20482 2662 int hvm, rc;
keir@20542 2663 int stubdomid = 0;
keir@20482 2664
keir@20482 2665 /* TODO: check if the device can be detached */
keir@20542 2666 libxl_device_pci_remove_xenstore(ctx, domid, pcidev);
keir@20482 2667
keir@20482 2668 hvm = is_hvm(ctx, domid);
keir@20482 2669 if (hvm) {
keir@20831 2670 if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 0) {
gianni@21892 2671 return ERROR_FAIL;
keir@20482 2672 }
keir@20779 2673 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 2674 state = libxl_xs_read(ctx, XBT_NULL, path);
keir@20779 2675 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 2676 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
keir@20482 2677 pcidev->bus, pcidev->dev, pcidev->func);
keir@20779 2678 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid);
keir@20482 2679 xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem"));
keir@20831 2680 if (libxl_wait_for_device_model(ctx, domid, "pci-removed", NULL, NULL) < 0) {
keir@20512 2681 XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
gianni@21892 2682 return ERROR_FAIL;
keir@20482 2683 }
keir@20779 2684 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 2685 xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
keir@20482 2686 } else {
keir@20542 2687 char *sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
keir@20482 2688 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2689 FILE *f = fopen(sysfs_path, "r");
keir@20482 2690 unsigned int start = 0, end = 0, flags = 0, size = 0;
keir@20482 2691 int irq = 0;
keir@20482 2692 int i;
keir@20482 2693
keir@20482 2694 if (f == NULL) {
keir@20512 2695 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 2696 goto skip1;
keir@20482 2697 }
keir@20482 2698 for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
keir@21466 2699 if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3)
keir@21466 2700 continue;
keir@20482 2701 size = end - start + 1;
keir@20482 2702 if (start) {
keir@20482 2703 if (flags & PCI_BAR_IO) {
keir@20482 2704 rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 0);
keir@20482 2705 if (rc < 0)
keir@20512 2706 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_ioport_permission error 0x%x/0x%x", start, size);
keir@20482 2707 } else {
keir@20482 2708 rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT,
keir@20482 2709 (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 0);
keir@20482 2710 if (rc < 0)
keir@20512 2711 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_iomem_permission error 0x%x/0x%x", start, size);
keir@20482 2712 }
keir@20482 2713 }
keir@20482 2714 }
keir@20482 2715 fclose(f);
keir@20482 2716 skip1:
keir@20542 2717 sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", pcidev->domain,
keir@20482 2718 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2719 f = fopen(sysfs_path, "r");
keir@20482 2720 if (f == NULL) {
keir@20512 2721 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 2722 goto out;
keir@20482 2723 }
keir@21466 2724 if ((fscanf(f, "%u", &irq) == 1) && irq) {
keir@20482 2725 rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
keir@20482 2726 if (rc < 0) {
keir@20512 2727 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_physdev_map_pirq irq=%d", irq);
keir@20482 2728 }
keir@20482 2729 rc = xc_domain_irq_permission(ctx->xch, domid, irq, 0);
keir@20482 2730 if (rc < 0) {
keir@20512 2731 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_irq_permission irq=%d", irq);
keir@20482 2732 }
keir@20482 2733 }
keir@20482 2734 fclose(f);
keir@20482 2735 }
keir@20482 2736 out:
Ian@21711 2737 libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2738
keir@20860 2739 if (!libxl_is_stubdom(ctx, domid, NULL)) {
keir@20779 2740 rc = xc_deassign_device(ctx->xch, domid, pcidev->value);
keir@20779 2741 if (rc < 0)
keir@20542 2742 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_deassign_device failed");
keir@20542 2743 }
keir@20542 2744
keir@20779 2745 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20779 2746 if (stubdomid != 0) {
keir@20542 2747 libxl_device_pci pcidev_s = *pcidev;
keir@20542 2748 libxl_device_pci_remove(ctx, stubdomid, &pcidev_s);
keir@20542 2749 }
keir@20542 2750
keir@20482 2751 return 0;
keir@20462 2752 }
keir@20482 2753
keir@20482 2754 libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t domid, int *num)
keir@20482 2755 {
keir@20482 2756 char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts;
keir@20482 2757 int n, i;
keir@20482 2758 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
keir@20482 2759 libxl_device_pci *pcidevs;
keir@20482 2760
keir@20516 2761 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid);
keir@20482 2762 num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", be_path));
keir@20482 2763 if (!num_devs) {
keir@20482 2764 *num = 0;
keir@20482 2765 return NULL;
keir@20482 2766 }
keir@20482 2767 n = atoi(num_devs);
keir@20779 2768 pcidevs = calloc(n, sizeof(libxl_device_pci));
keir@20482 2769 *num = n;
keir@20482 2770
keir@20482 2771 for (i = 0; i < n; i++) {
keir@20482 2772 xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20482 2773 sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
keir@20482 2774 xsvdevfn = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
keir@20482 2775 if (xsvdevfn)
keir@20482 2776 vdevfn = strtol(xsvdevfn, (char **) NULL, 16);
keir@20482 2777 libxl_device_pci_init(pcidevs + i, domain, bus, dev, func, vdevfn);
keir@20482 2778 xsopts = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
keir@20482 2779 if (xsopts) {
keir@20482 2780 char *saveptr;
keir@20482 2781 char *p = strtok_r(xsopts, ",=", &saveptr);
keir@20482 2782 do {
keir@20482 2783 while (*p == ' ')
keir@20482 2784 p++;
keir@20482 2785 if (!strcmp(p, "msitranslate")) {
keir@20482 2786 p = strtok_r(NULL, ",=", &saveptr);
keir@20482 2787 pcidevs[i].msitranslate = atoi(p);
keir@20482 2788 } else if (!strcmp(p, "power_mgmt")) {
keir@20482 2789 p = strtok_r(NULL, ",=", &saveptr);
keir@20482 2790 pcidevs[i].power_mgmt = atoi(p);
keir@20482 2791 }
keir@20482 2792 } while ((p = strtok_r(NULL, ",=", &saveptr)) != NULL);
keir@20482 2793 }
keir@20482 2794 }
keir@20482 2795 return pcidevs;
keir@20482 2796 }
keir@20482 2797
keir@20482 2798 int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20482 2799 {
keir@20482 2800 libxl_device_pci *pcidevs;
keir@20482 2801 int num, i;
keir@20482 2802
keir@20482 2803 pcidevs = libxl_device_pci_list(ctx, domid, &num);
keir@20482 2804 for (i = 0; i < num; i++) {
keir@20482 2805 if (libxl_device_pci_remove(ctx, domid, pcidevs + i) < 0)
gianni@21892 2806 return ERROR_FAIL;
keir@20482 2807 }
keir@20516 2808 free(pcidevs);
keir@20482 2809 return 0;
keir@20482 2810 }
keir@20482 2811
keir@21404 2812 int libxl_domain_setmaxmem(struct libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb)
keir@21404 2813 {
keir@21404 2814 char *mem, *endptr;
keir@21404 2815 uint32_t memorykb;
keir@21404 2816 char *dompath = libxl_xs_get_dompath(ctx, domid);
keir@21404 2817
keir@21404 2818 mem = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", dompath));
keir@21404 2819 if (!mem) {
keir@21404 2820 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot get memory info from %s/memory/target\n", dompath);
keir@21404 2821 return 1;
keir@21404 2822 }
keir@21404 2823 memorykb = strtoul(mem, &endptr, 10);
keir@21404 2824 if (*endptr != '\0') {
keir@21404 2825 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "invalid memory %s from %s/memory/target\n", mem, dompath);
keir@21404 2826 return 1;
keir@21404 2827 }
keir@21404 2828
keir@21404 2829 if (max_memkb < memorykb) {
keir@21404 2830 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "memory_static_max must be greater than or or equal to memory_dynamic_max\n");
keir@21404 2831 return 1;
keir@21404 2832 }
keir@21404 2833
keir@21404 2834 if (domid != 0)
Ian@21844 2835 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/static-max", dompath), "%"PRIu32, max_memkb);
keir@21404 2836
keir@21422 2837 return 0;
keir@21404 2838 }
keir@21404 2839
keir@21422 2840 int libxl_set_memory_target(struct libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb, int enforce)
keir@20647 2841 {
keir@20647 2842 int rc = 0;
keir@21422 2843 uint32_t memorykb = 0, videoram = 0;
keir@21405 2844 char *memmax, *endptr, *videoram_s = NULL;
keir@20647 2845 char *dompath = libxl_xs_get_dompath(ctx, domid);
keir@21374 2846 xc_domaininfo_t info;
keir@21374 2847 struct libxl_dominfo ptr;
keir@21374 2848 char *uuid;
keir@20542 2849
keir@21405 2850 if (domid) {
keir@21405 2851 memmax = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/static-max", dompath));
keir@21405 2852 if (!memmax) {
keir@21405 2853 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@21405 2854 "cannot get memory info from %s/memory/static-max\n", dompath);
keir@21405 2855 return 1;
keir@21405 2856 }
keir@21405 2857 memorykb = strtoul(memmax, &endptr, 10);
keir@21405 2858 if (*endptr != '\0') {
keir@21405 2859 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@21405 2860 "invalid max memory %s from %s/memory/static-max\n", memmax, dompath);
keir@21405 2861 return 1;
keir@21405 2862 }
keir@21405 2863
keir@21405 2864 if (target_memkb > memorykb) {
keir@21504 2865 XL_LOG(ctx, XL_LOG_ERROR,
keir@21405 2866 "memory_dynamic_max must be less than or equal to memory_static_max\n");
keir@21405 2867 return 1;
keir@21405 2868 }
keir@21405 2869 }
keir@21405 2870
keir@20647 2871 videoram_s = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/videoram", dompath));
keir@21314 2872 videoram = videoram_s ? atoi(videoram_s) : 0;
keir@20647 2873
Ian@21844 2874 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", dompath), "%"PRIu32, target_memkb);
keir@21374 2875
keir@21374 2876 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
keir@21374 2877 if (rc != 1 || info.domain != domid)
keir@21374 2878 return rc;
keir@21374 2879 xcinfo2xlinfo(&info, &ptr);
keir@21374 2880 uuid = libxl_uuid2string(ctx, ptr.uuid);
Ian@21844 2881 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "/vm/%s/memory", uuid), "%"PRIu32, target_memkb / 1024);
keir@21374 2882
keir@21422 2883 if (enforce || !domid)
keir@21422 2884 memorykb = target_memkb;
keir@21422 2885 rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb + LIBXL_MAXMEM_CONSTANT);
keir@21422 2886 if (rc != 0)
keir@21422 2887 return rc;
keir@20647 2888 rc = xc_domain_memory_set_pod_target(ctx->xch, domid, (target_memkb - videoram) / 4, NULL, NULL, NULL);
keir@20647 2889 return rc;
keir@20647 2890 }
keir@20875 2891
keir@20875 2892 int libxl_button_press(struct libxl_ctx *ctx, uint32_t domid, libxl_button button)
keir@20875 2893 {
keir@20875 2894 int rc = -1;
keir@20875 2895
keir@20875 2896 switch (button) {
keir@20875 2897 case POWER_BUTTON:
keir@20875 2898 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_POWER, 0);
keir@20875 2899 break;
keir@20875 2900 case SLEEP_BUTTON:
keir@20875 2901 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_SLEEP, 0);
keir@20875 2902 break;
keir@20875 2903 default:
keir@20875 2904 break;
keir@20875 2905 }
keir@20875 2906
keir@20875 2907 return rc;
keir@20875 2908 }
keir@21141 2909
keir@21141 2910 int libxl_get_physinfo(struct libxl_ctx *ctx, struct libxl_physinfo *physinfo)
keir@21141 2911 {
keir@21141 2912 xc_physinfo_t xcphysinfo = { 0 };
keir@21141 2913 int rc;
keir@21141 2914
keir@21141 2915 rc = xc_physinfo(ctx->xch, &xcphysinfo);
keir@21141 2916 if (rc != 0) {
gianni@21892 2917 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting physinfo");
gianni@21892 2918 return ERROR_FAIL;
keir@21141 2919 }
keir@21141 2920 physinfo->threads_per_core = xcphysinfo.threads_per_core;
keir@21141 2921 physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
keir@21142 2922 physinfo->max_cpu_id = xcphysinfo.max_cpu_id;
keir@21141 2923 physinfo->nr_cpus = xcphysinfo.nr_cpus;
keir@21141 2924 physinfo->cpu_khz = xcphysinfo.cpu_khz;
keir@21141 2925 physinfo->total_pages = xcphysinfo.total_pages;
keir@21141 2926 physinfo->free_pages = xcphysinfo.free_pages;
keir@21141 2927 physinfo->scrub_pages = xcphysinfo.scrub_pages;
keir@21264 2928 physinfo->nr_nodes = xcphysinfo.nr_nodes;
keir@21264 2929 memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap));
keir@21264 2930 physinfo->phys_cap = xcphysinfo.capabilities;
keir@21264 2931
keir@21141 2932 return 0;
keir@21141 2933 }
keir@21141 2934
keir@21266 2935 const libxl_version_info* libxl_get_version_info(struct libxl_ctx *ctx)
keir@21266 2936 {
keir@21266 2937 union {
keir@21266 2938 xen_extraversion_t xen_extra;
keir@21266 2939 xen_compile_info_t xen_cc;
keir@21266 2940 xen_changeset_info_t xen_chgset;
keir@21266 2941 xen_capabilities_info_t xen_caps;
keir@21266 2942 xen_platform_parameters_t p_parms;
keir@21266 2943 xen_commandline_t xen_commandline;
keir@21266 2944 } u;
keir@21266 2945 long xen_version;
keir@21266 2946 libxl_version_info *info = &ctx->version_info;
keir@21266 2947
keir@21266 2948 if (info->xen_version_extra != NULL)
keir@21266 2949 return info;
keir@21266 2950
keir@21266 2951 xen_version = xc_version(ctx->xch, XENVER_version, NULL);
keir@21266 2952 info->xen_version_major = xen_version >> 16;
keir@21266 2953 info->xen_version_minor = xen_version & 0xFF;
keir@21266 2954 xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra);
Ian@21845 2955 info->xen_version_extra = libxl_strdup(ctx, u.xen_extra);
keir@21266 2956
keir@21266 2957 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
Ian@21845 2958 info->compiler = libxl_strdup(ctx, u.xen_cc.compiler);
Ian@21845 2959 info->compile_by = libxl_strdup(ctx, u.xen_cc.compile_by);
Ian@21845 2960 info->compile_domain = libxl_strdup(ctx, u.xen_cc.compile_domain);
Ian@21845 2961 info->compile_date = libxl_strdup(ctx, u.xen_cc.compile_date);
keir@21266 2962
keir@21266 2963 xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps);
Ian@21845 2964 info->capabilities = libxl_strdup(ctx, u.xen_caps);
keir@21266 2965
keir@21266 2966 xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset);
Ian@21845 2967 info->changeset = libxl_strdup(ctx, u.xen_chgset);
keir@21266 2968
keir@21266 2969 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
keir@21266 2970 info->virt_start = u.p_parms.virt_start;
keir@21266 2971
keir@21266 2972 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
keir@21266 2973
keir@21266 2974 xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline);
Ian@21845 2975 info->commandline = libxl_strdup(ctx, u.xen_commandline);
keir@21266 2976
keir@21266 2977 return info;
keir@21266 2978 }
keir@21266 2979
keir@21141 2980 struct libxl_vcpuinfo *libxl_list_vcpu(struct libxl_ctx *ctx, uint32_t domid,
keir@21141 2981 int *nb_vcpu, int *cpusize)
keir@21141 2982 {
keir@21141 2983 struct libxl_vcpuinfo *ptr, *ret;
keir@21141 2984 xc_domaininfo_t domaininfo;
keir@21141 2985 xc_vcpuinfo_t vcpuinfo;
keir@21141 2986 xc_physinfo_t physinfo = { 0 };
keir@21141 2987
keir@21141 2988 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
gianni@21892 2989 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting infolist");
keir@21141 2990 return NULL;
keir@21141 2991 }
keir@21141 2992 if (xc_physinfo(ctx->xch, &physinfo) == -1) {
gianni@21892 2993 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting physinfo");
keir@21141 2994 return NULL;
keir@21141 2995 }
keir@21141 2996 *cpusize = physinfo.max_cpu_id + 1;
keir@21141 2997 ptr = libxl_calloc(ctx, domaininfo.max_vcpu_id + 1, sizeof (struct libxl_vcpuinfo));
keir@21141 2998 if (!ptr) {
keir@21141 2999 return NULL;
keir@21141 3000 }
keir@21141 3001
keir@21141 3002 ret = ptr;
keir@21141 3003 for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) {
keir@21141 3004 ptr->cpumap = libxl_calloc(ctx, (*cpusize + 63) / 64, sizeof (uint64_t));
keir@21141 3005 if (!ptr->cpumap) {
keir@21141 3006 return NULL;
keir@21141 3007 }
keir@21141 3008 if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) {
gianni@21892 3009 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting vcpu info");
keir@21141 3010 return NULL;
keir@21141 3011 }
keir@21141 3012 if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu, ptr->cpumap, *cpusize) == -1) {
gianni@21892 3013 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting vcpu affinity");
keir@21141 3014 return NULL;
keir@21141 3015 }
keir@21141 3016 ptr->vcpuid = *nb_vcpu;
keir@21141 3017 ptr->cpu = vcpuinfo.cpu;
keir@21141 3018 ptr->online = !!vcpuinfo.online;
keir@21141 3019 ptr->blocked = !!vcpuinfo.blocked;
keir@21141 3020 ptr->running = !!vcpuinfo.running;
keir@21141 3021 ptr->vcpu_time = vcpuinfo.cpu_time;
keir@21141 3022 }
keir@21141 3023 return ret;
keir@21141 3024 }
keir@21142 3025
keir@21142 3026 int libxl_set_vcpuaffinity(struct libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
keir@21142 3027 uint64_t *cpumap, int cpusize)
keir@21142 3028 {
gianni@21892 3029 if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap, cpusize)) {
gianni@21892 3030 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting vcpu affinity");
gianni@21892 3031 return ERROR_FAIL;
gianni@21892 3032 }
gianni@21892 3033 return 0;
keir@21142 3034 }
keir@21143 3035
keir@21143 3036 int libxl_set_vcpucount(struct libxl_ctx *ctx, uint32_t domid, uint32_t count)
keir@21143 3037 {
keir@21143 3038 xc_domaininfo_t domaininfo;
keir@21143 3039 char *dompath;
keir@21143 3040 int i;
keir@21143 3041
keir@21143 3042 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
gianni@21892 3043 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting domain info list");
keir@21143 3044 return ERROR_FAIL;
keir@21143 3045 }
keir@21143 3046 if (!count || ((domaininfo.max_vcpu_id + 1) < count)) {
keir@21143 3047 return ERROR_INVAL;
keir@21143 3048 }
keir@21143 3049 if (!(dompath = libxl_xs_get_dompath(ctx, domid)))
keir@21143 3050 return ERROR_FAIL;
keir@21143 3051
keir@21143 3052 for (i = 0; i <= domaininfo.max_vcpu_id; ++i) {
keir@21143 3053 libxl_xs_write(ctx, XBT_NULL,
keir@21143 3054 libxl_sprintf(ctx, "%s/cpu/%u/availability", dompath, i),
keir@21143 3055 "%s", ((1 << i) & ((1 << count) - 1)) ? "online" : "offline");
keir@21143 3056 }
keir@21143 3057 return 0;
keir@21143 3058 }
keir@21265 3059
keir@21265 3060 /*
keir@21265 3061 * returns one of the XEN_SCHEDULER_* constants from public/domctl.h
keir@21265 3062 */
keir@21265 3063 int libxl_get_sched_id(struct libxl_ctx *ctx)
keir@21265 3064 {
keir@21265 3065 int sched, ret;
keir@21265 3066
gianni@21892 3067 if ((ret = xc_sched_id(ctx->xch, &sched)) != 0) {
gianni@21892 3068 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting domain info list");
gianni@21892 3069 return ERROR_FAIL;
gianni@21892 3070 }
keir@21265 3071 return sched;
keir@21265 3072 }
keir@21292 3073
keir@21292 3074 int libxl_sched_credit_domain_get(struct libxl_ctx *ctx, uint32_t domid, struct libxl_sched_credit *scinfo)
keir@21292 3075 {
keir@21292 3076 struct xen_domctl_sched_credit sdom;
keir@21292 3077 int rc;
keir@21292 3078
keir@21292 3079 rc = xc_sched_credit_domain_get(ctx->xch, domid, &sdom);
gianni@21892 3080 if (rc != 0) {
gianni@21892 3081 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting domain sched credit");
gianni@21892 3082 return ERROR_FAIL;
gianni@21892 3083 }
keir@21292 3084
keir@21292 3085 scinfo->weight = sdom.weight;
keir@21292 3086 scinfo->cap = sdom.cap;
keir@21292 3087
keir@21292 3088 return 0;
keir@21292 3089 }
keir@21292 3090
keir@21292 3091 int libxl_sched_credit_domain_set(struct libxl_ctx *ctx, uint32_t domid, struct libxl_sched_credit *scinfo)
keir@21292 3092 {
keir@21292 3093 struct xen_domctl_sched_credit sdom;
keir@21292 3094 xc_domaininfo_t domaininfo;
keir@21292 3095 int rc;
keir@21292 3096
keir@21292 3097 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo);
gianni@21892 3098 if (rc < 0) {
gianni@21892 3099 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting domain info list");
gianni@21892 3100 return ERROR_FAIL;
gianni@21892 3101 }
keir@21292 3102 if (rc != 1 || domaininfo.domain != domid)
gianni@21892 3103 return ERROR_INVAL;
keir@21292 3104
keir@21292 3105
keir@21292 3106 if (scinfo->weight < 1 || scinfo->weight > 65535) {
keir@21292 3107 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21292 3108 "Cpu weight out of range, valid values are within range from 1 to 65535");
gianni@21892 3109 return ERROR_INVAL;
keir@21292 3110 }
keir@21292 3111
keir@21292 3112 if (scinfo->cap < 0 || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) {
keir@21292 3113 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21292 3114 "Cpu cap out of range, valid range is from 0 to %d for specified number of vcpus",
keir@21292 3115 ((domaininfo.max_vcpu_id + 1) * 100));
gianni@21892 3116 return ERROR_INVAL;
keir@21292 3117 }
keir@21292 3118
keir@21292 3119 sdom.weight = scinfo->weight;
keir@21292 3120 sdom.cap = scinfo->cap;
keir@21292 3121
keir@21292 3122 rc = xc_sched_credit_domain_set(ctx->xch, domid, &sdom);
gianni@21892 3123 if ( rc < 0 ) {
gianni@21892 3124 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting domain sched credit");
gianni@21892 3125 return ERROR_FAIL;
gianni@21892 3126 }
keir@21292 3127
keir@21292 3128 return 0;
keir@21292 3129 }
keir@21292 3130
keir@21393 3131 static int trigger_type_from_string(char *trigger_name)
keir@21393 3132 {
keir@21393 3133 if (!strcmp(trigger_name, "nmi"))
keir@21393 3134 return XEN_DOMCTL_SENDTRIGGER_NMI;
keir@21393 3135 else if (!strcmp(trigger_name, "reset"))
keir@21393 3136 return XEN_DOMCTL_SENDTRIGGER_RESET;
keir@21393 3137 else if (!strcmp(trigger_name, "init"))
keir@21393 3138 return XEN_DOMCTL_SENDTRIGGER_INIT;
keir@21393 3139 else if (!strcmp(trigger_name, "power"))
keir@21393 3140 return XEN_DOMCTL_SENDTRIGGER_POWER;
keir@21393 3141 else if (!strcmp(trigger_name, "sleep"))
keir@21393 3142 return XEN_DOMCTL_SENDTRIGGER_SLEEP;
keir@21393 3143 else
keir@21393 3144 return -1;
keir@21393 3145 }
keir@21393 3146
keir@21393 3147 int libxl_send_trigger(struct libxl_ctx *ctx, uint32_t domid, char *trigger_name, uint32_t vcpuid)
keir@21393 3148 {
keir@21393 3149 int rc = -1;
keir@21393 3150 int trigger_type = trigger_type_from_string(trigger_name);
keir@21393 3151
keir@21393 3152 if (trigger_type == -1) {
keir@21393 3153 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21393 3154 "Invalid trigger, valid triggers are <nmi|reset|init|power|sleep>");
gianni@21892 3155 return ERROR_INVAL;
keir@21393 3156 }
keir@21393 3157
keir@21393 3158 rc = xc_domain_send_trigger(ctx->xch, domid, trigger_type, vcpuid);
gianni@21892 3159 if (rc != 0) {
keir@21393 3160 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21393 3161 "Send trigger '%s' failed", trigger_name);
gianni@21892 3162 return ERROR_FAIL;
gianni@21892 3163 }
gianni@21892 3164
gianni@21892 3165 return 0;
keir@21393 3166 }
keir@21402 3167
keir@21402 3168 int libxl_send_sysrq(struct libxl_ctx *ctx, uint32_t domid, char sysrq)
keir@21402 3169 {
keir@21402 3170 char *dompath = libxl_xs_get_dompath(ctx, domid);
keir@21402 3171
keir@21402 3172 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/control/sysrq", dompath), "%c", sysrq);
keir@21402 3173
keir@21402 3174 return 0;
keir@21402 3175 }
keir@21402 3176
keir@21472 3177 int libxl_send_debug_keys(struct libxl_ctx *ctx, char *keys)
keir@21472 3178 {
gianni@21892 3179 int ret;
gianni@21892 3180 ret = xc_send_debug_keys(ctx->xch, keys);
gianni@21892 3181 if ( ret < 0 ) {
gianni@21892 3182 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "sending debug keys");
gianni@21892 3183 return ERROR_FAIL;
gianni@21892 3184 }
gianni@21892 3185 return 0;
keir@21472 3186 }
keir@21472 3187
keir@21496 3188 struct libxl_xen_console_reader *
keir@21496 3189 libxl_xen_console_read_start(struct libxl_ctx *ctx, int clear)
keir@21496 3190 {
keir@21496 3191 struct libxl_xen_console_reader *cr;
keir@21496 3192 unsigned int size = 16384;
keir@21496 3193 char *buf = malloc(size);
keir@21496 3194
keir@21496 3195 if (!buf) {
keir@21496 3196 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc buffer for libxl_xen_console_reader,"
keir@21496 3197 " size is %u", size);
keir@21496 3198 return NULL;
keir@21496 3199 }
keir@21496 3200
keir@21496 3201 cr = malloc(sizeof(struct libxl_xen_console_reader));
keir@21496 3202 if (!cr) {
keir@21496 3203 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc libxl_xen_console_reader");
keir@21496 3204 return NULL;
keir@21496 3205 }
keir@21496 3206
keir@21496 3207 memset(cr, 0, sizeof(struct libxl_xen_console_reader));
keir@21496 3208 cr->buffer = buf;
keir@21496 3209 cr->size = size;
keir@21496 3210 cr->count = size;
keir@21496 3211 cr->clear = clear;
keir@21496 3212 cr->incremental = 1;
keir@21496 3213
keir@21496 3214 return cr;
keir@21496 3215 }
keir@21496 3216
keir@21496 3217 /* return values: *line_r
keir@21496 3218 * 1 success, whole line obtained from buffer non-0
keir@21496 3219 * 0 no more lines available right now 0
keir@21496 3220 * negative error code ERROR_* 0
keir@21496 3221 * On success *line_r is updated to point to a nul-terminated
keir@21496 3222 * string which is valid until the next call on the same console
keir@21496 3223 * reader. The libxl caller may overwrite parts of the string
keir@21496 3224 * if it wishes. */
keir@21496 3225 int libxl_xen_console_read_line(struct libxl_ctx *ctx,
keir@21496 3226 struct libxl_xen_console_reader *cr,
keir@21496 3227 char **line_r)
keir@21496 3228 {
keir@21496 3229 int ret;
keir@21496 3230
keir@21496 3231 memset(cr->buffer, 0, cr->size);
keir@21496 3232 ret = xc_readconsolering(ctx->xch, &cr->buffer, &cr->count,
keir@21496 3233 cr->clear, cr->incremental, &cr->index);
gianni@21892 3234 if (ret < 0) {
gianni@21892 3235 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "reading console ring buffer");
gianni@21892 3236 return ERROR_FAIL;
gianni@21892 3237 }
keir@21496 3238 if (!ret) {
keir@21496 3239 if (cr->count) {
keir@21496 3240 *line_r = cr->buffer;
keir@21496 3241 ret = 1;
keir@21496 3242 } else {
keir@21496 3243 *line_r = NULL;
keir@21496 3244 ret = 0;
keir@21496 3245 }
keir@21496 3246 }
keir@21496 3247
keir@21496 3248 return ret;
keir@21496 3249 }
keir@21496 3250
keir@21496 3251 void libxl_xen_console_read_finish(struct libxl_ctx *ctx,
keir@21496 3252 struct libxl_xen_console_reader *cr)
keir@21496 3253 {
keir@21496 3254 free(cr->buffer);
keir@21496 3255 free(cr);
keir@21496 3256 }
keir@21496 3257
keir@21425 3258 uint32_t libxl_vm_get_start_time(struct libxl_ctx *ctx, uint32_t domid)
keir@21425 3259 {
keir@21425 3260 char *dompath = libxl_xs_get_dompath(ctx, domid);
keir@21425 3261 char *vm_path, *start_time;
keir@21425 3262
keir@21425 3263 vm_path = libxl_xs_read(
keir@21425 3264 ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vm", dompath));
keir@21425 3265 start_time = libxl_xs_read(
keir@21425 3266 ctx, XBT_NULL, libxl_sprintf(ctx, "%s/start_time", vm_path));
keir@21425 3267 if (start_time == NULL) {
keir@21425 3268 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21425 3269 "Can't get start time of domain '%d'", domid);
keir@21425 3270 return -1;
keir@21425 3271 }
keir@21425 3272
keir@21425 3273 return strtoul(start_time, NULL, 10);
keir@21425 3274 }
keir@21425 3275
keir@21471 3276 char *libxl_tmem_list(struct libxl_ctx *ctx, uint32_t domid, int use_long)
keir@21471 3277 {
keir@21471 3278 int rc;
keir@21471 3279 char _buf[32768];
keir@21471 3280
keir@21471 3281 rc = xc_tmem_control(ctx->xch, -1, TMEMC_LIST, domid, 32768, use_long,
keir@21471 3282 0, _buf);
keir@21471 3283 if (rc < 0) {
keir@21471 3284 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3285 "Can not get tmem list");
keir@21471 3286 return NULL;
keir@21471 3287 }
keir@21471 3288
keir@21471 3289 return strdup(_buf);
keir@21471 3290 }
keir@21471 3291
keir@21471 3292 int libxl_tmem_freeze(struct libxl_ctx *ctx, uint32_t domid)
keir@21471 3293 {
keir@21471 3294 int rc;
keir@21471 3295
keir@21471 3296 rc = xc_tmem_control(ctx->xch, -1, TMEMC_FREEZE, domid, 0, 0,
keir@21471 3297 0, NULL);
keir@21471 3298 if (rc < 0) {
keir@21471 3299 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3300 "Can not freeze tmem pools");
gianni@21892 3301 return ERROR_FAIL;
keir@21471 3302 }
keir@21471 3303
keir@21471 3304 return rc;
keir@21471 3305 }
keir@21471 3306
keir@21471 3307 int libxl_tmem_destroy(struct libxl_ctx *ctx, uint32_t domid)
keir@21471 3308 {
keir@21471 3309 int rc;
keir@21471 3310
keir@21471 3311 rc = xc_tmem_control(ctx->xch, -1, TMEMC_DESTROY, domid, 0, 0,
keir@21471 3312 0, NULL);
keir@21471 3313 if (rc < 0) {
keir@21471 3314 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3315 "Can not destroy tmem pools");
gianni@21892 3316 return ERROR_FAIL;
keir@21471 3317 }
keir@21471 3318
keir@21471 3319 return rc;
keir@21471 3320 }
keir@21471 3321
keir@21471 3322 int libxl_tmem_thaw(struct libxl_ctx *ctx, uint32_t domid)
keir@21471 3323 {
keir@21471 3324 int rc;
keir@21471 3325
keir@21471 3326 rc = xc_tmem_control(ctx->xch, -1, TMEMC_THAW, domid, 0, 0,
keir@21471 3327 0, NULL);
keir@21471 3328 if (rc < 0) {
keir@21471 3329 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3330 "Can not thaw tmem pools");
gianni@21892 3331 return ERROR_FAIL;
keir@21471 3332 }
keir@21471 3333
keir@21471 3334 return rc;