debuggers.hg

annotate tools/libxl/libxl.c @ 22396:477dda47486e

tools: change cpumaps to uint8_t

Cpumap types in tools (libxc and libxl) are changed to be based on bytes like
in the interface to the hypervisor.
To make handling easier the size of used cpumaps is always based on the
number of physical cpus supported by the hypervisor. This eliminates the need
to keep track of the cpumap size in external interfaces.
In libxl a macro for cycling through a cpumap is added (libxl_for_each_cpu).

Interfaces changed:
libxl_set_vcpuaffinity()
libxl_cpumap_alloc()
xc_vcpu_setaffinity()
xc_vcpu_getaffinity()
xc_cpupool_freeinfo()

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