debuggers.hg

annotate tools/libxl/libxl.c @ 21848:df18254561b2

libxl: support mapping files rather than carrying paths around

This will allow us to map and then unlink the file and therefore
delete the process on process exit or explicit unmap.

Using the mmaped versions of these files required rewriting build_pv
to use the xc_dom builder functionality directly rather than through
the xc_linux_build "compatibility layer". (The status of the
xc_linux_build interface as a compatibility layer seems a bit dubious
since all existing callers use it but if anything is going to replace
it then libxl seems like the likely candidate).

I'm not thrilled with the definition of the maps lifecycle. This could
be solved by adding a helper function to explicitly free the toplevel
structure.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Ian Jackson <Ian.Jackson@eu.citrix.com>
date Wed Jul 14 16:43:49 2010 +0100 (2010-07-14)
parents ad6448ee4bb6
children cb1ca77e4b77
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
keir@20462 1428 /******************************************************************************/
keir@20462 1429 int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
keir@20462 1430 {
keir@20462 1431 flexarray_t *front;
keir@20462 1432 flexarray_t *back;
keir@20462 1433 unsigned int boffset = 0;
keir@20462 1434 unsigned int foffset = 0;
keir@20462 1435 libxl_device device;
keir@21407 1436 char *dompath, **l;
keir@21407 1437 unsigned int nb;
keir@20462 1438
keir@20462 1439 front = flexarray_make(16, 1);
keir@20462 1440 if (!front)
keir@20462 1441 return ERROR_NOMEM;
keir@20462 1442 back = flexarray_make(16, 1);
keir@20462 1443 if (!back)
keir@20462 1444 return ERROR_NOMEM;
keir@20462 1445
keir@21407 1446 if (nic->devid == -1) {
keir@21407 1447 if (!(dompath = libxl_xs_get_dompath(ctx, domid))) {
keir@21407 1448 return ERROR_FAIL;
keir@21407 1449 }
keir@21407 1450 if (!(l = libxl_xs_directory(ctx, XBT_NULL,
keir@21407 1451 libxl_sprintf(ctx, "%s/device/vif", dompath), &nb))) {
keir@21407 1452 nic->devid = 0;
keir@21407 1453 } else {
keir@21407 1454 nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
keir@21407 1455 libxl_free(ctx, l);
keir@21407 1456 }
keir@21407 1457 }
keir@21407 1458
keir@20462 1459 device.backend_devid = nic->devid;
keir@20462 1460 device.backend_domid = nic->backend_domid;
keir@20462 1461 device.backend_kind = DEVICE_VIF;
keir@20462 1462 device.devid = nic->devid;
keir@20462 1463 device.domid = nic->domid;
keir@20462 1464 device.kind = DEVICE_VIF;
keir@20462 1465
keir@20516 1466 flexarray_set(back, boffset++, "frontend-id");
keir@20462 1467 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->domid));
keir@20516 1468 flexarray_set(back, boffset++, "online");
keir@20516 1469 flexarray_set(back, boffset++, "1");
keir@20516 1470 flexarray_set(back, boffset++, "state");
keir@20462 1471 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1472 flexarray_set(back, boffset++, "script");
keir@20516 1473 flexarray_set(back, boffset++, nic->script);
keir@20516 1474 flexarray_set(back, boffset++, "mac");
keir@20462 1475 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1476 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1477 nic->mac[3], nic->mac[4], nic->mac[5]));
Ian@21732 1478 flexarray_set(back, boffset++, "bridge");
Ian@21845 1479 flexarray_set(back, boffset++, libxl_strdup(ctx, nic->bridge));
keir@20516 1480 flexarray_set(back, boffset++, "handle");
keir@20462 1481 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->devid));
keir@20462 1482
keir@20516 1483 flexarray_set(front, foffset++, "backend-id");
keir@20462 1484 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->backend_domid));
keir@20516 1485 flexarray_set(front, foffset++, "state");
keir@20462 1486 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1487 flexarray_set(front, foffset++, "handle");
keir@20462 1488 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->devid));
keir@20516 1489 flexarray_set(front, foffset++, "mac");
keir@20462 1490 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1491 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1492 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20462 1493 if (0 /* protocol != native*/) {
keir@20516 1494 flexarray_set(front, foffset++, "protocol");
keir@20516 1495 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
keir@20462 1496 }
keir@20462 1497
keir@20462 1498 libxl_device_generic_add(ctx, &device,
keir@20462 1499 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20462 1500 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20462 1501
keir@20462 1502 /* FIXME: wait for plug */
keir@20516 1503 flexarray_free(back);
keir@20516 1504 flexarray_free(front);
keir@20462 1505 return 0;
keir@20462 1506 }
keir@20462 1507
keir@20626 1508 int libxl_device_nic_del(struct libxl_ctx *ctx,
keir@20626 1509 libxl_device_nic *nic, int wait)
keir@20462 1510 {
keir@20626 1511 libxl_device device;
keir@20462 1512
keir@20626 1513 device.backend_devid = nic->devid;
keir@20626 1514 device.backend_domid = nic->backend_domid;
keir@20626 1515 device.backend_kind = DEVICE_VIF;
keir@20626 1516 device.devid = nic->devid;
keir@20626 1517 device.domid = nic->domid;
keir@20626 1518 device.kind = DEVICE_VIF;
keir@20626 1519
keir@20626 1520 return libxl_device_del(ctx, &device, wait);
keir@20462 1521 }
keir@20462 1522
keir@21408 1523 libxl_nicinfo *libxl_list_nics(struct libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
keir@21408 1524 {
keir@21408 1525 char *dompath, *nic_path_fe;
keir@21408 1526 char **l;
keir@21408 1527 char *val, *tok;
keir@21408 1528 unsigned int nb_nics, i;
keir@21408 1529 libxl_nicinfo *res, *nics;
keir@21408 1530
keir@21408 1531 dompath = libxl_xs_get_dompath(ctx, domid);
keir@21408 1532 if (!dompath) {
keir@21408 1533 return NULL;
keir@21408 1534 }
keir@21408 1535 l = libxl_xs_directory(ctx, XBT_NULL,
keir@21408 1536 libxl_sprintf(ctx, "%s/device/vif", dompath), &nb_nics);
keir@21408 1537 if (!l) {
keir@21408 1538 return NULL;
keir@21408 1539 }
keir@21408 1540 res = libxl_calloc(ctx, nb_nics, sizeof (libxl_device_nic));
keir@21408 1541 if (!res) {
keir@21408 1542 libxl_free(ctx, l);
keir@21408 1543 return NULL;
keir@21408 1544 }
keir@21408 1545 nics = res;
keir@21408 1546 for (*nb = nb_nics; nb_nics > 0; --nb_nics, ++l, ++nics) {
keir@21408 1547 nic_path_fe = libxl_sprintf(ctx, "%s/device/vif/%s", dompath, *l);
keir@21408 1548
keir@21408 1549 nics->backend = libxl_xs_read(ctx, XBT_NULL,
keir@21408 1550 libxl_sprintf(ctx, "%s/backend", nic_path_fe));
keir@21408 1551 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", nic_path_fe));
keir@21408 1552 nics->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21408 1553
keir@21408 1554 nics->devid = strtoul(*l, NULL, 10);
keir@21408 1555 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", nic_path_fe));
keir@21408 1556 nics->state = val ? strtoul(val, NULL, 10) : -1;
keir@21408 1557 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", nic_path_fe));
keir@21408 1558 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21408 1559 ++i, tok = strtok(NULL, ":")) {
keir@21408 1560 nics->mac[i] = strtoul(tok, NULL, 16);
keir@21408 1561 }
keir@21408 1562 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/event-channel", nic_path_fe));
keir@21408 1563 nics->evtch = val ? strtol(val, NULL, 10) : -1;
keir@21408 1564 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/tx-ring-ref", nic_path_fe));
keir@21408 1565 nics->rref_tx = val ? strtol(val, NULL, 10) : -1;
keir@21408 1566 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/rx-ring-ref", nic_path_fe));
keir@21408 1567 nics->rref_rx = val ? strtol(val, NULL, 10) : -1;
keir@21408 1568 nics->frontend = libxl_xs_read(ctx, XBT_NULL,
keir@21408 1569 libxl_sprintf(ctx, "%s/frontend", nics->backend));
keir@21408 1570 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", nics->backend));
keir@21408 1571 nics->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21408 1572 nics->script = libxl_xs_read(ctx, XBT_NULL,
keir@21408 1573 libxl_sprintf(ctx, "%s/script", nics->backend));
keir@21408 1574
keir@21408 1575 libxl_free(ctx, nic_path_fe);
keir@21408 1576 }
keir@21408 1577
keir@21408 1578 libxl_free(ctx, l);
keir@21408 1579 return res;
keir@21408 1580 }
keir@21408 1581
keir@21580 1582 /******************************************************************************/
keir@21580 1583 int libxl_device_net2_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2)
keir@21580 1584 {
keir@21580 1585 flexarray_t *front, *back;
keir@21580 1586 unsigned int boffset = 0, foffset = 0;
keir@21580 1587 libxl_device device;
keir@21580 1588 char *dompath, *dom, **l;
keir@21580 1589 unsigned int nb;
keir@21580 1590
keir@21580 1591 front = flexarray_make(16, 1);
keir@21580 1592 if (!front)
keir@21580 1593 return ERROR_NOMEM;
keir@21580 1594 back = flexarray_make(16, 1);
keir@21580 1595 if (!back)
keir@21580 1596 return ERROR_NOMEM;
keir@21580 1597
keir@21580 1598 if (!(dompath = libxl_xs_get_dompath(ctx, domid))) {
keir@21580 1599 return ERROR_FAIL;
keir@21580 1600 }
keir@21580 1601 dom = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/name", dompath));
keir@21580 1602
keir@21580 1603 if (net2->devid == -1) {
keir@21580 1604 if (!(l = libxl_xs_directory(ctx, XBT_NULL,
keir@21580 1605 libxl_sprintf(ctx, "%s/device/vif2", dompath), &nb))) {
keir@21580 1606 net2->devid = 0;
keir@21580 1607 } else {
keir@21580 1608 net2->devid = strtoul(l[nb - 1], NULL, 10) + 1;
keir@21580 1609 libxl_free(ctx, l);
keir@21580 1610 }
keir@21580 1611 }
keir@21580 1612
keir@21580 1613 device.backend_devid = net2->devid;
keir@21580 1614 device.backend_domid = net2->backend_domid;
keir@21580 1615 device.backend_kind = DEVICE_VIF2;
keir@21580 1616 device.devid = net2->devid;
keir@21580 1617 device.domid = net2->domid;
keir@21580 1618 device.kind = DEVICE_VIF2;
keir@21580 1619
keir@21580 1620 flexarray_set(back, boffset++, "domain");
keir@21580 1621 flexarray_set(back, boffset++, dom);
keir@21580 1622 flexarray_set(back, boffset++, "frontend-id");
keir@21580 1623 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->domid));
keir@21580 1624
keir@21580 1625 flexarray_set(back, boffset++, "local-trusted");
keir@21580 1626 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->back_trusted));
keir@21580 1627 flexarray_set(back, boffset++, "mac");
keir@21580 1628 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1629 net2->back_mac[0], net2->back_mac[1],
keir@21580 1630 net2->back_mac[2], net2->back_mac[3],
keir@21580 1631 net2->back_mac[4], net2->back_mac[5]));
keir@21580 1632
keir@21580 1633 flexarray_set(back, boffset++, "remote-trusted");
keir@21580 1634 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->trusted));
keir@21580 1635 flexarray_set(back, boffset++, "remote-mac");
keir@21580 1636 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1637 net2->front_mac[0], net2->front_mac[1],
keir@21580 1638 net2->front_mac[2], net2->front_mac[3],
keir@21580 1639 net2->front_mac[4], net2->front_mac[5]));
keir@21580 1640
keir@21580 1641 flexarray_set(back, boffset++, "max-bypasses");
keir@21580 1642 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->max_bypasses));
keir@21580 1643 flexarray_set(back, boffset++, "filter-mac");
keir@21580 1644 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", !!(net2->filter_mac)));
keir@21580 1645 flexarray_set(back, boffset++, "handle");
keir@21580 1646 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->devid));
keir@21580 1647 flexarray_set(back, boffset++, "online");
keir@21580 1648 flexarray_set(back, boffset++, "1");
keir@21580 1649 flexarray_set(back, boffset++, "state");
keir@21580 1650 flexarray_set(back, boffset++, "1");
keir@21580 1651
keir@21580 1652 flexarray_set(front, foffset++, "backend-id");
keir@21580 1653 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->backend_domid));
keir@21580 1654
keir@21580 1655 flexarray_set(front, foffset++, "local-trusted");
keir@21580 1656 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->trusted));
keir@21580 1657 flexarray_set(front, foffset++, "mac");
keir@21580 1658 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1659 net2->front_mac[0], net2->front_mac[1],
keir@21580 1660 net2->front_mac[2], net2->front_mac[3],
keir@21580 1661 net2->front_mac[4], net2->front_mac[5]));
keir@21580 1662
keir@21580 1663 flexarray_set(front, foffset++, "remote-trusted");
keir@21580 1664 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->back_trusted));
keir@21580 1665 flexarray_set(front, foffset++, "remote-mac");
keir@21580 1666 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 1667 net2->back_mac[0], net2->back_mac[1],
keir@21580 1668 net2->back_mac[2], net2->back_mac[3],
keir@21580 1669 net2->back_mac[4], net2->back_mac[5]));
keir@21580 1670
keir@21580 1671 flexarray_set(front, foffset++, "filter-mac");
keir@21580 1672 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", !!(net2->filter_mac)));
keir@21580 1673 flexarray_set(front, foffset++, "state");
keir@21580 1674 flexarray_set(front, foffset++, "1");
keir@21580 1675
keir@21580 1676 libxl_device_generic_add(ctx, &device,
keir@21580 1677 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@21580 1678 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@21580 1679
keir@21580 1680 /* FIXME: wait for plug */
keir@21580 1681 flexarray_free(back);
keir@21580 1682 flexarray_free(front);
keir@21580 1683 return 0;
keir@21580 1684 }
keir@21408 1685
keir@21581 1686 libxl_net2info *libxl_device_net2_list(struct libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
keir@21581 1687 {
keir@21581 1688 char *dompath, *net2_path_fe;
keir@21581 1689 char **l;
keir@21581 1690 char *val, *tok;
keir@21581 1691 unsigned int nb_net2s, i;
keir@21581 1692 libxl_net2info *res, *net2s;
keir@21581 1693
keir@21581 1694 dompath = libxl_xs_get_dompath(ctx, domid);
keir@21581 1695 if (!dompath) {
keir@21581 1696 return NULL;
keir@21581 1697 }
keir@21581 1698 l = libxl_xs_directory(ctx, XBT_NULL,
keir@21581 1699 libxl_sprintf(ctx, "%s/device/vif2", dompath), &nb_net2s);
keir@21581 1700 if (!l) {
keir@21581 1701 return NULL;
keir@21581 1702 }
keir@21581 1703 res = libxl_calloc(ctx, nb_net2s, sizeof (libxl_net2info));
keir@21581 1704 if (!res) {
keir@21581 1705 libxl_free(ctx, l);
keir@21581 1706 return NULL;
keir@21581 1707 }
keir@21581 1708 net2s = res;
keir@21581 1709 for (*nb = nb_net2s; nb_net2s > 0; --nb_net2s, ++l, ++net2s) {
keir@21581 1710 net2_path_fe = libxl_sprintf(ctx, "%s/device/vif2/%s", dompath, *l);
keir@21581 1711
keir@21581 1712 net2s->backend = libxl_xs_read(ctx, XBT_NULL,
keir@21581 1713 libxl_sprintf(ctx, "%s/backend", net2_path_fe));
keir@21581 1714 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", net2_path_fe));
keir@21581 1715 net2s->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1716
keir@21581 1717 net2s->devid = strtoul(*l, NULL, 10);
keir@21581 1718 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", net2_path_fe));
keir@21581 1719 net2s->state = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1720
keir@21581 1721 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", net2_path_fe));
keir@21581 1722 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21581 1723 ++i, tok = strtok(NULL, ":")) {
keir@21581 1724 net2s->mac[i] = strtoul(tok, NULL, 16);
keir@21581 1725 }
keir@21581 1726 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/remote-trusted", net2_path_fe));
keir@21581 1727 net2s->trusted = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1728
keir@21581 1729 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/remote-mac", net2_path_fe));
keir@21581 1730 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21581 1731 ++i, tok = strtok(NULL, ":")) {
keir@21581 1732 net2s->back_mac[i] = strtoul(tok, NULL, 16);
keir@21581 1733 }
keir@21581 1734 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/filter-mac", net2_path_fe));
keir@21581 1735 net2s->filter_mac = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1736
keir@21581 1737 net2s->frontend = libxl_xs_read(ctx, XBT_NULL,
keir@21581 1738 libxl_sprintf(ctx, "%s/frontend", net2s->backend));
keir@21581 1739 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", net2s->backend));
keir@21581 1740 net2s->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21581 1741 libxl_free(ctx, net2_path_fe);
keir@21581 1742 }
keir@21581 1743
keir@21581 1744 libxl_free(ctx, l);
keir@21581 1745 return res;
keir@21581 1746 }
keir@21581 1747
keir@21582 1748 int libxl_device_net2_del(struct libxl_ctx *ctx, libxl_device_net2 *net2, int wait)
keir@21582 1749 {
keir@21582 1750 libxl_device device;
keir@21582 1751
keir@21582 1752 device.backend_devid = net2->devid;
keir@21582 1753 device.backend_domid = net2->backend_domid;
keir@21582 1754 device.backend_kind = DEVICE_VIF2;
keir@21582 1755 device.devid = net2->devid;
keir@21582 1756 device.domid = net2->domid;
keir@21582 1757 device.kind = DEVICE_VIF2;
keir@21582 1758
keir@21582 1759 return libxl_device_del(ctx, &device, wait);
keir@21582 1760 }
keir@21582 1761
keir@21581 1762
keir@20462 1763 /******************************************************************************/
keir@20509 1764 int libxl_device_console_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
keir@20462 1765 {
keir@20509 1766 flexarray_t *front;
keir@20509 1767 flexarray_t *back;
keir@20509 1768 unsigned int boffset = 0;
keir@20509 1769 unsigned int foffset = 0;
keir@20509 1770 libxl_device device;
keir@20509 1771
keir@20509 1772 if (console->build_state) {
keir@20509 1773 xs_transaction_t t;
keir@20509 1774 char **ents = (char **) libxl_calloc(ctx, 9, sizeof(char *));
keir@20516 1775 ents[0] = "console/port";
keir@20509 1776 ents[1] = libxl_sprintf(ctx, "%"PRIu32, console->build_state->console_port);
keir@20516 1777 ents[2] = "console/ring-ref";
keir@20509 1778 ents[3] = libxl_sprintf(ctx, "%lu", console->build_state->console_mfn);
keir@20516 1779 ents[4] = "console/limit";
keir@20509 1780 ents[5] = libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT);
keir@20516 1781 ents[6] = "console/type";
keir@20509 1782 if (console->constype == CONSTYPE_XENCONSOLED)
keir@20509 1783 ents[7] = "xenconsoled";
keir@20509 1784 else
keir@20509 1785 ents[7] = "ioemu";
keir@20509 1786 retry_transaction:
keir@20509 1787 t = xs_transaction_start(ctx->xsh);
keir@20516 1788 libxl_xs_writev(ctx, t, libxl_xs_get_dompath(ctx, console->domid), ents);
keir@20509 1789 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20509 1790 if (errno == EAGAIN)
keir@20509 1791 goto retry_transaction;
keir@20509 1792 }
keir@20509 1793
keir@20509 1794 front = flexarray_make(16, 1);
keir@20509 1795 if (!front)
keir@20509 1796 return ERROR_NOMEM;
keir@20509 1797 back = flexarray_make(16, 1);
keir@20509 1798 if (!back)
keir@20509 1799 return ERROR_NOMEM;
keir@20509 1800
keir@20509 1801 device.backend_devid = console->devid;
keir@20509 1802 device.backend_domid = console->backend_domid;
keir@20509 1803 device.backend_kind = DEVICE_CONSOLE;
keir@20509 1804 device.devid = console->devid;
keir@20509 1805 device.domid = console->domid;
keir@20509 1806 device.kind = DEVICE_CONSOLE;
keir@20509 1807
keir@20516 1808 flexarray_set(back, boffset++, "frontend-id");
keir@20509 1809 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", console->domid));
keir@20516 1810 flexarray_set(back, boffset++, "online");
keir@20516 1811 flexarray_set(back, boffset++, "1");
keir@20516 1812 flexarray_set(back, boffset++, "state");
keir@20509 1813 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1814 flexarray_set(back, boffset++, "domain");
keir@20516 1815 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20516 1816 flexarray_set(back, boffset++, "protocol");
keir@20516 1817 flexarray_set(back, boffset++, LIBXL_XENCONSOLE_PROTOCOL);
keir@20509 1818
keir@20516 1819 flexarray_set(front, foffset++, "backend-id");
keir@20509 1820 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", console->backend_domid));
keir@20516 1821 flexarray_set(front, foffset++, "state");
keir@20509 1822 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1823 flexarray_set(front, foffset++, "limit");
keir@20509 1824 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT));
keir@20516 1825 flexarray_set(front, foffset++, "protocol");
keir@20516 1826 flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL);
keir@20516 1827 flexarray_set(front, foffset++, "type");
keir@20509 1828 if (console->constype == CONSTYPE_XENCONSOLED)
keir@20516 1829 flexarray_set(front, foffset++, "xenconsoled");
keir@20509 1830 else
keir@20516 1831 flexarray_set(front, foffset++, "ioemu");
keir@20509 1832
keir@20509 1833 libxl_device_generic_add(ctx, &device,
keir@20509 1834 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 1835 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20516 1836 flexarray_free(back);
keir@20516 1837 flexarray_free(front);
keir@20509 1838
keir@20509 1839 return 0;
keir@20509 1840 }
keir@20509 1841
keir@20509 1842 /******************************************************************************/
keir@20509 1843 int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
keir@20509 1844 {
keir@20509 1845 flexarray_t *front;
keir@20509 1846 flexarray_t *back;
keir@20509 1847 unsigned int boffset = 0;
keir@20509 1848 unsigned int foffset = 0;
keir@20509 1849 libxl_device device;
keir@20509 1850
keir@20509 1851 front = flexarray_make(16, 1);
keir@20509 1852 if (!front)
keir@20509 1853 return ERROR_NOMEM;
keir@20509 1854 back = flexarray_make(16, 1);
keir@20509 1855 if (!back)
keir@20509 1856 return ERROR_NOMEM;
keir@20509 1857
keir@20509 1858 device.backend_devid = vkb->devid;
keir@20509 1859 device.backend_domid = vkb->backend_domid;
keir@20509 1860 device.backend_kind = DEVICE_VKBD;
keir@20509 1861 device.devid = vkb->devid;
keir@20509 1862 device.domid = vkb->domid;
keir@20509 1863 device.kind = DEVICE_VKBD;
keir@20509 1864
keir@20516 1865 flexarray_set(back, boffset++, "frontend-id");
keir@20509 1866 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vkb->domid));
keir@20516 1867 flexarray_set(back, boffset++, "online");
keir@20516 1868 flexarray_set(back, boffset++, "1");
keir@20516 1869 flexarray_set(back, boffset++, "state");
keir@20509 1870 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1871 flexarray_set(back, boffset++, "domain");
keir@20516 1872 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20509 1873
keir@20516 1874 flexarray_set(front, foffset++, "backend-id");
keir@20509 1875 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vkb->backend_domid));
keir@20516 1876 flexarray_set(front, foffset++, "state");
keir@20509 1877 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 1878
keir@20509 1879 libxl_device_generic_add(ctx, &device,
keir@20509 1880 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 1881 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20516 1882 flexarray_free(back);
keir@20516 1883 flexarray_free(front);
keir@20509 1884
keir@20509 1885 return 0;
keir@20462 1886 }
keir@20462 1887
keir@20462 1888 int libxl_device_vkb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 1889 {
keir@20462 1890 return ERROR_NI;
keir@20462 1891 }
keir@20462 1892
keir@20462 1893 int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 1894 {
keir@20462 1895 return ERROR_NI;
keir@20462 1896 }
keir@20462 1897
keir@20637 1898 libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t domid, int *num)
keir@20637 1899 {
keir@20637 1900 char *be_path_tap, *be_path_vbd;
keir@21411 1901 libxl_device_disk *dend, *disks, *ret = NULL;
keir@21411 1902 char **b, **l = NULL;
keir@20637 1903 unsigned int numl;
keir@20637 1904 char *type;
keir@20637 1905
keir@20637 1906 be_path_vbd = libxl_sprintf(ctx, "%s/backend/vbd/%d", libxl_xs_get_dompath(ctx, 0), domid);
keir@20637 1907 be_path_tap = libxl_sprintf(ctx, "%s/backend/tap/%d", libxl_xs_get_dompath(ctx, 0), domid);
keir@20637 1908
keir@21411 1909 b = l = libxl_xs_directory(ctx, XBT_NULL, be_path_vbd, &numl);
keir@20637 1910 if (l) {
keir@21411 1911 ret = realloc(ret, sizeof(libxl_device_disk) * numl);
keir@21411 1912 disks = ret;
keir@21411 1913 *num = numl;
keir@21411 1914 dend = ret + *num;
keir@21411 1915 for (; disks < dend; ++disks, ++l) {
keir@21411 1916 disks->backend_domid = 0;
keir@21411 1917 disks->domid = domid;
keir@21411 1918 disks->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/params", be_path_vbd, *l));
keir@21411 1919 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 1920 disks->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/dev", be_path_vbd, *l));
keir@21411 1921 disks->unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/removable", be_path_vbd, *l)));
keir@21411 1922 if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/mode", be_path_vbd, *l)), "w"))
keir@21411 1923 disks->readwrite = 1;
keir@20637 1924 else
keir@21411 1925 disks->readwrite = 0;
keir@21411 1926 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 1927 disks->is_cdrom = !strcmp(type, "cdrom");
keir@20637 1928 }
keir@21411 1929 libxl_free(ctx, b);
keir@20637 1930 }
keir@21411 1931 b = l = libxl_xs_directory(ctx, XBT_NULL, be_path_tap, &numl);
keir@20637 1932 if (l) {
keir@21411 1933 ret = realloc(ret, sizeof(libxl_device_disk) * (*num + numl));
keir@21411 1934 disks = ret + *num;
keir@21411 1935 *num += numl;
keir@21411 1936 for (dend = ret + *num; disks < dend; ++disks, ++l) {
keir@21411 1937 disks->backend_domid = 0;
keir@21411 1938 disks->domid = domid;
keir@21411 1939 disks->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/params", be_path_tap, *l));
keir@21411 1940 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 1941 disks->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/dev", be_path_tap, *l));
keir@21411 1942 disks->unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/removable", be_path_tap, *l)));
keir@21411 1943 if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/mode", be_path_tap, *l)), "w"))
keir@21411 1944 disks->readwrite = 1;
keir@20637 1945 else
keir@21411 1946 disks->readwrite = 0;
keir@21411 1947 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 1948 disks->is_cdrom = !strcmp(type, "cdrom");
keir@20637 1949 }
keir@21411 1950 libxl_free(ctx, b);
keir@20637 1951 }
keir@21411 1952 return ret;
keir@21411 1953 }
keir@21411 1954
keir@21411 1955 int libxl_device_disk_getinfo(struct libxl_ctx *ctx, uint32_t domid,
keir@21411 1956 libxl_device_disk *disk, libxl_diskinfo *diskinfo)
keir@21411 1957 {
keir@21411 1958 char *dompath, *diskpath;
keir@21411 1959 char *val;
keir@21411 1960
keir@21411 1961 dompath = libxl_xs_get_dompath(ctx, domid);
keir@21411 1962 diskinfo->devid = device_disk_dev_number(disk->virtpath);
keir@21411 1963
keir@21411 1964 /* tap devices entries in xenstore are written as vbd devices. */
keir@21411 1965 diskpath = libxl_sprintf(ctx, "%s/device/vbd/%d", dompath, diskinfo->devid);
keir@21411 1966 diskinfo->backend = libxl_xs_read(ctx, XBT_NULL,
keir@21411 1967 libxl_sprintf(ctx, "%s/backend", diskpath));
keir@21411 1968 if (!diskinfo->backend) {
keir@21411 1969 return ERROR_FAIL;
keir@21411 1970 }
keir@21411 1971 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", diskpath));
keir@21411 1972 diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21411 1973 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", diskpath));
keir@21411 1974 diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
keir@21411 1975 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/event-channel", diskpath));
keir@21411 1976 diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
keir@21411 1977 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/ring-ref", diskpath));
keir@21411 1978 diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
keir@21411 1979 diskinfo->frontend = libxl_xs_read(ctx, XBT_NULL,
keir@21411 1980 libxl_sprintf(ctx, "%s/frontend", diskinfo->backend));
keir@21411 1981 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", diskinfo->backend));
keir@21411 1982 diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21411 1983
keir@21411 1984 return 0;
keir@20637 1985 }
keir@20637 1986
keir@20637 1987 int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20637 1988 {
keir@20637 1989 int num, i;
keir@20637 1990 uint32_t stubdomid;
keir@20637 1991 libxl_device_disk *disks;
keir@20637 1992
keir@20637 1993 if (!disk->physpath) {
keir@20637 1994 disk->physpath = "";
keir@20637 1995 disk->phystype = PHYSTYPE_PHY;
keir@20637 1996 }
keir@20637 1997 disks = libxl_device_disk_list(ctx, domid, &num);
keir@20637 1998 for (i = 0; i < num; i++) {
keir@20637 1999 if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath))
keir@20637 2000 /* found */
keir@20637 2001 break;
keir@20637 2002 }
keir@20637 2003 if (i == num) {
keir@20637 2004 XL_LOG(ctx, XL_LOG_ERROR, "Virtual device not found");
keir@20637 2005 return -1;
keir@20637 2006 }
keir@20637 2007 libxl_device_disk_del(ctx, disks + i, 1);
keir@20637 2008 libxl_device_disk_add(ctx, domid, disk);
keir@20637 2009 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20637 2010 if (stubdomid) {
keir@20781 2011 disks[i].domid = stubdomid;
keir@20637 2012 libxl_device_disk_del(ctx, disks + i, 1);
keir@20781 2013 disk->domid = stubdomid;
keir@20637 2014 libxl_device_disk_add(ctx, stubdomid, disk);
keir@20781 2015 disk->domid = domid;
keir@20637 2016 }
keir@20637 2017 return 0;
keir@20637 2018 }
keir@20637 2019
keir@20462 2020 /******************************************************************************/
keir@20509 2021 static int libxl_build_xenpv_qemu_args(struct libxl_ctx *ctx,
keir@20509 2022 libxl_device_vfb *vfb,
keir@20509 2023 int num_console,
keir@20509 2024 libxl_device_console *console,
keir@20860 2025 libxl_device_model_info *info)
keir@20860 2026 {
keir@20509 2027 int i = 0, j = 0, num = 0;
keir@20509 2028 memset(info, 0x00, sizeof(libxl_device_model_info));
keir@20509 2029
keir@20509 2030 info->vnc = vfb->vnc;
keir@20509 2031 if (vfb->vnclisten)
Ian@21845 2032 info->vnclisten = libxl_strdup(ctx, vfb->vnclisten);
keir@20509 2033 info->vncdisplay = vfb->vncdisplay;
keir@20509 2034 info->vncunused = vfb->vncunused;
keir@21362 2035 if (vfb->vncpasswd)
keir@21362 2036 info->vncpasswd = vfb->vncpasswd;
keir@20509 2037 if (vfb->keymap)
Ian@21845 2038 info->keymap = libxl_strdup(ctx, vfb->keymap);
keir@20509 2039 info->sdl = vfb->sdl;
keir@20509 2040 info->opengl = vfb->opengl;
keir@20509 2041 for (i = 0; i < num_console; i++) {
keir@20509 2042 if (console->constype == CONSTYPE_IOEMU)
keir@20509 2043 num++;
keir@20509 2044 }
keir@20509 2045 if (num > 0) {
keir@20860 2046 uint32_t guest_domid;
keir@20860 2047 if (libxl_is_stubdom(ctx, vfb->domid, &guest_domid)) {
keir@20599 2048 char *filename;
keir@20599 2049 char *name = libxl_sprintf(ctx, "qemu-dm-%s", libxl_domid_to_name(ctx, guest_domid));
keir@20599 2050 libxl_create_logfile(ctx, name, &filename);
keir@20599 2051 info->serial = libxl_sprintf(ctx, "file:%s", filename);
keir@20599 2052 free(filename);
keir@20599 2053 } else {
keir@20599 2054 info->serial = "pty";
keir@20599 2055 }
keir@20509 2056 num--;
keir@20509 2057 }
keir@20509 2058 if (num > 0) {
keir@20509 2059 info->extra = (char **) libxl_calloc(ctx, num * 2 + 1, sizeof(char *));
keir@20509 2060 for (j = 0; j < num * 2; j = j + 2) {
keir@20509 2061 info->extra[j] = "-serial";
keir@20509 2062 info->extra[j + 1] = "pty";
keir@20509 2063 }
keir@20509 2064 info->extra[j] = NULL;
keir@20509 2065 }
keir@20509 2066 info->domid = vfb->domid;
keir@20509 2067 info->dom_name = libxl_domid_to_name(ctx, vfb->domid);
keir@21376 2068 info->device_model = libxl_abs_path(ctx, "qemu-dm", libxl_libexec_path());
keir@20509 2069 info->type = XENPV;
keir@20509 2070 return 0;
keir@20509 2071 }
keir@20509 2072
keir@20509 2073 int libxl_create_xenpv_qemu(struct libxl_ctx *ctx, libxl_device_vfb *vfb,
keir@20514 2074 int num_console, libxl_device_console *console,
keir@20514 2075 struct libxl_device_model_starting **starting_r)
keir@20509 2076 {
keir@20509 2077 libxl_device_model_info info;
keir@20509 2078
keir@20509 2079 libxl_build_xenpv_qemu_args(ctx, vfb, num_console, console, &info);
keir@20542 2080 libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r);
keir@20509 2081 return 0;
keir@20509 2082 }
keir@20509 2083
keir@20509 2084 int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
keir@20462 2085 {
keir@20509 2086 flexarray_t *front;
keir@20509 2087 flexarray_t *back;
keir@20509 2088 unsigned int boffset = 0;
keir@20509 2089 unsigned int foffset = 0;
keir@20509 2090 libxl_device device;
keir@20509 2091
keir@20509 2092 front = flexarray_make(16, 1);
keir@20509 2093 if (!front)
keir@20509 2094 return ERROR_NOMEM;
keir@20509 2095 back = flexarray_make(16, 1);
keir@20509 2096 if (!back)
keir@20509 2097 return ERROR_NOMEM;
keir@20509 2098
keir@20509 2099 device.backend_devid = vfb->devid;
keir@20509 2100 device.backend_domid = vfb->backend_domid;
keir@20509 2101 device.backend_kind = DEVICE_VFB;
keir@20509 2102 device.devid = vfb->devid;
keir@20509 2103 device.domid = vfb->domid;
keir@20509 2104 device.kind = DEVICE_VFB;
keir@20509 2105
keir@20516 2106 flexarray_set(back, boffset++, "frontend-id");
keir@20509 2107 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->domid));
keir@20516 2108 flexarray_set(back, boffset++, "online");
keir@20516 2109 flexarray_set(back, boffset++, "1");
keir@20516 2110 flexarray_set(back, boffset++, "state");
keir@20509 2111 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 2112 flexarray_set(back, boffset++, "domain");
keir@20516 2113 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20516 2114 flexarray_set(back, boffset++, "vnc");
keir@20509 2115 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vnc));
keir@20516 2116 flexarray_set(back, boffset++, "vnclisten");
keir@20516 2117 flexarray_set(back, boffset++, vfb->vnclisten);
keir@21362 2118 flexarray_set(back, boffset++, "vncpasswd");
keir@21362 2119 flexarray_set(back, boffset++, vfb->vncpasswd);
keir@20516 2120 flexarray_set(back, boffset++, "vncdisplay");
keir@20509 2121 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncdisplay));
keir@20516 2122 flexarray_set(back, boffset++, "vncunused");
keir@20509 2123 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncunused));
keir@20516 2124 flexarray_set(back, boffset++, "sdl");
keir@20509 2125 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->sdl));
keir@20516 2126 flexarray_set(back, boffset++, "opengl");
keir@20509 2127 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->opengl));
keir@20509 2128 if (vfb->xauthority) {
keir@20516 2129 flexarray_set(back, boffset++, "xauthority");
keir@20516 2130 flexarray_set(back, boffset++, vfb->xauthority);
keir@20509 2131 }
keir@20509 2132 if (vfb->display) {
keir@20516 2133 flexarray_set(back, boffset++, "display");
keir@20516 2134 flexarray_set(back, boffset++, vfb->display);
keir@20509 2135 }
keir@20509 2136
keir@20516 2137 flexarray_set(front, foffset++, "backend-id");
keir@20509 2138 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vfb->backend_domid));
keir@20516 2139 flexarray_set(front, foffset++, "state");
keir@20509 2140 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 2141
keir@20509 2142 libxl_device_generic_add(ctx, &device,
keir@20509 2143 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 2144 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20509 2145 flexarray_free(front);
keir@20509 2146 flexarray_free(back);
keir@20509 2147
keir@20509 2148 return 0;
keir@20462 2149 }
keir@20462 2150
keir@20462 2151 int libxl_device_vfb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 2152 {
keir@20462 2153 return ERROR_NI;
keir@20462 2154 }
keir@20462 2155
keir@20462 2156 int libxl_device_vfb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 2157 {
keir@20462 2158 return ERROR_NI;
keir@20462 2159 }
keir@20462 2160
keir@20462 2161 /******************************************************************************/
keir@20482 2162
keir@20482 2163 int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
keir@20482 2164 unsigned int bus, unsigned int dev,
keir@20482 2165 unsigned int func, unsigned int vdevfn)
keir@20482 2166 {
keir@20482 2167 pcidev->domain = domain;
keir@20482 2168 pcidev->bus = bus;
keir@20482 2169 pcidev->dev = dev;
keir@20482 2170 pcidev->func = func;
keir@20482 2171 pcidev->vdevfn = vdevfn;
keir@20482 2172 return 0;
keir@20482 2173 }
keir@20482 2174
keir@20482 2175 static int libxl_create_pci_backend(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev, int num)
keir@20482 2176 {
keir@20482 2177 flexarray_t *front;
keir@20482 2178 flexarray_t *back;
keir@20482 2179 unsigned int boffset = 0;
keir@20482 2180 unsigned int foffset = 0;
keir@20482 2181 libxl_device device;
keir@20482 2182 int i;
keir@20482 2183
keir@20482 2184 front = flexarray_make(16, 1);
keir@20482 2185 if (!front)
keir@20482 2186 return ERROR_NOMEM;
keir@20482 2187 back = flexarray_make(16, 1);
keir@20482 2188 if (!back)
keir@20482 2189 return ERROR_NOMEM;
keir@20482 2190
keir@20512 2191 XL_LOG(ctx, XL_LOG_DEBUG, "Creating pci backend");
keir@20482 2192
keir@20482 2193 /* add pci device */
keir@20482 2194 device.backend_devid = 0;
keir@20482 2195 device.backend_domid = 0;
keir@20482 2196 device.backend_kind = DEVICE_PCI;
keir@20482 2197 device.devid = 0;
keir@20482 2198 device.domid = domid;
keir@20482 2199 device.kind = DEVICE_PCI;
keir@20482 2200
keir@20516 2201 flexarray_set(back, boffset++, "frontend-id");
keir@20482 2202 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", domid));
keir@20516 2203 flexarray_set(back, boffset++, "online");
keir@20516 2204 flexarray_set(back, boffset++, "1");
keir@20516 2205 flexarray_set(back, boffset++, "state");
keir@20482 2206 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 2207 flexarray_set(back, boffset++, "domain");
keir@20516 2208 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20482 2209 for (i = 0; i < num; i++) {
keir@20482 2210 flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", i));
keir@20482 2211 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 2212 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", i));
keir@20482 2213 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 2214 if (pcidev->vdevfn) {
keir@20482 2215 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", i));
keir@20482 2216 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", pcidev->vdevfn));
keir@20482 2217 }
keir@20482 2218 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", i));
keir@20482 2219 flexarray_set(back, boffset++, libxl_sprintf(ctx, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
keir@20482 2220 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", i));
keir@20482 2221 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20482 2222 }
keir@20516 2223 flexarray_set(back, boffset++, "num_devs");
keir@20482 2224 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num));
keir@20482 2225
keir@20516 2226 flexarray_set(front, foffset++, "backend-id");
keir@20482 2227 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 0));
keir@20516 2228 flexarray_set(front, foffset++, "state");
keir@20482 2229 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20482 2230
keir@20482 2231 libxl_device_generic_add(ctx, &device,
keir@20482 2232 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20482 2233 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20482 2234
keir@20482 2235 flexarray_free(back);
keir@20482 2236 flexarray_free(front);
keir@20482 2237 return 0;
keir@20482 2238 }
keir@20482 2239
keir@20482 2240 static int libxl_device_pci_add_xenstore(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 2241 {
keir@20482 2242 flexarray_t *back;
keir@20482 2243 char *num_devs, *be_path;
keir@20482 2244 int num = 0;
keir@20482 2245 unsigned int boffset = 0;
keir@20482 2246 xs_transaction_t t;
keir@20482 2247
keir@20516 2248 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid);
keir@20482 2249 num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", be_path));
keir@20482 2250 if (!num_devs)
keir@20482 2251 return libxl_create_pci_backend(ctx, domid, pcidev, 1);
keir@20482 2252
keir@20482 2253 if (!is_hvm(ctx, domid)) {
keir@20482 2254 if (libxl_wait_for_backend(ctx, be_path, "4") < 0)
keir@20482 2255 return -1;
keir@20482 2256 }
keir@20482 2257
keir@20482 2258 back = flexarray_make(16, 1);
keir@20482 2259 if (!back)
keir@20482 2260 return ERROR_NOMEM;
keir@20482 2261
keir@20512 2262 XL_LOG(ctx, XL_LOG_DEBUG, "Adding new pci device to xenstore");
keir@20482 2263 num = atoi(num_devs);
keir@20482 2264 flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", num));
keir@20482 2265 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 2266 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", num));
keir@20482 2267 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 2268 if (pcidev->vdevfn) {
keir@20482 2269 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", num));
keir@20482 2270 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", pcidev->vdevfn));
keir@20482 2271 }
keir@20482 2272 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", num));
keir@20482 2273 flexarray_set(back, boffset++, libxl_sprintf(ctx, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
keir@20482 2274 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", num));
keir@20482 2275 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 2276 flexarray_set(back, boffset++, "num_devs");
keir@20482 2277 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num + 1));
keir@20516 2278 flexarray_set(back, boffset++, "state");
keir@20482 2279 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 7));
keir@20482 2280
keir@20482 2281 retry_transaction:
keir@20482 2282 t = xs_transaction_start(ctx->xsh);
keir@20482 2283 libxl_xs_writev(ctx, t, be_path,
keir@20482 2284 libxl_xs_kvs_of_flexarray(ctx, back, boffset));
keir@20482 2285 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20482 2286 if (errno == EAGAIN)
keir@20482 2287 goto retry_transaction;
keir@20482 2288
keir@20482 2289 flexarray_free(back);
keir@20482 2290 return 0;
keir@20482 2291 }
keir@20482 2292
keir@20482 2293 static int libxl_device_pci_remove_xenstore(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20482 2294 {
keir@20542 2295 char *be_path, *num_devs_path, *num_devs, *xsdev, *tmp, *tmppath;
keir@20542 2296 int num, i, j;
keir@20482 2297 xs_transaction_t t;
keir@20482 2298 unsigned int domain = 0, bus = 0, dev = 0, func = 0;
keir@20482 2299
keir@20516 2300 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid);
keir@20482 2301 num_devs_path = libxl_sprintf(ctx, "%s/num_devs", be_path);
keir@20482 2302 num_devs = libxl_xs_read(ctx, XBT_NULL, num_devs_path);
keir@20482 2303 if (!num_devs)
keir@20482 2304 return -1;
keir@20482 2305 num = atoi(num_devs);
keir@20482 2306
keir@20482 2307 if (!is_hvm(ctx, domid)) {
keir@20482 2308 if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
keir@20542 2309 XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", be_path);
keir@20482 2310 return -1;
keir@20482 2311 }
keir@20482 2312 }
keir@20482 2313
keir@20482 2314 for (i = 0; i < num; i++) {
keir@20482 2315 xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20482 2316 sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
keir@20482 2317 if (domain == pcidev->domain && bus == pcidev->bus &&
keir@20482 2318 pcidev->dev == dev && pcidev->func == func) {
keir@20482 2319 break;
keir@20482 2320 }
keir@20482 2321 }
keir@20482 2322 if (i == num) {
keir@20512 2323 XL_LOG(ctx, XL_LOG_ERROR, "Couldn't find the device on xenstore");
keir@20482 2324 return -1;
keir@20482 2325 }
keir@20482 2326
keir@20482 2327 retry_transaction:
keir@20482 2328 t = xs_transaction_start(ctx->xsh);
keir@20542 2329 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i), "5", strlen("5"));
keir@20482 2330 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state", be_path), "7", strlen("7"));
keir@20482 2331 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20482 2332 if (errno == EAGAIN)
keir@20482 2333 goto retry_transaction;
keir@20542 2334
keir@20542 2335 if (!is_hvm(ctx, domid)) {
keir@20542 2336 if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
keir@20542 2337 XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", be_path);
keir@20542 2338 return -1;
keir@20542 2339 }
keir@20542 2340 }
keir@20542 2341
keir@20542 2342 retry_transaction2:
keir@20542 2343 t = xs_transaction_start(ctx->xsh);
keir@20542 2344 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i));
keir@20542 2345 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, i));
keir@20542 2346 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20542 2347 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, i));
keir@20542 2348 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
keir@20542 2349 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
keir@20542 2350 libxl_xs_write(ctx, t, num_devs_path, "%d", num - 1);
keir@20542 2351 for (j = i + 1; j < num; j++) {
keir@20542 2352 tmppath = libxl_sprintf(ctx, "%s/state-%d", be_path, j);
keir@20542 2353 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2354 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2355 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2356 tmppath = libxl_sprintf(ctx, "%s/dev-%d", be_path, j);
keir@20542 2357 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2358 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2359 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2360 tmppath = libxl_sprintf(ctx, "%s/key-%d", be_path, j);
keir@20542 2361 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2362 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2363 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2364 tmppath = libxl_sprintf(ctx, "%s/vdev-%d", be_path, j);
keir@20542 2365 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2366 if (tmp) {
keir@20542 2367 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2368 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2369 }
keir@20542 2370 tmppath = libxl_sprintf(ctx, "%s/opts-%d", be_path, j);
keir@20542 2371 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2372 if (tmp) {
keir@20542 2373 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2374 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2375 }
keir@20542 2376 tmppath = libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j);
keir@20542 2377 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 2378 if (tmp) {
keir@20542 2379 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 2380 xs_rm(ctx->xsh, t, tmppath);
keir@20542 2381 }
keir@20542 2382 }
keir@20542 2383 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 2384 if (errno == EAGAIN)
keir@20542 2385 goto retry_transaction2;
keir@20542 2386
keir@20542 2387 if (num == 1) {
keir@20542 2388 char *fe_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend", be_path));
keir@20542 2389 libxl_device_destroy(ctx, be_path, 1);
keir@20542 2390 xs_rm(ctx->xsh, XBT_NULL, be_path);
keir@20542 2391 xs_rm(ctx->xsh, XBT_NULL, fe_path);
keir@20542 2392 return 0;
keir@20542 2393 }
keir@20542 2394
keir@20482 2395 return 0;
keir@20462 2396 }
keir@20462 2397
keir@20482 2398 int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 2399 {
keir@20779 2400 char *path;
keir@20482 2401 char *state, *vdevfn;
keir@20482 2402 int rc, hvm;
keir@20542 2403 int stubdomid = 0;
keir@20482 2404
keir@20482 2405 /* TODO: check if the device can be assigned */
keir@20482 2406
Ian@21711 2407 libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2408
keir@20779 2409 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20779 2410 if (stubdomid != 0) {
keir@20542 2411 libxl_device_pci pcidev_s = *pcidev;
keir@20542 2412 libxl_device_pci_add(ctx, stubdomid, &pcidev_s);
keir@20542 2413 }
keir@20542 2414
keir@20482 2415 hvm = is_hvm(ctx, domid);
keir@20482 2416 if (hvm) {
keir@20831 2417 if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 0) {
keir@20482 2418 return -1;
keir@20482 2419 }
keir@20779 2420 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 2421 state = libxl_xs_read(ctx, XBT_NULL, path);
keir@20779 2422 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 2423 if (pcidev->vdevfn)
keir@20482 2424 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF_VDEVFN, pcidev->domain,
keir@20482 2425 pcidev->bus, pcidev->dev, pcidev->func, pcidev->vdevfn);
keir@20482 2426 else
keir@20482 2427 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
keir@20482 2428 pcidev->bus, pcidev->dev, pcidev->func);
keir@20779 2429 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid);
keir@20482 2430 xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins"));
keir@20831 2431 if (libxl_wait_for_device_model(ctx, domid, "pci-inserted", NULL, NULL) < 0)
keir@20512 2432 XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
keir@20779 2433 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 2434 vdevfn = libxl_xs_read(ctx, XBT_NULL, path);
keir@20482 2435 sscanf(vdevfn + 2, "%x", &pcidev->vdevfn);
keir@20779 2436 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 2437 xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
keir@20482 2438 } else {
keir@20542 2439 char *sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
keir@20482 2440 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2441 FILE *f = fopen(sysfs_path, "r");
keir@21517 2442 unsigned long long start = 0, end = 0, flags = 0, size = 0;
keir@20482 2443 int irq = 0;
keir@20482 2444 int i;
keir@20482 2445
keir@20482 2446 if (f == NULL) {
keir@20512 2447 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 2448 return -1;
keir@20482 2449 }
keir@20482 2450 for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
keir@21517 2451 if (fscanf(f, "0x%llx 0x%llx 0x%llx\n", &start, &end, &flags) != 3)
keir@21466 2452 continue;
keir@20482 2453 size = end - start + 1;
keir@20482 2454 if (start) {
keir@20482 2455 if (flags & PCI_BAR_IO) {
keir@20482 2456 rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 1);
keir@20482 2457 if (rc < 0)
keir@21517 2458 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_ioport_permission error 0x%llx/0x%llx", start, size);
keir@20482 2459 } else {
keir@20482 2460 rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT,
keir@20482 2461 (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 1);
keir@20482 2462 if (rc < 0)
keir@21537 2463 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_iomem_permission error 0x%llx/0x%llx", start, size);
keir@20482 2464 }
keir@20482 2465 }
keir@20482 2466 }
keir@20482 2467 fclose(f);
keir@20542 2468 sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", pcidev->domain,
keir@20482 2469 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2470 f = fopen(sysfs_path, "r");
keir@20482 2471 if (f == NULL) {
keir@20512 2472 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 2473 goto out;
keir@20482 2474 }
keir@21466 2475 if ((fscanf(f, "%u", &irq) == 1) && irq) {
keir@20482 2476 rc = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
keir@20482 2477 if (rc < 0) {
keir@20512 2478 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_physdev_map_pirq irq=%d", irq);
keir@20482 2479 }
keir@20482 2480 rc = xc_domain_irq_permission(ctx->xch, domid, irq, 1);
keir@20482 2481 if (rc < 0) {
keir@20512 2482 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_irq_permission irq=%d", irq);
keir@20482 2483 }
keir@20482 2484 }
keir@20482 2485 fclose(f);
keir@20482 2486 }
keir@20482 2487 out:
keir@20860 2488 if (!libxl_is_stubdom(ctx, domid, NULL)) {
keir@20779 2489 rc = xc_assign_device(ctx->xch, domid, pcidev->value);
keir@20779 2490 if (rc < 0)
keir@20542 2491 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_assign_device failed");
keir@20542 2492 }
keir@20482 2493
keir@20482 2494 libxl_device_pci_add_xenstore(ctx, domid, pcidev);
keir@20482 2495 return 0;
keir@20462 2496 }
keir@20462 2497
keir@20482 2498 int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 2499 {
keir@20779 2500 char *path;
keir@20482 2501 char *state;
keir@20482 2502 int hvm, rc;
keir@20542 2503 int stubdomid = 0;
keir@20482 2504
keir@20482 2505 /* TODO: check if the device can be detached */
keir@20542 2506 libxl_device_pci_remove_xenstore(ctx, domid, pcidev);
keir@20482 2507
keir@20482 2508 hvm = is_hvm(ctx, domid);
keir@20482 2509 if (hvm) {
keir@20831 2510 if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 0) {
keir@20482 2511 return -1;
keir@20482 2512 }
keir@20779 2513 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 2514 state = libxl_xs_read(ctx, XBT_NULL, path);
keir@20779 2515 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 2516 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
keir@20482 2517 pcidev->bus, pcidev->dev, pcidev->func);
keir@20779 2518 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid);
keir@20482 2519 xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem"));
keir@20831 2520 if (libxl_wait_for_device_model(ctx, domid, "pci-removed", NULL, NULL) < 0) {
keir@20512 2521 XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
keir@20482 2522 return -1;
keir@20482 2523 }
keir@20779 2524 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 2525 xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
keir@20482 2526 } else {
keir@20542 2527 char *sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
keir@20482 2528 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2529 FILE *f = fopen(sysfs_path, "r");
keir@20482 2530 unsigned int start = 0, end = 0, flags = 0, size = 0;
keir@20482 2531 int irq = 0;
keir@20482 2532 int i;
keir@20482 2533
keir@20482 2534 if (f == NULL) {
keir@20512 2535 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 2536 goto skip1;
keir@20482 2537 }
keir@20482 2538 for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
keir@21466 2539 if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3)
keir@21466 2540 continue;
keir@20482 2541 size = end - start + 1;
keir@20482 2542 if (start) {
keir@20482 2543 if (flags & PCI_BAR_IO) {
keir@20482 2544 rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 0);
keir@20482 2545 if (rc < 0)
keir@20512 2546 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_ioport_permission error 0x%x/0x%x", start, size);
keir@20482 2547 } else {
keir@20482 2548 rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT,
keir@20482 2549 (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 0);
keir@20482 2550 if (rc < 0)
keir@20512 2551 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_iomem_permission error 0x%x/0x%x", start, size);
keir@20482 2552 }
keir@20482 2553 }
keir@20482 2554 }
keir@20482 2555 fclose(f);
keir@20482 2556 skip1:
keir@20542 2557 sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", pcidev->domain,
keir@20482 2558 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2559 f = fopen(sysfs_path, "r");
keir@20482 2560 if (f == NULL) {
keir@20512 2561 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 2562 goto out;
keir@20482 2563 }
keir@21466 2564 if ((fscanf(f, "%u", &irq) == 1) && irq) {
keir@20482 2565 rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
keir@20482 2566 if (rc < 0) {
keir@20512 2567 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_physdev_map_pirq irq=%d", irq);
keir@20482 2568 }
keir@20482 2569 rc = xc_domain_irq_permission(ctx->xch, domid, irq, 0);
keir@20482 2570 if (rc < 0) {
keir@20512 2571 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_irq_permission irq=%d", irq);
keir@20482 2572 }
keir@20482 2573 }
keir@20482 2574 fclose(f);
keir@20482 2575 }
keir@20482 2576 out:
Ian@21711 2577 libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2578
keir@20860 2579 if (!libxl_is_stubdom(ctx, domid, NULL)) {
keir@20779 2580 rc = xc_deassign_device(ctx->xch, domid, pcidev->value);
keir@20779 2581 if (rc < 0)
keir@20542 2582 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_deassign_device failed");
keir@20542 2583 }
keir@20542 2584
keir@20779 2585 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20779 2586 if (stubdomid != 0) {
keir@20542 2587 libxl_device_pci pcidev_s = *pcidev;
keir@20542 2588 libxl_device_pci_remove(ctx, stubdomid, &pcidev_s);
keir@20542 2589 }
keir@20542 2590
keir@20482 2591 return 0;
keir@20462 2592 }
keir@20482 2593
keir@20482 2594 libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t domid, int *num)
keir@20482 2595 {
keir@20482 2596 char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts;
keir@20482 2597 int n, i;
keir@20482 2598 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
keir@20482 2599 libxl_device_pci *pcidevs;
keir@20482 2600
keir@20516 2601 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid);
keir@20482 2602 num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", be_path));
keir@20482 2603 if (!num_devs) {
keir@20482 2604 *num = 0;
keir@20482 2605 return NULL;
keir@20482 2606 }
keir@20482 2607 n = atoi(num_devs);
keir@20779 2608 pcidevs = calloc(n, sizeof(libxl_device_pci));
keir@20482 2609 *num = n;
keir@20482 2610
keir@20482 2611 for (i = 0; i < n; i++) {
keir@20482 2612 xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20482 2613 sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
keir@20482 2614 xsvdevfn = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
keir@20482 2615 if (xsvdevfn)
keir@20482 2616 vdevfn = strtol(xsvdevfn, (char **) NULL, 16);
keir@20482 2617 libxl_device_pci_init(pcidevs + i, domain, bus, dev, func, vdevfn);
keir@20482 2618 xsopts = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
keir@20482 2619 if (xsopts) {
keir@20482 2620 char *saveptr;
keir@20482 2621 char *p = strtok_r(xsopts, ",=", &saveptr);
keir@20482 2622 do {
keir@20482 2623 while (*p == ' ')
keir@20482 2624 p++;
keir@20482 2625 if (!strcmp(p, "msitranslate")) {
keir@20482 2626 p = strtok_r(NULL, ",=", &saveptr);
keir@20482 2627 pcidevs[i].msitranslate = atoi(p);
keir@20482 2628 } else if (!strcmp(p, "power_mgmt")) {
keir@20482 2629 p = strtok_r(NULL, ",=", &saveptr);
keir@20482 2630 pcidevs[i].power_mgmt = atoi(p);
keir@20482 2631 }
keir@20482 2632 } while ((p = strtok_r(NULL, ",=", &saveptr)) != NULL);
keir@20482 2633 }
keir@20482 2634 }
keir@20482 2635 return pcidevs;
keir@20482 2636 }
keir@20482 2637
keir@20482 2638 int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20482 2639 {
keir@20482 2640 libxl_device_pci *pcidevs;
keir@20482 2641 int num, i;
keir@20482 2642
keir@20482 2643 pcidevs = libxl_device_pci_list(ctx, domid, &num);
keir@20482 2644 for (i = 0; i < num; i++) {
keir@20482 2645 if (libxl_device_pci_remove(ctx, domid, pcidevs + i) < 0)
keir@20482 2646 return -1;
keir@20482 2647 }
keir@20516 2648 free(pcidevs);
keir@20482 2649 return 0;
keir@20482 2650 }
keir@20482 2651
keir@21404 2652 int libxl_domain_setmaxmem(struct libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb)
keir@21404 2653 {
keir@21404 2654 char *mem, *endptr;
keir@21404 2655 uint32_t memorykb;
keir@21404 2656 char *dompath = libxl_xs_get_dompath(ctx, domid);
keir@21404 2657
keir@21404 2658 mem = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", dompath));
keir@21404 2659 if (!mem) {
keir@21404 2660 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot get memory info from %s/memory/target\n", dompath);
keir@21404 2661 return 1;
keir@21404 2662 }
keir@21404 2663 memorykb = strtoul(mem, &endptr, 10);
keir@21404 2664 if (*endptr != '\0') {
keir@21404 2665 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "invalid memory %s from %s/memory/target\n", mem, dompath);
keir@21404 2666 return 1;
keir@21404 2667 }
keir@21404 2668
keir@21404 2669 if (max_memkb < memorykb) {
keir@21404 2670 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "memory_static_max must be greater than or or equal to memory_dynamic_max\n");
keir@21404 2671 return 1;
keir@21404 2672 }
keir@21404 2673
keir@21404 2674 if (domid != 0)
Ian@21844 2675 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/static-max", dompath), "%"PRIu32, max_memkb);
keir@21404 2676
keir@21422 2677 return 0;
keir@21404 2678 }
keir@21404 2679
keir@21422 2680 int libxl_set_memory_target(struct libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb, int enforce)
keir@20647 2681 {
keir@20647 2682 int rc = 0;
keir@21422 2683 uint32_t memorykb = 0, videoram = 0;
keir@21405 2684 char *memmax, *endptr, *videoram_s = NULL;
keir@20647 2685 char *dompath = libxl_xs_get_dompath(ctx, domid);
keir@21374 2686 xc_domaininfo_t info;
keir@21374 2687 struct libxl_dominfo ptr;
keir@21374 2688 char *uuid;
keir@20542 2689
keir@21405 2690 if (domid) {
keir@21405 2691 memmax = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/static-max", dompath));
keir@21405 2692 if (!memmax) {
keir@21405 2693 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@21405 2694 "cannot get memory info from %s/memory/static-max\n", dompath);
keir@21405 2695 return 1;
keir@21405 2696 }
keir@21405 2697 memorykb = strtoul(memmax, &endptr, 10);
keir@21405 2698 if (*endptr != '\0') {
keir@21405 2699 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@21405 2700 "invalid max memory %s from %s/memory/static-max\n", memmax, dompath);
keir@21405 2701 return 1;
keir@21405 2702 }
keir@21405 2703
keir@21405 2704 if (target_memkb > memorykb) {
keir@21504 2705 XL_LOG(ctx, XL_LOG_ERROR,
keir@21405 2706 "memory_dynamic_max must be less than or equal to memory_static_max\n");
keir@21405 2707 return 1;
keir@21405 2708 }
keir@21405 2709 }
keir@21405 2710
keir@20647 2711 videoram_s = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/videoram", dompath));
keir@21314 2712 videoram = videoram_s ? atoi(videoram_s) : 0;
keir@20647 2713
Ian@21844 2714 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", dompath), "%"PRIu32, target_memkb);
keir@21374 2715
keir@21374 2716 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
keir@21374 2717 if (rc != 1 || info.domain != domid)
keir@21374 2718 return rc;
keir@21374 2719 xcinfo2xlinfo(&info, &ptr);
keir@21374 2720 uuid = libxl_uuid2string(ctx, ptr.uuid);
Ian@21844 2721 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "/vm/%s/memory", uuid), "%"PRIu32, target_memkb / 1024);
keir@21374 2722
keir@21422 2723 if (enforce || !domid)
keir@21422 2724 memorykb = target_memkb;
keir@21422 2725 rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb + LIBXL_MAXMEM_CONSTANT);
keir@21422 2726 if (rc != 0)
keir@21422 2727 return rc;
keir@20647 2728 rc = xc_domain_memory_set_pod_target(ctx->xch, domid, (target_memkb - videoram) / 4, NULL, NULL, NULL);
keir@20647 2729 return rc;
keir@20647 2730 }
keir@20875 2731
keir@20875 2732 int libxl_button_press(struct libxl_ctx *ctx, uint32_t domid, libxl_button button)
keir@20875 2733 {
keir@20875 2734 int rc = -1;
keir@20875 2735
keir@20875 2736 switch (button) {
keir@20875 2737 case POWER_BUTTON:
keir@20875 2738 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_POWER, 0);
keir@20875 2739 break;
keir@20875 2740 case SLEEP_BUTTON:
keir@20875 2741 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_SLEEP, 0);
keir@20875 2742 break;
keir@20875 2743 default:
keir@20875 2744 break;
keir@20875 2745 }
keir@20875 2746
keir@20875 2747 return rc;
keir@20875 2748 }
keir@21141 2749
keir@21141 2750 int libxl_get_physinfo(struct libxl_ctx *ctx, struct libxl_physinfo *physinfo)
keir@21141 2751 {
keir@21141 2752 xc_physinfo_t xcphysinfo = { 0 };
keir@21141 2753 int rc;
keir@21141 2754
keir@21141 2755 rc = xc_physinfo(ctx->xch, &xcphysinfo);
keir@21141 2756 if (rc != 0) {
keir@21141 2757 return rc;
keir@21141 2758 }
keir@21141 2759 physinfo->threads_per_core = xcphysinfo.threads_per_core;
keir@21141 2760 physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
keir@21142 2761 physinfo->max_cpu_id = xcphysinfo.max_cpu_id;
keir@21141 2762 physinfo->nr_cpus = xcphysinfo.nr_cpus;
keir@21141 2763 physinfo->cpu_khz = xcphysinfo.cpu_khz;
keir@21141 2764 physinfo->total_pages = xcphysinfo.total_pages;
keir@21141 2765 physinfo->free_pages = xcphysinfo.free_pages;
keir@21141 2766 physinfo->scrub_pages = xcphysinfo.scrub_pages;
keir@21264 2767 physinfo->nr_nodes = xcphysinfo.nr_nodes;
keir@21264 2768 memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap));
keir@21264 2769 physinfo->phys_cap = xcphysinfo.capabilities;
keir@21264 2770
keir@21141 2771 return 0;
keir@21141 2772 }
keir@21141 2773
keir@21266 2774 const libxl_version_info* libxl_get_version_info(struct libxl_ctx *ctx)
keir@21266 2775 {
keir@21266 2776 union {
keir@21266 2777 xen_extraversion_t xen_extra;
keir@21266 2778 xen_compile_info_t xen_cc;
keir@21266 2779 xen_changeset_info_t xen_chgset;
keir@21266 2780 xen_capabilities_info_t xen_caps;
keir@21266 2781 xen_platform_parameters_t p_parms;
keir@21266 2782 xen_commandline_t xen_commandline;
keir@21266 2783 } u;
keir@21266 2784 long xen_version;
keir@21266 2785 libxl_version_info *info = &ctx->version_info;
keir@21266 2786
keir@21266 2787 if (info->xen_version_extra != NULL)
keir@21266 2788 return info;
keir@21266 2789
keir@21266 2790 xen_version = xc_version(ctx->xch, XENVER_version, NULL);
keir@21266 2791 info->xen_version_major = xen_version >> 16;
keir@21266 2792 info->xen_version_minor = xen_version & 0xFF;
keir@21266 2793 xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra);
Ian@21845 2794 info->xen_version_extra = libxl_strdup(ctx, u.xen_extra);
keir@21266 2795
keir@21266 2796 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
Ian@21845 2797 info->compiler = libxl_strdup(ctx, u.xen_cc.compiler);
Ian@21845 2798 info->compile_by = libxl_strdup(ctx, u.xen_cc.compile_by);
Ian@21845 2799 info->compile_domain = libxl_strdup(ctx, u.xen_cc.compile_domain);
Ian@21845 2800 info->compile_date = libxl_strdup(ctx, u.xen_cc.compile_date);
keir@21266 2801
keir@21266 2802 xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps);
Ian@21845 2803 info->capabilities = libxl_strdup(ctx, u.xen_caps);
keir@21266 2804
keir@21266 2805 xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset);
Ian@21845 2806 info->changeset = libxl_strdup(ctx, u.xen_chgset);
keir@21266 2807
keir@21266 2808 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
keir@21266 2809 info->virt_start = u.p_parms.virt_start;
keir@21266 2810
keir@21266 2811 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
keir@21266 2812
keir@21266 2813 xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline);
Ian@21845 2814 info->commandline = libxl_strdup(ctx, u.xen_commandline);
keir@21266 2815
keir@21266 2816 return info;
keir@21266 2817 }
keir@21266 2818
keir@21141 2819 struct libxl_vcpuinfo *libxl_list_vcpu(struct libxl_ctx *ctx, uint32_t domid,
keir@21141 2820 int *nb_vcpu, int *cpusize)
keir@21141 2821 {
keir@21141 2822 struct libxl_vcpuinfo *ptr, *ret;
keir@21141 2823 xc_domaininfo_t domaininfo;
keir@21141 2824 xc_vcpuinfo_t vcpuinfo;
keir@21141 2825 xc_physinfo_t physinfo = { 0 };
keir@21141 2826
keir@21141 2827 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
keir@21141 2828 return NULL;
keir@21141 2829 }
keir@21141 2830 if (xc_physinfo(ctx->xch, &physinfo) == -1) {
keir@21141 2831 return NULL;
keir@21141 2832 }
keir@21141 2833 *cpusize = physinfo.max_cpu_id + 1;
keir@21141 2834 ptr = libxl_calloc(ctx, domaininfo.max_vcpu_id + 1, sizeof (struct libxl_vcpuinfo));
keir@21141 2835 if (!ptr) {
keir@21141 2836 return NULL;
keir@21141 2837 }
keir@21141 2838
keir@21141 2839 ret = ptr;
keir@21141 2840 for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) {
keir@21141 2841 ptr->cpumap = libxl_calloc(ctx, (*cpusize + 63) / 64, sizeof (uint64_t));
keir@21141 2842 if (!ptr->cpumap) {
keir@21141 2843 return NULL;
keir@21141 2844 }
keir@21141 2845 if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) {
keir@21141 2846 return NULL;
keir@21141 2847 }
keir@21141 2848 if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu, ptr->cpumap, *cpusize) == -1) {
keir@21141 2849 return NULL;
keir@21141 2850 }
keir@21141 2851 ptr->vcpuid = *nb_vcpu;
keir@21141 2852 ptr->cpu = vcpuinfo.cpu;
keir@21141 2853 ptr->online = !!vcpuinfo.online;
keir@21141 2854 ptr->blocked = !!vcpuinfo.blocked;
keir@21141 2855 ptr->running = !!vcpuinfo.running;
keir@21141 2856 ptr->vcpu_time = vcpuinfo.cpu_time;
keir@21141 2857 }
keir@21141 2858 return ret;
keir@21141 2859 }
keir@21142 2860
keir@21142 2861 int libxl_set_vcpuaffinity(struct libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
keir@21142 2862 uint64_t *cpumap, int cpusize)
keir@21142 2863 {
keir@21142 2864 return (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap, cpusize));
keir@21142 2865 }
keir@21143 2866
keir@21143 2867 int libxl_set_vcpucount(struct libxl_ctx *ctx, uint32_t domid, uint32_t count)
keir@21143 2868 {
keir@21143 2869 xc_domaininfo_t domaininfo;
keir@21143 2870 char *dompath;
keir@21143 2871 int i;
keir@21143 2872
keir@21143 2873 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
keir@21143 2874 return ERROR_FAIL;
keir@21143 2875 }
keir@21143 2876 if (!count || ((domaininfo.max_vcpu_id + 1) < count)) {
keir@21143 2877 return ERROR_INVAL;
keir@21143 2878 }
keir@21143 2879 if (!(dompath = libxl_xs_get_dompath(ctx, domid)))
keir@21143 2880 return ERROR_FAIL;
keir@21143 2881
keir@21143 2882 for (i = 0; i <= domaininfo.max_vcpu_id; ++i) {
keir@21143 2883 libxl_xs_write(ctx, XBT_NULL,
keir@21143 2884 libxl_sprintf(ctx, "%s/cpu/%u/availability", dompath, i),
keir@21143 2885 "%s", ((1 << i) & ((1 << count) - 1)) ? "online" : "offline");
keir@21143 2886 }
keir@21143 2887 return 0;
keir@21143 2888 }
keir@21265 2889
keir@21265 2890 /*
keir@21265 2891 * returns one of the XEN_SCHEDULER_* constants from public/domctl.h
keir@21265 2892 * or -1 if an error occured.
keir@21265 2893 */
keir@21265 2894 int libxl_get_sched_id(struct libxl_ctx *ctx)
keir@21265 2895 {
keir@21265 2896 int sched, ret;
keir@21265 2897
keir@21265 2898 if ((ret = xc_sched_id(ctx->xch, &sched)) != 0)
keir@21265 2899 return ret;
keir@21265 2900 return sched;
keir@21265 2901 }
keir@21292 2902
keir@21292 2903 int libxl_sched_credit_domain_get(struct libxl_ctx *ctx, uint32_t domid, struct libxl_sched_credit *scinfo)
keir@21292 2904 {
keir@21292 2905 struct xen_domctl_sched_credit sdom;
keir@21292 2906 int rc;
keir@21292 2907
keir@21292 2908 rc = xc_sched_credit_domain_get(ctx->xch, domid, &sdom);
keir@21292 2909 if (rc != 0)
keir@21292 2910 return rc;
keir@21292 2911
keir@21292 2912 scinfo->weight = sdom.weight;
keir@21292 2913 scinfo->cap = sdom.cap;
keir@21292 2914
keir@21292 2915 return 0;
keir@21292 2916 }
keir@21292 2917
keir@21292 2918 int libxl_sched_credit_domain_set(struct libxl_ctx *ctx, uint32_t domid, struct libxl_sched_credit *scinfo)
keir@21292 2919 {
keir@21292 2920 struct xen_domctl_sched_credit sdom;
keir@21292 2921 xc_domaininfo_t domaininfo;
keir@21292 2922 int rc;
keir@21292 2923
keir@21292 2924 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo);
keir@21292 2925 if (rc != 1 || domaininfo.domain != domid)
keir@21292 2926 return rc;
keir@21292 2927
keir@21292 2928
keir@21292 2929 if (scinfo->weight < 1 || scinfo->weight > 65535) {
keir@21292 2930 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21292 2931 "Cpu weight out of range, valid values are within range from 1 to 65535");
keir@21292 2932 return -1;
keir@21292 2933 }
keir@21292 2934
keir@21292 2935 if (scinfo->cap < 0 || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) {
keir@21292 2936 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21292 2937 "Cpu cap out of range, valid range is from 0 to %d for specified number of vcpus",
keir@21292 2938 ((domaininfo.max_vcpu_id + 1) * 100));
keir@21292 2939 return -1;
keir@21292 2940 }
keir@21292 2941
keir@21292 2942 sdom.weight = scinfo->weight;
keir@21292 2943 sdom.cap = scinfo->cap;
keir@21292 2944
keir@21292 2945 rc = xc_sched_credit_domain_set(ctx->xch, domid, &sdom);
keir@21292 2946 if (rc != 0)
keir@21292 2947 return rc;
keir@21292 2948
keir@21292 2949 return 0;
keir@21292 2950 }
keir@21292 2951
keir@21393 2952 static int trigger_type_from_string(char *trigger_name)
keir@21393 2953 {
keir@21393 2954 if (!strcmp(trigger_name, "nmi"))
keir@21393 2955 return XEN_DOMCTL_SENDTRIGGER_NMI;
keir@21393 2956 else if (!strcmp(trigger_name, "reset"))
keir@21393 2957 return XEN_DOMCTL_SENDTRIGGER_RESET;
keir@21393 2958 else if (!strcmp(trigger_name, "init"))
keir@21393 2959 return XEN_DOMCTL_SENDTRIGGER_INIT;
keir@21393 2960 else if (!strcmp(trigger_name, "power"))
keir@21393 2961 return XEN_DOMCTL_SENDTRIGGER_POWER;
keir@21393 2962 else if (!strcmp(trigger_name, "sleep"))
keir@21393 2963 return XEN_DOMCTL_SENDTRIGGER_SLEEP;
keir@21393 2964 else
keir@21393 2965 return -1;
keir@21393 2966 }
keir@21393 2967
keir@21393 2968 int libxl_send_trigger(struct libxl_ctx *ctx, uint32_t domid, char *trigger_name, uint32_t vcpuid)
keir@21393 2969 {
keir@21393 2970 int rc = -1;
keir@21393 2971 int trigger_type = trigger_type_from_string(trigger_name);
keir@21393 2972
keir@21393 2973 if (trigger_type == -1) {
keir@21393 2974 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21393 2975 "Invalid trigger, valid triggers are <nmi|reset|init|power|sleep>");
keir@21393 2976 return -1;
keir@21393 2977 }
keir@21393 2978
keir@21393 2979 rc = xc_domain_send_trigger(ctx->xch, domid, trigger_type, vcpuid);
keir@21393 2980 if (rc != 0)
keir@21393 2981 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21393 2982 "Send trigger '%s' failed", trigger_name);
keir@21393 2983
keir@21393 2984 return rc;
keir@21393 2985 }
keir@21402 2986
keir@21402 2987 int libxl_send_sysrq(struct libxl_ctx *ctx, uint32_t domid, char sysrq)
keir@21402 2988 {
keir@21402 2989 char *dompath = libxl_xs_get_dompath(ctx, domid);
keir@21402 2990
keir@21402 2991 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/control/sysrq", dompath), "%c", sysrq);
keir@21402 2992
keir@21402 2993 return 0;
keir@21402 2994 }
keir@21402 2995
keir@21472 2996 int libxl_send_debug_keys(struct libxl_ctx *ctx, char *keys)
keir@21472 2997 {
keir@21472 2998 return xc_send_debug_keys(ctx->xch, keys);
keir@21472 2999 }
keir@21472 3000
keir@21496 3001 struct libxl_xen_console_reader *
keir@21496 3002 libxl_xen_console_read_start(struct libxl_ctx *ctx, int clear)
keir@21496 3003 {
keir@21496 3004 struct libxl_xen_console_reader *cr;
keir@21496 3005 unsigned int size = 16384;
keir@21496 3006 char *buf = malloc(size);
keir@21496 3007
keir@21496 3008 if (!buf) {
keir@21496 3009 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc buffer for libxl_xen_console_reader,"
keir@21496 3010 " size is %u", size);
keir@21496 3011 return NULL;
keir@21496 3012 }
keir@21496 3013
keir@21496 3014 cr = malloc(sizeof(struct libxl_xen_console_reader));
keir@21496 3015 if (!cr) {
keir@21496 3016 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc libxl_xen_console_reader");
keir@21496 3017 return NULL;
keir@21496 3018 }
keir@21496 3019
keir@21496 3020 memset(cr, 0, sizeof(struct libxl_xen_console_reader));
keir@21496 3021 cr->buffer = buf;
keir@21496 3022 cr->size = size;
keir@21496 3023 cr->count = size;
keir@21496 3024 cr->clear = clear;
keir@21496 3025 cr->incremental = 1;
keir@21496 3026
keir@21496 3027 return cr;
keir@21496 3028 }
keir@21496 3029
keir@21496 3030 /* return values: *line_r
keir@21496 3031 * 1 success, whole line obtained from buffer non-0
keir@21496 3032 * 0 no more lines available right now 0
keir@21496 3033 * negative error code ERROR_* 0
keir@21496 3034 * On success *line_r is updated to point to a nul-terminated
keir@21496 3035 * string which is valid until the next call on the same console
keir@21496 3036 * reader. The libxl caller may overwrite parts of the string
keir@21496 3037 * if it wishes. */
keir@21496 3038 int libxl_xen_console_read_line(struct libxl_ctx *ctx,
keir@21496 3039 struct libxl_xen_console_reader *cr,
keir@21496 3040 char **line_r)
keir@21496 3041 {
keir@21496 3042 int ret;
keir@21496 3043
keir@21496 3044 memset(cr->buffer, 0, cr->size);
keir@21496 3045 ret = xc_readconsolering(ctx->xch, &cr->buffer, &cr->count,
keir@21496 3046 cr->clear, cr->incremental, &cr->index);
keir@21496 3047 if (!ret) {
keir@21496 3048 if (cr->count) {
keir@21496 3049 *line_r = cr->buffer;
keir@21496 3050 ret = 1;
keir@21496 3051 } else {
keir@21496 3052 *line_r = NULL;
keir@21496 3053 ret = 0;
keir@21496 3054 }
keir@21496 3055 }
keir@21496 3056
keir@21496 3057 return ret;
keir@21496 3058 }
keir@21496 3059
keir@21496 3060 void libxl_xen_console_read_finish(struct libxl_ctx *ctx,
keir@21496 3061 struct libxl_xen_console_reader *cr)
keir@21496 3062 {
keir@21496 3063 free(cr->buffer);
keir@21496 3064 free(cr);
keir@21496 3065 }
keir@21496 3066
keir@21425 3067 uint32_t libxl_vm_get_start_time(struct libxl_ctx *ctx, uint32_t domid)
keir@21425 3068 {
keir@21425 3069 char *dompath = libxl_xs_get_dompath(ctx, domid);
keir@21425 3070 char *vm_path, *start_time;
keir@21425 3071
keir@21425 3072 vm_path = libxl_xs_read(
keir@21425 3073 ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vm", dompath));
keir@21425 3074 start_time = libxl_xs_read(
keir@21425 3075 ctx, XBT_NULL, libxl_sprintf(ctx, "%s/start_time", vm_path));
keir@21425 3076 if (start_time == NULL) {
keir@21425 3077 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21425 3078 "Can't get start time of domain '%d'", domid);
keir@21425 3079 return -1;
keir@21425 3080 }
keir@21425 3081
keir@21425 3082 return strtoul(start_time, NULL, 10);
keir@21425 3083 }
keir@21425 3084
keir@21471 3085 char *libxl_tmem_list(struct libxl_ctx *ctx, uint32_t domid, int use_long)
keir@21471 3086 {
keir@21471 3087 int rc;
keir@21471 3088 char _buf[32768];
keir@21471 3089
keir@21471 3090 rc = xc_tmem_control(ctx->xch, -1, TMEMC_LIST, domid, 32768, use_long,
keir@21471 3091 0, _buf);
keir@21471 3092 if (rc < 0) {
keir@21471 3093 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3094 "Can not get tmem list");
keir@21471 3095 return NULL;
keir@21471 3096 }
keir@21471 3097
keir@21471 3098 return strdup(_buf);
keir@21471 3099 }
keir@21471 3100
keir@21471 3101 int libxl_tmem_freeze(struct libxl_ctx *ctx, uint32_t domid)
keir@21471 3102 {
keir@21471 3103 int rc;
keir@21471 3104
keir@21471 3105 rc = xc_tmem_control(ctx->xch, -1, TMEMC_FREEZE, domid, 0, 0,
keir@21471 3106 0, NULL);
keir@21471 3107 if (rc < 0) {
keir@21471 3108 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3109 "Can not freeze tmem pools");
keir@21471 3110 return -1;
keir@21471 3111 }
keir@21471 3112
keir@21471 3113 return rc;
keir@21471 3114 }
keir@21471 3115
keir@21471 3116 int libxl_tmem_destroy(struct libxl_ctx *ctx, uint32_t domid)
keir@21471 3117 {
keir@21471 3118 int rc;
keir@21471 3119
keir@21471 3120 rc = xc_tmem_control(ctx->xch, -1, TMEMC_DESTROY, domid, 0, 0,
keir@21471 3121 0, NULL);
keir@21471 3122 if (rc < 0) {
keir@21471 3123 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3124 "Can not destroy tmem pools");
keir@21471 3125 return -1;
keir@21471 3126 }
keir@21471 3127
keir@21471 3128 return rc;
keir@21471 3129 }
keir@21471 3130
keir@21471 3131 int libxl_tmem_thaw(struct libxl_ctx *ctx, uint32_t domid)
keir@21471 3132 {
keir@21471 3133 int rc;
keir@21471 3134
keir@21471 3135 rc = xc_tmem_control(ctx->xch, -1, TMEMC_THAW, domid, 0, 0,
keir@21471 3136 0, NULL);
keir@21471 3137 if (rc < 0) {
keir@21471 3138 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3139 "Can not thaw tmem pools");
keir@21471 3140 return -1;
keir@21471 3141 }
keir@21471 3142
keir@21471 3143 return rc;
keir@21471 3144 }
keir@21471 3145
keir@21471 3146 static int32_t tmem_setop_from_string(char *set_name)
keir@21471 3147 {
keir@21471 3148 if (!strcmp(set_name, "weight"))
keir@21471 3149 return TMEMC_SET_WEIGHT;
keir@21471 3150 else if (!strcmp(set_name, "cap"))
keir@21471 3151 return TMEMC_SET_CAP;
keir@21471 3152 else if (!strcmp(set_name, "compress"))
keir@21471 3153 return TMEMC_SET_COMPRESS;
keir@21471 3154 else
keir@21471 3155 return -1;
keir@21471 3156 }
keir@21471 3157
keir@21471 3158 int libxl_tmem_set(struct libxl_ctx *ctx, uint32_t domid, char* name, uint32_t set)
keir@21471 3159 {
keir@21471 3160 int rc;
keir@21471 3161 int32_t subop = tmem_setop_from_string(name);
keir@21471 3162
keir@21471 3163 if (subop == -1) {
keir@21471 3164 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21471 3165 "Invalid set, valid sets are <weight|cap|compress>");
keir@21471 3166 return -1;
keir@21471 3167 }
keir@21471 3168 rc = xc_tmem_control(ctx->xch, -1, subop, domid, set, 0, 0, NULL);
keir@21471 3169 if (rc < 0) {
keir@21471 3170 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3171 "Can not set tmem %s", name);
keir@21471 3172 return -1;
keir@21471 3173 }
keir@21471 3174
keir@21471 3175 return rc;
keir@21471 3176 }
keir@21471 3177
keir@21471 3178 int libxl_tmem_shared_auth(struct libxl_ctx *ctx, uint32_t domid,
keir@21471 3179 char* uuid, int auth)
keir@21471 3180 {
keir@21471 3181 int rc;
keir@21471 3182
keir@21471 3183 rc = xc_tmem_auth(ctx->xch, domid, uuid, auth);
keir@21471 3184 if (rc < 0) {
keir@21471 3185 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3186 "Can not set tmem shared auth");
keir@21471 3187 return -1;
keir@21471 3188 }
keir@21471 3189
keir@21471 3190 return rc;
keir@21471 3191 }
keir@21471 3192
Ian@21848 3193 int libxl_file_reference_map(struct libxl_ctx *ctx, libxl_file_reference *f)
Ian@21848 3194 {
Ian@21848 3195 struct stat st_buf;
Ian@21848 3196 int ret, fd;
Ian@21848 3197 void *data;
Ian@21848 3198
Ian@21848 3199 if (f->mapped)
Ian@21848 3200 return 0;
Ian@21848 3201
Ian@21848 3202 fd = open(f->path, O_RDONLY);
Ian@21848 3203 if (f < 0)
Ian@21848 3204 return ERROR_FAIL;
Ian@21848 3205
Ian@21848 3206 ret = fstat(fd, &st_buf);
Ian@21848 3207 if (ret < 0)
Ian@21848 3208 goto out;
Ian@21848 3209
Ian@21848 3210 ret = -1;
Ian@21848 3211 data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
Ian@21848 3212 if (data == NULL)
Ian@21848 3213 goto out;
Ian@21848 3214
Ian@21848 3215 f->mapped = 1;
Ian@21848 3216 f->data = data;
Ian@21848 3217 f->size = st_buf.st_size;
Ian@21848 3218
Ian@21848 3219 ret = 0;
Ian@21848 3220 out:
Ian@21848 3221 close(fd);
Ian@21848 3222
Ian@21848 3223 return ret == 0 ? 0 : ERROR_FAIL;
Ian@21848 3224 }
Ian@21848 3225
Ian@21848 3226 int libxl_file_reference_unmap(struct libxl_ctx *ctx, libxl_file_reference *f)
Ian@21848 3227 {
Ian@21848 3228 int ret;
Ian@21848 3229
Ian@21848 3230 if (!f->mapped)
Ian@21848 3231 return 0;
Ian@21848 3232
Ian@21848 3233 ret = munmap(f->data, f->size);
Ian@21848 3234
Ian@21848 3235 return ret == 0 ? 0 : ERROR_FAIL;
Ian@21848 3236 }