debuggers.hg

annotate tools/libxl/libxl.c @ 22040:2e08ec0028e4

tools: xenconsole[d] and libxl: multiple console support

This patch implements the new protocol for handling pv consoles and
emulated serials as described in the document docs/misc/console.txt.

The changes are:

- xenconsoled: do not write the pty under serial in xenstore if
xenconsoled is handling a consolepath;

- xenconsole: implement support for an explicit console type parameter;
the parameter can be "pv", to specify that the user wants to
connect to a pv console, or "serial", to specify that the user wants to
connect to an emulated serial. If the type parameter hasn't been
specified be the user, xenconsole tries to guess which type of console
it has to connect to, defaulting to pv console for pv guests and
emulated serial for hvm guests.

- xenconsole: use the new xenstore paths;

- libxl: rename libxl_console_constype to libxl_console_consback:
constype is used to to specify whether qemu or xenconsoled provides the
backend, so I renamed it to libxl_console_consback to make it more
obvious that we are talking about backends;

- libxl: add a new libxl_console_constype to specify if the console is
an emulated serial or a pv console;

- libxl: support the new xenconsole "type" command line parameter;

- libxl: use the "output" node under console in xenstore to tell qemu
where do we want the output of this pv console to go;

- remove the legacy "serialpath" from xenconsoled altogether

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>


Also: update the QEMU_TAG to pull in the qemu part of these changes.

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