debuggers.hg

annotate tools/libxl/libxl.c @ 21849:cb1ca77e4b77

libxl: add function to attach/detach a disk to/from the local VM

Useful if you need to read a guest filesystem (e.g. pygrub).

I'm not overly thrilled with the implementation WRT tap interfaces,
particularly WRT to detach. I was unable to find a way to get at the
paramters necessary to call tap_ctl_destroy so I assumed for now it
that is OK to assume that the tap device is going to be wanted for the
actual domain at some point in the immediate future and hence there is
no pressing need to destroy it.

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