debuggers.hg

annotate tools/libxl/libxl.c @ 20785:d4613b521798

libxl: remove API for dominfolist and list that returns xc_dominfo.

fixup xl and part of libxl that use those API, to use simpler, faster
and less wasteful API (doesn't need to get the info about all domains
when looking for one specific domain).

Signed-off-by: Vincent Hanquez <vincent.hanquez@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Dec 30 12:45:13 2009 +0000 (2009-12-30)
parents 49d0c3ff7943
children a4aace0808d2
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>
keir@20514 25 #include <sys/wait.h>
keir@20462 26 #include <signal.h>
keir@20468 27 #include <unistd.h> /* for write, unlink and close */
keir@20509 28 #include <stdint.h>
keir@20509 29 #include <inttypes.h>
keir@20514 30 #include <assert.h>
keir@20513 31
keir@20462 32 #include "libxl.h"
keir@20462 33 #include "libxl_utils.h"
keir@20462 34 #include "libxl_internal.h"
keir@20462 35 #include "flexarray.h"
keir@20462 36
keir@20462 37 int libxl_ctx_init(struct libxl_ctx *ctx)
keir@20462 38 {
keir@20462 39 memset(ctx, 0, sizeof(struct libxl_ctx));
keir@20462 40 ctx->alloc_maxsize = 256;
keir@20462 41 ctx->alloc_ptrs = calloc(ctx->alloc_maxsize, sizeof(void *));
keir@20462 42 if (!ctx->alloc_ptrs)
keir@20462 43 return ERROR_NOMEM;
keir@20462 44
keir@20462 45 ctx->xch = xc_interface_open();
keir@20462 46 ctx->xsh = xs_daemon_open();
keir@20462 47 return 0;
keir@20462 48 }
keir@20462 49
keir@20462 50 int libxl_ctx_free(struct libxl_ctx *ctx)
keir@20462 51 {
keir@20462 52 libxl_free_all(ctx);
keir@20462 53 free(ctx->alloc_ptrs);
keir@20462 54 xc_interface_close(ctx->xch);
keir@20545 55 xs_daemon_close(ctx->xsh);
keir@20462 56 return 0;
keir@20462 57 }
keir@20462 58
keir@20462 59 int libxl_ctx_set_log(struct libxl_ctx *ctx, libxl_log_callback log_callback, void *log_data)
keir@20462 60 {
keir@20462 61 ctx->log_callback = log_callback;
keir@20462 62 ctx->log_userdata = log_data;
keir@20462 63 return 0;
keir@20462 64 }
keir@20462 65
keir@20462 66 /******************************************************************************/
keir@20462 67
keir@20462 68 int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info,
keir@20462 69 uint32_t *domid)
keir@20462 70 {
keir@20462 71 int flags, ret, i;
keir@20468 72 char *uuid_string;
keir@20646 73 char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"};
keir@20462 74 char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
keir@20646 75 "control", "attr", "messages" };
keir@20462 76 char *dom_path, *vm_path, *vss_path;
keir@20462 77 struct xs_permissions roperm[2];
keir@20462 78 struct xs_permissions rwperm[1];
keir@20462 79 xs_transaction_t t;
keir@20468 80 xen_domain_handle_t handle;
keir@20462 81
keir@20468 82 uuid_string = libxl_uuid_to_string(ctx, info->uuid);
keir@20462 83 if (!uuid_string) {
keir@20462 84 XL_LOG(ctx, XL_LOG_ERROR, "missing uuid");
keir@20462 85 return ERROR_FAIL;
keir@20462 86 }
keir@20462 87
keir@20462 88 flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
keir@20462 89 flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
keir@20462 90 *domid = 0;
keir@20462 91
keir@20580 92 /*
keir@20468 93 * info->uuid != xen_domain_handle_t
keir@20468 94 * See:
keir@20468 95 * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
keir@20468 96 * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
keir@20468 97 *
keir@20468 98 * A DCE 1.1 compatible source representation of UUIDs.
keir@20468 99 *
keir@20468 100 * struct uuid {
keir@20468 101 * uint32_t time_low;
keir@20468 102 * uint16_t time_mid;
keir@20468 103 * uint16_t time_hi_and_version;
keir@20468 104 * uint8_t clock_seq_hi_and_reserved;
keir@20468 105 * uint8_t clock_seq_low;
keir@20468 106 * uint8_t node[_UUID_NODE_LEN];
keir@20468 107 * };
keir@20468 108 */
keir@20580 109 /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
keir@20580 110 memcpy(handle, info->uuid, sizeof(xen_domain_handle_t));
keir@20468 111
keir@20468 112 ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
keir@20462 113 if (ret < 0) {
keir@20512 114 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain creation fail");
keir@20462 115 return ERROR_FAIL;
keir@20462 116 }
keir@20462 117
keir@20462 118 dom_path = libxl_xs_get_dompath(ctx, *domid);
keir@20512 119 if (!dom_path)
keir@20512 120 return ERROR_FAIL;
keir@20512 121
keir@20462 122 vm_path = libxl_sprintf(ctx, "/vm/%s", uuid_string);
keir@20462 123 vss_path = libxl_sprintf(ctx, "/vss/%s", uuid_string);
keir@20512 124 if (!vm_path || !vss_path) {
keir@20462 125 XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate create paths");
keir@20462 126 return ERROR_FAIL;
keir@20462 127 }
keir@20462 128
keir@20462 129 roperm[0].id = 0;
keir@20462 130 roperm[0].perms = XS_PERM_NONE;
keir@20462 131 roperm[1].id = *domid;
keir@20462 132 roperm[1].perms = XS_PERM_READ;
keir@20462 133 rwperm[0].id = *domid;
keir@20462 134 rwperm[0].perms = XS_PERM_NONE;
keir@20462 135
keir@20462 136 retry_transaction:
keir@20462 137 t = xs_transaction_start(ctx->xsh);
keir@20462 138 xs_rm(ctx->xsh, t, dom_path);
keir@20462 139 xs_mkdir(ctx->xsh, t, dom_path);
keir@20462 140 xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm));
keir@20462 141
keir@20462 142 xs_rm(ctx->xsh, t, vm_path);
keir@20462 143 xs_mkdir(ctx->xsh, t, vm_path);
keir@20462 144 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
keir@20462 145
keir@20462 146 xs_rm(ctx->xsh, t, vss_path);
keir@20462 147 xs_mkdir(ctx->xsh, t, vss_path);
keir@20462 148 xs_set_permissions(ctx->xsh, t, vss_path, rwperm, ARRAY_SIZE(rwperm));
keir@20462 149
keir@20462 150 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vm", dom_path), vm_path, strlen(vm_path));
keir@20462 151 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vss", dom_path), vss_path, strlen(vss_path));
keir@20462 152 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", dom_path), info->name, strlen(info->name));
keir@20462 153
keir@20462 154 for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
keir@20462 155 char *path = libxl_sprintf(ctx, "%s/%s", dom_path, rw_paths[i]);
keir@20462 156 xs_mkdir(ctx->xsh, t, path);
keir@20462 157 xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm));
keir@20462 158 libxl_free(ctx, path);
keir@20462 159 }
keir@20462 160 for (i = 0; i < ARRAY_SIZE(ro_paths); i++) {
keir@20462 161 char *path = libxl_sprintf(ctx, "%s/%s", dom_path, ro_paths[i]);
keir@20462 162 xs_mkdir(ctx->xsh, t, path);
keir@20462 163 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
keir@20462 164 libxl_free(ctx, path);
keir@20462 165 }
keir@20462 166
keir@20462 167 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
keir@20462 168 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", vm_path), info->name, strlen(info->name));
keir@20462 169
keir@20462 170 libxl_xs_writev(ctx, t, dom_path, info->xsdata);
keir@20462 171 libxl_xs_writev(ctx, t, libxl_sprintf(ctx, "%s/platform", dom_path), info->platformdata);
keir@20462 172
keir@20462 173 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
keir@20462 174
keir@20462 175 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20462 176 if (errno == EAGAIN)
keir@20462 177 goto retry_transaction;
keir@20462 178 return 0;
keir@20462 179 }
keir@20462 180
keir@20516 181 int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, libxl_domain_build_state *state)
keir@20462 182 {
keir@20462 183 char **vments = NULL, **localents = NULL;
keir@20578 184 int i;
keir@20462 185
keir@20509 186 build_pre(ctx, domid, info, state);
keir@20462 187 if (info->hvm) {
keir@20509 188 build_hvm(ctx, domid, info, state);
keir@20509 189 vments = libxl_calloc(ctx, 5, sizeof(char *));
keir@20516 190 vments[0] = "rtc/timeoffset";
keir@20516 191 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
keir@20516 192 vments[2] = "image/ostype";
keir@20516 193 vments[3] = "hvm";
keir@20462 194 } else {
keir@20509 195 build_pv(ctx, domid, info, state);
keir@20509 196 vments = libxl_calloc(ctx, 9, sizeof(char *));
keir@20578 197 i = 0;
keir@20578 198 vments[i++] = "image/ostype";
keir@20578 199 vments[i++] = "linux";
keir@20578 200 vments[i++] = "image/kernel";
keir@20578 201 vments[i++] = (char*) info->kernel;
keir@20578 202 if (info->u.pv.ramdisk) {
keir@20578 203 vments[i++] = "image/ramdisk";
keir@20578 204 vments[i++] = (char*) info->u.pv.ramdisk;
keir@20578 205 }
keir@20578 206 if (info->u.pv.cmdline) {
keir@20578 207 vments[i++] = "image/cmdline";
keir@20578 208 vments[i++] = (char*) info->u.pv.cmdline;
keir@20578 209 }
keir@20462 210 }
keir@20509 211 build_post(ctx, domid, info, state, vments, localents);
keir@20516 212 return 0;
keir@20462 213 }
keir@20462 214
keir@20462 215 int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info,
keir@20565 216 uint32_t domid, int fd, libxl_domain_build_state *state,
keir@20565 217 libxl_device_model_info *dm_info)
keir@20462 218 {
keir@20462 219 char **vments = NULL, **localents = NULL;
keir@20627 220 int i;
keir@20462 221
keir@20565 222 build_pre(ctx, domid, info, state);
keir@20565 223 restore_common(ctx, domid, info, state, fd);
keir@20462 224 if (info->hvm) {
keir@20565 225 vments = libxl_calloc(ctx, 5, sizeof(char *));
keir@20516 226 vments[0] = "rtc/timeoffset";
keir@20516 227 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
keir@20565 228 vments[2] = "image/ostype";
keir@20565 229 vments[3] = "hvm";
keir@20462 230 } else {
keir@20565 231 vments = libxl_calloc(ctx, 9, sizeof(char *));
keir@20627 232 i = 0;
keir@20627 233 vments[i++] = "image/ostype";
keir@20627 234 vments[i++] = "linux";
keir@20627 235 vments[i++] = "image/kernel";
keir@20627 236 vments[i++] = (char*) info->kernel;
keir@20627 237 if (info->u.pv.ramdisk) {
keir@20627 238 vments[i++] = "image/ramdisk";
keir@20627 239 vments[i++] = (char*) info->u.pv.ramdisk;
keir@20627 240 }
keir@20627 241 if (info->u.pv.cmdline) {
keir@20627 242 vments[i++] = "image/cmdline";
keir@20627 243 vments[i++] = (char*) info->u.pv.cmdline;
keir@20627 244 }
keir@20462 245 }
keir@20565 246 build_post(ctx, domid, info, state, vments, localents);
keir@20565 247 if (info->hvm)
keir@20565 248 asprintf(&(dm_info->saved_state), "/var/lib/xen/qemu-save.%d", domid);
keir@20565 249 else
keir@20565 250 dm_info->saved_state = NULL;
keir@20565 251
keir@20462 252 return 0;
keir@20462 253 }
keir@20462 254
keir@20629 255 int libxl_domain_resume(struct libxl_ctx *ctx, uint32_t domid)
keir@20629 256 {
keir@20629 257 if (is_hvm(ctx, domid)) {
keir@20629 258 XL_LOG(ctx, XL_LOG_DEBUG, "Called domain_resume on "
keir@20629 259 "non-cooperative hvm domain %u", domid);
keir@20629 260 return ERROR_NI;
keir@20629 261 }
keir@20629 262 if (xc_domain_resume(ctx->xch, domid, 1)) {
keir@20629 263 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@20629 264 "xc_domain_resume failed for domain %u",
keir@20629 265 domid);
keir@20629 266 return ERROR_FAIL;
keir@20629 267 }
keir@20629 268 if (!xs_resume_domain(ctx->xsh, domid)) {
keir@20629 269 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@20629 270 "xs_resume_domain failed for domain %u",
keir@20629 271 domid);
keir@20629 272 return ERROR_FAIL;
keir@20629 273 }
keir@20629 274 return 0;
keir@20629 275 }
keir@20629 276
keir@20462 277 struct libxl_dominfo * libxl_domain_list(struct libxl_ctx *ctx, int *nb_domain)
keir@20462 278 {
keir@20462 279 struct libxl_dominfo *ptr;
keir@20462 280 int index, i, ret, first_domain;
keir@20462 281 xc_domaininfo_t info[16];
keir@20462 282 int size = 16;
keir@20462 283
keir@20462 284 first_domain = 1;
keir@20462 285 index = 0;
keir@20516 286 ptr = calloc(size, sizeof(struct libxl_dominfo));
keir@20462 287 if (!ptr)
keir@20462 288 return NULL;
keir@20462 289 redo:
keir@20462 290 ret = xc_domain_getinfolist(ctx->xch, first_domain, 16, info);
keir@20462 291 for (i = 0; i < ret; i++) {
keir@20462 292 if (index == size) {
keir@20462 293 struct libxl_dominfo *ptr2;
keir@20462 294
keir@20516 295 ptr2 = calloc(size * 2, sizeof(struct libxl_dominfo));
keir@20462 296 if (!ptr2) {
keir@20516 297 free(ptr);
keir@20462 298 return NULL;
keir@20462 299 }
keir@20462 300 memcpy(ptr2, ptr, sizeof(struct libxl_dominfo) * size);
keir@20516 301 free(ptr);
keir@20462 302 ptr = ptr2;
keir@20462 303 size *= 2;
keir@20462 304 }
keir@20579 305 memcpy(&(ptr[index].uuid), info[i].handle, sizeof(xen_domain_handle_t));
keir@20462 306 ptr[index].domid = info[i].domain;
keir@20784 307
keir@20784 308 if (info[i].flags & XEN_DOMINF_dying)
keir@20784 309 ptr[index].dying = 1;
keir@20784 310 else if (info[i].flags & XEN_DOMINF_paused)
keir@20784 311 ptr[index].paused = 1;
keir@20784 312 else if (info[i].flags & XEN_DOMINF_blocked || info[i].flags & XEN_DOMINF_running)
keir@20784 313 ptr[index].running = 1;
keir@20784 314
keir@20462 315 first_domain = info[i].domain + 1;
keir@20462 316 index++;
keir@20462 317 }
keir@20462 318 if (ret == 16)
keir@20462 319 goto redo;
keir@20462 320 *nb_domain = index;
keir@20462 321 return ptr;
keir@20462 322 }
keir@20462 323
keir@20462 324 int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info *info,
keir@20462 325 uint32_t domid, int fd)
keir@20462 326 {
keir@20565 327 int hvm = is_hvm(ctx, domid);
keir@20565 328 int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
keir@20565 329 int debug = info != NULL && info->flags & XL_SUSPEND_LIVE;
keir@20462 330
keir@20462 331 core_suspend(ctx, domid, fd, hvm, live, debug);
keir@20565 332 if (hvm)
keir@20779 333 save_device_model(ctx, domid, fd);
keir@20462 334 return 0;
keir@20462 335 }
keir@20462 336
keir@20462 337 int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 338 {
keir@20462 339 xc_domain_pause(ctx->xch, domid);
keir@20462 340 return 0;
keir@20462 341 }
keir@20462 342
keir@20462 343 int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 344 {
keir@20779 345 char *path;
keir@20565 346 char *state;
keir@20565 347
keir@20565 348 if (is_hvm(ctx, domid)) {
keir@20779 349 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20565 350 state = libxl_xs_read(ctx, XBT_NULL, path);
keir@20565 351 if (state != NULL && !strcmp(state, "paused")) {
keir@20565 352 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid), "continue", strlen("continue"));
keir@20565 353 libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL);
keir@20565 354 }
keir@20565 355 }
keir@20462 356 xc_domain_unpause(ctx->xch, domid);
keir@20565 357
keir@20462 358 return 0;
keir@20462 359 }
keir@20462 360
keir@20462 361 static char *req_table[] = {
keir@20462 362 [0] = "poweroff",
keir@20462 363 [1] = "reboot",
keir@20462 364 [2] = "suspend",
keir@20462 365 [3] = "crash",
keir@20462 366 [4] = "halt",
keir@20462 367 };
keir@20462 368
keir@20462 369 int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req)
keir@20462 370 {
keir@20462 371 char *shutdown_path;
keir@20462 372 char *dom_path;
keir@20462 373
keir@20462 374 if (req > ARRAY_SIZE(req_table))
keir@20462 375 return ERROR_INVAL;
keir@20462 376
keir@20462 377 dom_path = libxl_xs_get_dompath(ctx, domid);
keir@20512 378 if (!dom_path)
keir@20512 379 return ERROR_FAIL;
keir@20512 380
keir@20462 381 shutdown_path = libxl_sprintf(ctx, "%s/control/shutdown", dom_path);
keir@20462 382
keir@20462 383 xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], strlen(req_table[req]));
keir@20462 384 if (/* hvm */ 0) {
keir@20462 385 unsigned long acpi_s_state = 0;
keir@20462 386 unsigned long pvdriver = 0;
keir@20462 387 xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, &acpi_s_state);
keir@20462 388 xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
keir@20462 389 if (!pvdriver && acpi_s_state != 0)
keir@20462 390 xc_domain_shutdown(ctx->xch, domid, req);
keir@20462 391 }
keir@20462 392 return 0;
keir@20462 393 }
keir@20462 394
keir@20637 395 int libxl_get_wait_fd(struct libxl_ctx *ctx, int *fd)
keir@20545 396 {
keir@20545 397 *fd = xs_fileno(ctx->xsh);
keir@20545 398 return 0;
keir@20545 399 }
keir@20545 400
keir@20637 401 int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, libxl_waiter *waiter)
keir@20637 402 {
keir@20637 403 waiter->path = strdup("@releaseDomain");
keir@20637 404 asprintf(&(waiter->token), "%d", DOMAIN_DEATH);
keir@20637 405 if (!xs_watch(ctx->xsh, waiter->path, waiter->token))
keir@20637 406 return -1;
keir@20637 407 return 0;
keir@20637 408 }
keir@20637 409
keir@20637 410 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 411 {
keir@20637 412 int i;
keir@20637 413 uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
keir@20637 414
keir@20637 415 if (!domid)
keir@20637 416 domid = guest_domid;
keir@20637 417
keir@20637 418 for (i = 0; i < num_disks; i++) {
keir@20637 419 asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject", libxl_xs_get_dompath(ctx, domid), device_disk_dev_number(disks[i].virtpath));
keir@20637 420 asprintf(&(waiter[i].token), "%d", DISK_EJECT);
keir@20637 421 xs_watch(ctx->xsh, waiter->path, waiter->token);
keir@20637 422 }
keir@20637 423 return 0;
keir@20637 424 }
keir@20637 425
keir@20637 426 int libxl_get_event(struct libxl_ctx *ctx, libxl_event *event)
keir@20545 427 {
keir@20545 428 unsigned int num;
keir@20637 429 char **events = xs_read_watch(ctx->xsh, &num);
keir@20637 430 if (num != 2) {
keir@20637 431 free(events);
keir@20637 432 return -1;
keir@20637 433 }
keir@20637 434 event->path = strdup(events[XS_WATCH_PATH]);
keir@20637 435 event->token = strdup(events[XS_WATCH_TOKEN]);
keir@20637 436 event->type = atoi(event->token);
keir@20637 437 free(events);
keir@20637 438 return 0;
keir@20637 439 }
keir@20637 440
keir@20637 441 int libxl_stop_waiting(struct libxl_ctx *ctx, libxl_waiter *waiter)
keir@20637 442 {
keir@20637 443 if (!xs_unwatch(ctx->xsh, waiter->path, waiter->token))
keir@20637 444 return -1;
keir@20637 445 else
keir@20637 446 return 0;
keir@20637 447 }
keir@20637 448
keir@20637 449 int libxl_free_event(libxl_event *event)
keir@20637 450 {
keir@20637 451 free(event->path);
keir@20637 452 free(event->token);
keir@20637 453 return 0;
keir@20637 454 }
keir@20637 455
keir@20637 456 int libxl_free_waiter(libxl_waiter *waiter)
keir@20637 457 {
keir@20637 458 free(waiter->path);
keir@20637 459 free(waiter->token);
keir@20637 460 return 0;
keir@20637 461 }
keir@20637 462
keir@20785 463 int libxl_event_get_domain_death_info(struct libxl_ctx *ctx, uint32_t domid, libxl_event *event, xc_domaininfo_t *info)
keir@20637 464 {
keir@20785 465 int rc = 0, ret;
keir@20545 466
keir@20637 467 if (event && event->type == DOMAIN_DEATH) {
keir@20785 468 ret = xc_domain_getinfolist(ctx->xch, domid, 1, info);
keir@20785 469 if (ret == 1 && info->domain == domid) {
keir@20785 470 if (info->flags & XEN_DOMINF_running ||
keir@20785 471 (!(info->flags & XEN_DOMINF_shutdown) && !(info->flags & XEN_DOMINF_dying)))
keir@20545 472 goto out;
keir@20545 473 rc = 1;
keir@20545 474 goto out;
keir@20545 475 }
keir@20785 476 memset(info, 0, sizeof(xc_dominfo_t));
keir@20545 477 rc = 1;
keir@20545 478 goto out;
keir@20545 479 }
keir@20545 480 out:
keir@20545 481 return rc;
keir@20545 482 }
keir@20545 483
keir@20637 484 int libxl_event_get_disk_eject_info(struct libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_device_disk *disk)
keir@20637 485 {
keir@20637 486 if (event && event->type == DISK_EJECT) {
keir@20637 487 char *path;
keir@20637 488 char *backend;
keir@20637 489 char *value = libxl_xs_read(ctx, XBT_NULL, event->path);
keir@20637 490
keir@20637 491 if (!value || strcmp(value, "eject"))
keir@20637 492 return 0;
keir@20637 493
keir@20637 494 path = strdup(event->path);
keir@20637 495 path[strlen(path) - 6] = '\0';
keir@20637 496 backend = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend", path));
keir@20637 497
keir@20637 498 disk->backend_domid = 0;
keir@20637 499 disk->domid = domid;
keir@20637 500 disk->physpath = NULL;
keir@20637 501 disk->phystype = 0;
keir@20637 502 /* this value is returned to the user: do not free right away */
keir@20637 503 disk->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev", backend));
keir@20637 504 disk->unpluggable = 1;
keir@20637 505 disk->readwrite = 0;
keir@20637 506 disk->is_cdrom = 1;
keir@20637 507
keir@20637 508 free(path);
keir@20637 509 return 1;
keir@20637 510 }
keir@20637 511 return 0;
keir@20637 512 }
keir@20637 513
keir@20462 514 static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 515 {
keir@20462 516 char *pid;
keir@20462 517 int ret;
keir@20462 518
keir@20462 519 pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/image/device-model-pid", domid));
keir@20462 520 if (!pid) {
keir@20542 521 int stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20542 522 if (!stubdomid) {
keir@20542 523 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't find device model's pid");
keir@20542 524 return -1;
keir@20542 525 }
keir@20542 526 XL_LOG(ctx, XL_LOG_ERROR, "Device model is a stubdom, domid=%d\n", stubdomid);
keir@20542 527 return libxl_domain_destroy(ctx, stubdomid, 0);
keir@20462 528 }
keir@20462 529 xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", domid));
keir@20462 530
keir@20462 531 ret = kill(atoi(pid), SIGHUP);
keir@20462 532 if (ret < 0 && errno == ESRCH) {
keir@20512 533 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model already exited");
keir@20462 534 ret = 0;
keir@20462 535 } else if (ret == 0) {
keir@20512 536 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model signaled");
keir@20462 537 ret = 0;
keir@20462 538 } else {
keir@20512 539 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to kill Device Model [%d]",
keir@20512 540 atoi(pid));
keir@20462 541 }
keir@20462 542 return ret;
keir@20462 543 }
keir@20462 544
keir@20462 545 int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force)
keir@20462 546 {
keir@20581 547 char *dom_path, *uuid_str;
keir@20779 548 char *vm_path, *vss_path, *xapi_path;
keir@20468 549 xen_uuid_t *uuid;
keir@20628 550 int rc, dm_present;
keir@20628 551
keir@20628 552 if (is_hvm(ctx, domid)) {
keir@20628 553 dm_present = 1;
keir@20628 554 } else {
keir@20628 555 char *pid;
keir@20628 556 pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/image/device-model-pid", domid));
keir@20628 557 dm_present = (pid != NULL);
keir@20628 558 libxl_free(ctx, pid);
keir@20628 559 }
keir@20462 560
keir@20462 561 dom_path = libxl_xs_get_dompath(ctx, domid);
keir@20512 562 if (!dom_path)
keir@20462 563 return -1;
keir@20512 564
keir@20462 565 if (libxl_domid_to_uuid(ctx, &uuid, domid) < 0) {
keir@20512 566 XL_LOG(ctx, XL_LOG_ERROR, "failed ot get uuid for %d", domid);
keir@20462 567 return -1;
keir@20462 568 }
keir@20482 569 if (libxl_device_pci_shutdown(ctx, domid) < 0)
keir@20512 570 XL_LOG(ctx, XL_LOG_ERROR, "pci shutdown failed for domid %d", domid);
keir@20628 571 if (dm_present) {
keir@20628 572 xs_write(ctx->xsh, XBT_NULL,
keir@20628 573 libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid),
keir@20628 574 "shutdown", strlen("shutdown"));
keir@20628 575 }
keir@20512 576 rc = xc_domain_pause(ctx->xch, domid);
keir@20512 577 if (rc < 0) {
keir@20512 578 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_pause failed for %d", domid);
keir@20462 579 return -1;
keir@20462 580 }
keir@20628 581 if (dm_present) {
keir@20628 582 if (libxl_destroy_device_model(ctx, domid) < 0)
keir@20628 583 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_device_model failed for %d", domid);
keir@20628 584 }
keir@20462 585 if (libxl_devices_destroy(ctx, domid, force) < 0)
keir@20512 586 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d", domid);
keir@20462 587 if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
keir@20512 588 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", dom_path);
keir@20779 589
keir@20581 590 uuid_str = libxl_uuid_to_string(ctx, uuid);
keir@20779 591
keir@20779 592 vm_path = libxl_sprintf(ctx, "/vm/%s", uuid_str);
keir@20462 593 if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
keir@20512 594 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vm_path);
keir@20779 595
keir@20779 596 vss_path = libxl_sprintf(ctx, "/vss/%s", uuid_str);
keir@20581 597 if (!xs_rm(ctx->xsh, XBT_NULL, vss_path))
keir@20581 598 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vss_path);
keir@20779 599
keir@20779 600 xapi_path = libxl_sprintf(ctx, "/xapi/%u", domid);
keir@20581 601 if (!xs_rm(ctx->xsh, XBT_NULL, xapi_path))
keir@20581 602 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", xapi_path);
keir@20779 603
keir@20545 604 rc = xc_domain_destroy(ctx->xch, domid);
keir@20545 605 if (rc < 0) {
keir@20545 606 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
keir@20545 607 return -1;
keir@20545 608 }
keir@20462 609 return 0;
keir@20462 610 }
keir@20462 611
keir@20564 612 int libxl_console_attach(struct libxl_ctx *ctx, uint32_t domid, int cons_num)
keir@20564 613 {
keir@20564 614 struct stat st;
keir@20564 615 const char *XENCONSOLE = "/usr/lib/xen/bin/xenconsole";
keir@20564 616 char *cmd;
keir@20564 617
keir@20564 618 if (stat(XENCONSOLE, &st) != 0) {
keir@20564 619 XL_LOG(ctx, XL_LOG_ERROR, "could not access %s", XENCONSOLE);
keir@20564 620 return ERROR_FAIL;
keir@20564 621 }
keir@20564 622
keir@20564 623 cmd = libxl_sprintf(ctx, "%s %d --num %d", XENCONSOLE, domid, cons_num);
keir@20564 624 return (system(cmd) != 0) ? ERROR_FAIL : 0;
keir@20564 625 }
keir@20564 626
keir@20462 627 static char ** libxl_build_device_model_args(struct libxl_ctx *ctx,
keir@20462 628 libxl_device_model_info *info,
keir@20462 629 libxl_device_nic *vifs,
keir@20462 630 int num_vifs)
keir@20462 631 {
keir@20462 632 int num = 0, i;
keir@20462 633 flexarray_t *dm_args;
keir@20462 634 dm_args = flexarray_make(16, 1);
keir@20462 635 if (!dm_args)
keir@20462 636 return NULL;
keir@20462 637
keir@20516 638 flexarray_set(dm_args, num++, "qemu-dm");
keir@20516 639 flexarray_set(dm_args, num++, "-d");
keir@20462 640
keir@20462 641 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->domid));
keir@20462 642
keir@20462 643 if (info->dom_name) {
keir@20516 644 flexarray_set(dm_args, num++, "-domain-name");
keir@20516 645 flexarray_set(dm_args, num++, info->dom_name);
keir@20462 646 }
keir@20462 647 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
keir@20516 648 flexarray_set(dm_args, num++, "-vnc");
keir@20462 649 if (info->vncdisplay) {
keir@20462 650 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
keir@20462 651 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:%d", info->vnclisten, info->vncdisplay));
keir@20462 652 } else {
keir@20462 653 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "127.0.0.1:%d", info->vncdisplay));
keir@20462 654 }
keir@20462 655 } else if (info->vnclisten) {
keir@20462 656 if (strchr(info->vnclisten, ':') != NULL) {
keir@20516 657 flexarray_set(dm_args, num++, info->vnclisten);
keir@20462 658 } else {
keir@20462 659 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:0", info->vnclisten));
keir@20462 660 }
keir@20462 661 } else {
keir@20516 662 flexarray_set(dm_args, num++, "127.0.0.1:0");
keir@20462 663 }
keir@20462 664 if (info->vncunused) {
keir@20516 665 flexarray_set(dm_args, num++, "-vncunused");
keir@20462 666 }
keir@20462 667 }
keir@20462 668 if (info->sdl || info->opengl) {
keir@20516 669 flexarray_set(dm_args, num++, "-sdl");
keir@20462 670 if (info->opengl) {
keir@20516 671 flexarray_set(dm_args, num++, "-disable-opengl");
keir@20462 672 }
keir@20462 673 }
keir@20462 674 if (info->keymap) {
keir@20516 675 flexarray_set(dm_args, num++, "-k");
keir@20516 676 flexarray_set(dm_args, num++, info->keymap);
keir@20462 677 }
keir@20462 678 if (info->nographic && (!info->sdl && !info->vnc)) {
keir@20516 679 flexarray_set(dm_args, num++, "-nographic");
keir@20462 680 }
keir@20462 681 if (info->serial) {
keir@20516 682 flexarray_set(dm_args, num++, "-serial");
keir@20516 683 flexarray_set(dm_args, num++, info->serial);
keir@20462 684 }
keir@20509 685 if (info->type == XENFV) {
keir@20509 686 if (info->videoram) {
keir@20516 687 flexarray_set(dm_args, num++, "-videoram");
keir@20509 688 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->videoram));
keir@20509 689 }
keir@20509 690 if (info->stdvga) {
keir@20516 691 flexarray_set(dm_args, num++, "-std-vga");
keir@20509 692 }
keir@20509 693
keir@20509 694 if (info->boot) {
keir@20516 695 flexarray_set(dm_args, num++, "-boot");
keir@20516 696 flexarray_set(dm_args, num++, info->boot);
keir@20509 697 }
keir@20509 698 if (info->usb) {
keir@20516 699 flexarray_set(dm_args, num++, "-usb");
keir@20509 700 if (info->usbdevice) {
keir@20516 701 flexarray_set(dm_args, num++, "-usbdevice");
keir@20516 702 flexarray_set(dm_args, num++, info->usbdevice);
keir@20509 703 }
keir@20509 704 }
keir@20509 705 if (info->apic) {
keir@20516 706 flexarray_set(dm_args, num++, "-acpi");
keir@20509 707 }
keir@20509 708 for (i = 0; i < num_vifs; i++) {
keir@20509 709 if (vifs[i].nictype == NICTYPE_IOEMU) {
keir@20780 710 char *smac = libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20780 711 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
keir@20780 712 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
keir@20781 713 if (!vifs[i].ifname)
keir@20781 714 vifs[i].ifname = libxl_sprintf(ctx, "tap%d.%d", info->domid, vifs[i].devid - 1);
keir@20516 715 flexarray_set(dm_args, num++, "-net");
keir@20509 716 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "nic,vlan=%d,macaddr=%s,model=%s",
keir@20780 717 vifs[i].devid, smac, vifs[i].model));
keir@20516 718 flexarray_set(dm_args, num++, "-net");
keir@20509 719 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "tap,vlan=%d,ifname=%s,bridge=%s",
keir@20509 720 vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
keir@20509 721 }
keir@20462 722 }
keir@20462 723 }
keir@20565 724 if (info->saved_state) {
keir@20565 725 flexarray_set(dm_args, num++, "-loadvm");
keir@20565 726 flexarray_set(dm_args, num++, info->saved_state);
keir@20565 727 }
keir@20509 728 for (i = 0; info->extra && info->extra[i] != NULL; i++)
keir@20509 729 flexarray_set(dm_args, num++, info->extra[i]);
keir@20516 730 flexarray_set(dm_args, num++, "-M");
keir@20509 731 if (info->type == XENPV)
keir@20516 732 flexarray_set(dm_args, num++, "xenpv");
keir@20509 733 else
keir@20516 734 flexarray_set(dm_args, num++, "xenfv");
keir@20462 735 flexarray_set(dm_args, num++, NULL);
keir@20462 736
keir@20462 737 return (char **) flexarray_contents(dm_args);
keir@20462 738 }
keir@20462 739
keir@20514 740 void dm_xenstore_record_pid(struct libxl_ctx *ctx, void *for_spawn,
keir@20514 741 pid_t innerchild) {
keir@20514 742 struct libxl_device_model_starting *starting = for_spawn;
keir@20514 743 struct libxl_ctx clone;
keir@20514 744 char *kvs[3];
keir@20624 745 int rc, cloned;
keir@20514 746
keir@20624 747 if (libxl_clone_context_xs(ctx, &clone)) {
keir@20624 748 XL_LOG(ctx, XL_LOG_ERROR, "Out of memory when cloning context");
keir@20624 749 /* Throw a prayer fallback */
keir@20624 750 clone = *ctx;
keir@20624 751 clone.xsh = xs_daemon_open();
keir@20624 752 cloned = 0;
keir@20624 753 } else {
keir@20624 754 cloned = 1;
keir@20624 755 }
keir@20514 756 /* we mustn't use the parent's handle in the child */
keir@20514 757
keir@20514 758 kvs[0] = "image/device-model-pid";
keir@20610 759 kvs[1] = libxl_sprintf(&clone, "%d", innerchild);
keir@20514 760 kvs[2] = NULL;
keir@20610 761 rc = libxl_xs_writev(&clone, XBT_NULL, starting->dom_path, kvs);
keir@20610 762 if (rc) XL_LOG_ERRNO(&clone, XL_LOG_ERROR,
keir@20514 763 "Couldn't record device model pid %ld at %s/%s",
keir@20514 764 (unsigned long)innerchild, starting->dom_path, kvs);
keir@20624 765 if (cloned) {
keir@20624 766 libxl_discard_cloned_context_xs(&clone);
keir@20624 767 } else {
keir@20624 768 xs_daemon_close(clone.xsh);
keir@20624 769 }
keir@20514 770 }
keir@20514 771
keir@20542 772 static int libxl_vfb_and_vkb_from_device_model_info(struct libxl_ctx *ctx,
keir@20542 773 libxl_device_model_info *info,
keir@20542 774 libxl_device_vfb *vfb,
keir@20542 775 libxl_device_vkb *vkb)
keir@20542 776 {
keir@20542 777 memset(vfb, 0x00, sizeof(libxl_device_vfb));
keir@20542 778 memset(vkb, 0x00, sizeof(libxl_device_vkb));
keir@20542 779
keir@20542 780 vfb->backend_domid = 0;
keir@20542 781 vfb->devid = 0;
keir@20542 782 vfb->vnc = info->vnc;
keir@20542 783 vfb->vnclisten = info->vnclisten;
keir@20542 784 vfb->vncdisplay = info->vncdisplay;
keir@20542 785 vfb->vncunused = info->vncunused;
keir@20542 786 vfb->keymap = info->keymap;
keir@20542 787 vfb->sdl = info->sdl;
keir@20542 788 vfb->opengl = info->opengl;
keir@20542 789
keir@20542 790 vkb->backend_domid = 0;
keir@20542 791 vkb->devid = 0;
keir@20542 792 return 0;
keir@20542 793 }
keir@20542 794
keir@20542 795 static int libxl_write_dmargs(struct libxl_ctx *ctx, int domid, int guest_domid, char **args)
keir@20542 796 {
keir@20542 797 int i;
keir@20542 798 char *vm_path;
keir@20542 799 char *dmargs, *path;
keir@20542 800 int dmargs_size;
keir@20542 801 struct xs_permissions roperm[2];
keir@20542 802 xs_transaction_t t;
keir@20542 803
keir@20542 804 roperm[0].id = 0;
keir@20542 805 roperm[0].perms = XS_PERM_NONE;
keir@20542 806 roperm[1].id = domid;
keir@20542 807 roperm[1].perms = XS_PERM_READ;
keir@20542 808
keir@20542 809 vm_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/vm", guest_domid));
keir@20542 810
keir@20542 811 i = 0;
keir@20542 812 dmargs_size = 0;
keir@20542 813 while (args[i] != NULL) {
keir@20542 814 dmargs_size = dmargs_size + strlen(args[i]) + 1;
keir@20542 815 i++;
keir@20542 816 }
keir@20542 817 dmargs_size++;
keir@20542 818 dmargs = (char *) malloc(dmargs_size);
keir@20542 819 i = 1;
keir@20542 820 dmargs[0] = '\0';
keir@20542 821 while (args[i] != NULL) {
keir@20542 822 if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) {
keir@20542 823 strcat(dmargs, " ");
keir@20542 824 strcat(dmargs, args[i]);
keir@20542 825 }
keir@20542 826 i++;
keir@20542 827 }
keir@20542 828 path = libxl_sprintf(ctx, "%s/image/dmargs", vm_path);
keir@20542 829
keir@20542 830 retry_transaction:
keir@20542 831 t = xs_transaction_start(ctx->xsh);
keir@20542 832 xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs));
keir@20542 833 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
keir@20542 834 xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm));
keir@20542 835 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 836 if (errno == EAGAIN)
keir@20542 837 goto retry_transaction;
keir@20542 838 free(dmargs);
keir@20542 839 return 0;
keir@20542 840 }
keir@20542 841
keir@20542 842 static int libxl_create_stubdom(struct libxl_ctx *ctx,
keir@20542 843 libxl_device_model_info *info,
keir@20542 844 libxl_device_disk *disks, int num_disks,
keir@20542 845 libxl_device_nic *vifs, int num_vifs,
keir@20542 846 libxl_device_vfb *vfb,
keir@20542 847 libxl_device_vkb *vkb,
keir@20542 848 libxl_device_model_starting **starting_r)
keir@20542 849 {
keir@20570 850 int i, num_console = 1;
keir@20570 851 libxl_device_console *console;
keir@20542 852 libxl_domain_create_info c_info;
keir@20542 853 libxl_domain_build_info b_info;
keir@20542 854 libxl_domain_build_state state;
keir@20542 855 uint32_t domid;
keir@20542 856 char **args;
keir@20542 857 xen_uuid_t uuid[16];
keir@20542 858 struct xs_permissions perm[2];
keir@20542 859 xs_transaction_t t;
keir@20594 860 libxl_device_model_starting *dm_starting = 0;
keir@20542 861
keir@20542 862 args = libxl_build_device_model_args(ctx, info, vifs, num_vifs);
keir@20542 863 if (!args)
keir@20542 864 return ERROR_FAIL;
keir@20542 865
keir@20542 866 memset(&c_info, 0x00, sizeof(libxl_domain_create_info));
keir@20542 867 c_info.hvm = 0;
keir@20542 868 c_info.name = libxl_sprintf(ctx, "%s-dm", libxl_domid_to_name(ctx, info->domid));
keir@20542 869 xen_uuid_generate(uuid);
keir@20542 870 c_info.uuid = uuid;
keir@20542 871
keir@20542 872 memset(&b_info, 0x00, sizeof(libxl_domain_build_info));
keir@20542 873 b_info.max_vcpus = 1;
keir@20542 874 b_info.max_memkb = 32 * 1024;
keir@20647 875 b_info.target_memkb = b_info.max_memkb;
keir@20542 876 b_info.kernel = "/usr/lib/xen/boot/ioemu-stubdom.gz";
keir@20542 877 b_info.u.pv.cmdline = libxl_sprintf(ctx, " -d %d", info->domid);
keir@20542 878 b_info.u.pv.ramdisk = "";
keir@20542 879 b_info.u.pv.features = "";
keir@20542 880 b_info.hvm = 0;
keir@20542 881
keir@20542 882 libxl_domain_make(ctx, &c_info, &domid);
keir@20542 883 libxl_domain_build(ctx, &b_info, domid, &state);
keir@20542 884
keir@20542 885 libxl_write_dmargs(ctx, domid, info->domid, args);
keir@20542 886 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/image/device-model-domid", libxl_xs_get_dompath(ctx, info->domid)), "%d", domid);
keir@20542 887 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/target", libxl_xs_get_dompath(ctx, domid)), "%d", info->domid);
keir@20542 888 xc_domain_set_target(ctx->xch, domid, info->domid);
keir@20542 889 xs_set_target(ctx->xsh, domid, info->domid);
keir@20542 890
keir@20542 891 perm[0].id = domid;
keir@20542 892 perm[0].perms = XS_PERM_NONE;
keir@20542 893 perm[1].id = info->domid;
keir@20542 894 perm[1].perms = XS_PERM_READ;
keir@20542 895 retry_transaction:
keir@20542 896 t = xs_transaction_start(ctx->xsh);
keir@20542 897 xs_mkdir(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid));
keir@20542 898 xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm));
keir@20635 899 xs_mkdir(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/%d/device/vfs", domid));
keir@20635 900 xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm));
keir@20542 901 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 902 if (errno == EAGAIN)
keir@20542 903 goto retry_transaction;
keir@20542 904
keir@20542 905 for (i = 0; i < num_disks; i++) {
keir@20781 906 disks[i].domid = domid;
keir@20781 907 libxl_device_disk_add(ctx, domid, &disks[i]);
keir@20542 908 }
keir@20542 909 for (i = 0; i < num_vifs; i++) {
keir@20781 910 vifs[i].domid = domid;
keir@20781 911 libxl_device_nic_add(ctx, domid, &vifs[i]);
keir@20542 912 }
keir@20781 913 vfb->domid = domid;
keir@20542 914 libxl_device_vfb_add(ctx, domid, vfb);
keir@20781 915 vkb->domid = domid;
keir@20542 916 libxl_device_vkb_add(ctx, domid, vkb);
keir@20542 917
keir@20570 918 if (info->serial)
keir@20570 919 num_console++;
keir@20570 920 console = libxl_calloc(ctx, num_console, sizeof(libxl_device_console));
keir@20570 921 for (i = 0; i < num_console; i++) {
keir@20781 922 console[i].devid = i;
keir@20781 923 console[i].constype = CONSTYPE_IOEMU;
keir@20781 924 console[i].domid = domid;
keir@20570 925 if (!i)
keir@20781 926 console[i].build_state = &state;
keir@20570 927 libxl_device_console_add(ctx, domid, &console[i]);
keir@20570 928 }
keir@20594 929 if (libxl_create_xenpv_qemu(ctx, vfb, num_console, console, &dm_starting) < 0) {
keir@20594 930 free(args);
keir@20594 931 return -1;
keir@20594 932 }
keir@20594 933 if (libxl_confirm_device_model_startup(ctx, dm_starting) < 0) {
keir@20594 934 free(args);
keir@20594 935 return -1;
keir@20594 936 }
keir@20542 937
keir@20542 938 libxl_domain_unpause(ctx, domid);
keir@20542 939
keir@20594 940 if (starting_r) {
keir@20594 941 *starting_r = libxl_calloc(ctx, sizeof(libxl_device_model_starting), 1);
keir@20598 942 (*starting_r)->domid = info->domid;
keir@20594 943 (*starting_r)->dom_path = libxl_xs_get_dompath(ctx, info->domid);
keir@20594 944 (*starting_r)->for_spawn = NULL;
keir@20594 945 }
keir@20594 946
keir@20542 947 free(args);
keir@20542 948 return 0;
keir@20542 949 }
keir@20542 950
keir@20462 951 int libxl_create_device_model(struct libxl_ctx *ctx,
keir@20462 952 libxl_device_model_info *info,
keir@20542 953 libxl_device_disk *disks, int num_disks,
keir@20514 954 libxl_device_nic *vifs, int num_vifs,
keir@20514 955 libxl_device_model_starting **starting_r)
keir@20462 956 {
keir@20546 957 char *path, *logfile;
keir@20514 958 int logfile_w, null;
keir@20546 959 int rc;
keir@20462 960 char **args;
keir@20594 961 struct libxl_device_model_starting buf_starting, *p;
keir@20514 962
keir@20542 963 if (strstr(info->device_model, "stubdom-dm")) {
keir@20542 964 libxl_device_vfb vfb;
keir@20542 965 libxl_device_vkb vkb;
keir@20542 966
keir@20542 967 libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb);
keir@20542 968 return libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r);
keir@20542 969 }
keir@20542 970
keir@20462 971 args = libxl_build_device_model_args(ctx, info, vifs, num_vifs);
keir@20462 972 if (!args)
keir@20462 973 return ERROR_FAIL;
keir@20462 974
keir@20462 975 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid);
keir@20462 976 xs_mkdir(ctx->xsh, XBT_NULL, path);
keir@20462 977
keir@20546 978 libxl_create_logfile(ctx, libxl_sprintf(ctx, "qemu-dm-%s", info->dom_name), &logfile);
keir@20467 979 logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
keir@20546 980 free(logfile);
keir@20462 981 null = open("/dev/null", O_RDONLY);
keir@20514 982
keir@20514 983 if (starting_r) {
keir@20516 984 rc = ERROR_NOMEM;
keir@20594 985 *starting_r = libxl_calloc(ctx, sizeof(libxl_device_model_starting), 1);
keir@20516 986 if (!*starting_r) goto xit;
keir@20594 987 p = *starting_r;
keir@20611 988 p->for_spawn = libxl_calloc(ctx, sizeof(struct libxl_spawn_starting), 1);
keir@20594 989 } else {
keir@20594 990 p = &buf_starting;
keir@20594 991 p->for_spawn = NULL;
keir@20594 992 }
keir@20514 993
keir@20594 994 p->domid = info->domid;
keir@20594 995 p->dom_path = libxl_xs_get_dompath(ctx, info->domid);
keir@20594 996 if (!p->dom_path) { libxl_free(ctx, p); return ERROR_FAIL; }
keir@20594 997
keir@20594 998 rc = libxl_spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid);
keir@20514 999 if (rc < 0) goto xit;
keir@20514 1000 if (!rc) { /* inner child */
keir@20514 1001 libxl_exec(ctx, null, logfile_w, logfile_w,
keir@20514 1002 info->device_model, args);
keir@20514 1003 }
keir@20514 1004
keir@20514 1005 rc = 0;
keir@20514 1006 xit:
keir@20516 1007 free(args);
keir@20462 1008 close(null);
keir@20462 1009 close(logfile_w);
keir@20462 1010
keir@20514 1011 return rc;
keir@20514 1012 }
keir@20514 1013
keir@20514 1014 int libxl_detach_device_model(struct libxl_ctx *ctx,
keir@20779 1015 libxl_device_model_starting *starting)
keir@20779 1016 {
keir@20514 1017 int rc;
keir@20594 1018 rc = libxl_spawn_detach(ctx, starting->for_spawn);
keir@20594 1019 if (starting->for_spawn) libxl_free(ctx, starting->for_spawn);
keir@20514 1020 libxl_free(ctx, starting);
keir@20514 1021 return rc;
keir@20514 1022 }
keir@20462 1023
keir@20514 1024
keir@20514 1025 int libxl_confirm_device_model_startup(struct libxl_ctx *ctx,
keir@20779 1026 libxl_device_model_starting *starting)
keir@20779 1027 {
keir@20514 1028 int problem = libxl_wait_for_device_model(ctx, starting->domid, "running",
keir@20514 1029 libxl_spawn_check,
keir@20594 1030 starting->for_spawn);
keir@20514 1031 int detach = libxl_detach_device_model(ctx, starting);
keir@20514 1032 return problem ? problem : detach;
keir@20542 1033 return 0;
keir@20462 1034 }
keir@20462 1035
keir@20514 1036
keir@20462 1037 /******************************************************************************/
keir@20566 1038
keir@20566 1039 static int is_blktap2_supported(void)
keir@20566 1040 {
keir@20566 1041 char buf[1024];
keir@20566 1042 FILE *f = fopen("/proc/devices", "r");
keir@20566 1043
keir@20566 1044
keir@20566 1045 while (fgets(buf, sizeof(buf), f) != NULL) {
keir@20566 1046 if (strstr(buf, "blktap2")) {
keir@20566 1047 fclose(f);
keir@20566 1048 return 1;
keir@20566 1049 }
keir@20566 1050 }
keir@20566 1051 fclose(f);
keir@20566 1052 return 0;
keir@20566 1053 }
keir@20566 1054
keir@20566 1055 static char *get_blktap2_device(struct libxl_ctx *ctx, char *name, char *type)
keir@20566 1056 {
keir@20566 1057 char buf[1024];
keir@20566 1058 char *p;
keir@20566 1059 int devnum;
keir@20566 1060 FILE *f = fopen("/sys/class/blktap2/devices", "r");
keir@20566 1061
keir@20566 1062
keir@20566 1063 while (!feof(f)) {
keir@20566 1064 fscanf(f, "%d %s", &devnum, buf);
keir@20566 1065 p = strchr(buf, ':');
keir@20571 1066 if (p == NULL)
keir@20571 1067 continue;
keir@20566 1068 p++;
keir@20566 1069 if (!strcmp(p, name) && !strncmp(buf, type, 3)) {
keir@20566 1070 fclose(f);
keir@20566 1071 return libxl_sprintf(ctx, "/dev/xen/blktap-2/tapdev%d", devnum);
keir@20566 1072 }
keir@20566 1073 }
keir@20566 1074 fclose(f);
keir@20566 1075 return NULL;
keir@20566 1076 }
keir@20566 1077
keir@20462 1078 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20462 1079 {
keir@20462 1080 flexarray_t *front;
keir@20462 1081 flexarray_t *back;
keir@20462 1082 char *backend_type;
keir@20462 1083 unsigned int boffset = 0;
keir@20462 1084 unsigned int foffset = 0;
keir@20462 1085 int devid;
keir@20462 1086 libxl_device device;
keir@20566 1087 int major, minor;
keir@20462 1088
keir@20462 1089 front = flexarray_make(16, 1);
keir@20462 1090 if (!front)
keir@20462 1091 return ERROR_NOMEM;
keir@20462 1092 back = flexarray_make(16, 1);
keir@20462 1093 if (!back) /* leaks front if error */
keir@20462 1094 return ERROR_NOMEM;
keir@20462 1095
keir@20462 1096 backend_type = device_disk_backend_type_of_phystype(disk->phystype);
keir@20462 1097 devid = device_disk_dev_number(disk->virtpath);
keir@20462 1098
keir@20462 1099 device.backend_devid = devid;
keir@20462 1100 device.backend_domid = disk->backend_domid;
keir@20462 1101 device.devid = devid;
keir@20462 1102 device.domid = disk->domid;
keir@20462 1103 device.kind = DEVICE_VBD;
keir@20462 1104
keir@20462 1105 switch (disk->phystype) {
keir@20462 1106 case PHYSTYPE_PHY: {
keir@20462 1107
keir@20509 1108 device_physdisk_major_minor(disk->physpath, &major, &minor);
keir@20516 1109 flexarray_set(back, boffset++, "physical-device");
keir@20462 1110 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, minor));
keir@20462 1111
keir@20516 1112 flexarray_set(back, boffset++, "params");
keir@20516 1113 flexarray_set(back, boffset++, disk->physpath);
keir@20462 1114
keir@20462 1115 device.backend_kind = DEVICE_VBD;
keir@20462 1116 break;
keir@20462 1117 }
keir@20566 1118 case PHYSTYPE_FILE:
keir@20566 1119 /* let's pretend is tap:aio for the moment */
keir@20566 1120 disk->phystype = PHYSTYPE_AIO;
keir@20462 1121 case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD:
keir@20566 1122 if (is_blktap2_supported()) {
keir@20566 1123 int rc, c, p[2], tot;
keir@20566 1124 char buf[1024], *dev;
keir@20779 1125 dev = get_blktap2_device(ctx, disk->physpath, device_disk_string_of_phystype(disk->phystype));
keir@20779 1126 if (dev == NULL) {
keir@20566 1127 if (pipe(p) < 0) {
keir@20566 1128 XL_LOG(ctx, XL_LOG_ERROR, "Failed to create a pipe");
keir@20566 1129 return -1;
keir@20566 1130 }
keir@20566 1131 rc = fork();
keir@20566 1132 if (rc < 0) {
keir@20566 1133 XL_LOG(ctx, XL_LOG_ERROR, "Failed to fork a new process");
keir@20566 1134 return -1;
keir@20566 1135 } else if (!rc) { /* child */
keir@20566 1136 int null_r, null_w;
keir@20566 1137 char *args[4];
keir@20566 1138 args[0] = "tapdisk2";
keir@20566 1139 args[1] = "-n";
keir@20566 1140 args[2] = libxl_sprintf(ctx, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath);
keir@20566 1141 args[3] = NULL;
keir@20566 1142
keir@20566 1143 null_r = open("/dev/null", O_RDONLY);
keir@20566 1144 null_w = open("/dev/null", O_WRONLY);
keir@20566 1145 libxl_exec(ctx, null_r, p[1], null_w, "/usr/sbin/tapdisk2", args);
keir@20566 1146 XL_LOG(ctx, XL_LOG_ERROR, "Error execing tapdisk2");
keir@20566 1147 }
keir@20566 1148 close(p[1]);
keir@20566 1149 tot = 0;
keir@20566 1150 while ((c = read(p[0], buf + tot, sizeof(buf) - tot)) > 0)
keir@20566 1151 tot = tot + c;
keir@20566 1152 close(p[0]);
keir@20566 1153 buf[tot - 1] = '\0';
keir@20566 1154 dev = buf;
keir@20566 1155 }
keir@20566 1156 flexarray_set(back, boffset++, "tapdisk-params");
keir@20566 1157 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20566 1158 flexarray_set(back, boffset++, "params");
keir@20566 1159 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", dev));
keir@20566 1160 backend_type = "phy";
keir@20566 1161 device_physdisk_major_minor(dev, &major, &minor);
keir@20566 1162 flexarray_set(back, boffset++, "physical-device");
keir@20566 1163 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, minor));
keir@20566 1164 device.backend_kind = DEVICE_VBD;
keir@20566 1165
keir@20566 1166 break;
keir@20566 1167 }
keir@20516 1168 flexarray_set(back, boffset++, "params");
keir@20462 1169 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s",
keir@20462 1170 device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20462 1171
keir@20462 1172 device.backend_kind = DEVICE_TAP;
keir@20462 1173 break;
keir@20462 1174 }
keir@20462 1175
keir@20516 1176 flexarray_set(back, boffset++, "frontend-id");
keir@20462 1177 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", disk->domid));
keir@20516 1178 flexarray_set(back, boffset++, "online");
keir@20516 1179 flexarray_set(back, boffset++, "1");
keir@20516 1180 flexarray_set(back, boffset++, "removable");
keir@20462 1181 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", (disk->unpluggable) ? 1 : 0));
keir@20516 1182 flexarray_set(back, boffset++, "bootable");
keir@20509 1183 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1184 flexarray_set(back, boffset++, "state");
keir@20462 1185 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1186 flexarray_set(back, boffset++, "dev");
keir@20516 1187 flexarray_set(back, boffset++, disk->virtpath);
keir@20516 1188 flexarray_set(back, boffset++, "type");
keir@20516 1189 flexarray_set(back, boffset++, backend_type);
keir@20516 1190 flexarray_set(back, boffset++, "mode");
keir@20516 1191 flexarray_set(back, boffset++, disk->readwrite ? "w" : "r");
keir@20462 1192
keir@20516 1193 flexarray_set(front, foffset++, "backend-id");
keir@20462 1194 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", disk->backend_domid));
keir@20516 1195 flexarray_set(front, foffset++, "state");
keir@20462 1196 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1197 flexarray_set(front, foffset++, "virtual-device");
keir@20462 1198 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", devid));
keir@20516 1199 flexarray_set(front, foffset++, "device-type");
keir@20516 1200 flexarray_set(front, foffset++, disk->is_cdrom ? "cdrom" : "disk");
keir@20462 1201
keir@20462 1202 if (0 /* protocol != native*/) {
keir@20516 1203 flexarray_set(front, foffset++, "protocol");
keir@20516 1204 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
keir@20462 1205 }
keir@20462 1206
keir@20462 1207 libxl_device_generic_add(ctx, &device,
keir@20462 1208 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20462 1209 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20516 1210 flexarray_free(back);
keir@20516 1211 flexarray_free(front);
keir@20462 1212 return 0;
keir@20462 1213 }
keir@20462 1214
keir@20626 1215 int libxl_device_disk_del(struct libxl_ctx *ctx,
keir@20626 1216 libxl_device_disk *disk, int wait)
keir@20462 1217 {
keir@20626 1218 libxl_device device;
keir@20626 1219 int devid;
keir@20462 1220
keir@20626 1221 devid = device_disk_dev_number(disk->virtpath);
keir@20626 1222 device.backend_domid = disk->backend_domid;
keir@20626 1223 device.backend_devid = devid;
keir@20626 1224 device.backend_kind =
keir@20626 1225 (disk->phystype == PHYSTYPE_PHY) ? DEVICE_VBD : DEVICE_TAP;
keir@20626 1226 device.domid = disk->domid;
keir@20626 1227 device.devid = devid;
keir@20626 1228 device.kind = DEVICE_VBD;
keir@20626 1229 return libxl_device_del(ctx, &device, wait);
keir@20462 1230 }
keir@20462 1231
keir@20462 1232 /******************************************************************************/
keir@20462 1233 int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
keir@20462 1234 {
keir@20462 1235 flexarray_t *front;
keir@20462 1236 flexarray_t *back;
keir@20462 1237 unsigned int boffset = 0;
keir@20462 1238 unsigned int foffset = 0;
keir@20462 1239 libxl_device device;
keir@20462 1240
keir@20462 1241 front = flexarray_make(16, 1);
keir@20462 1242 if (!front)
keir@20462 1243 return ERROR_NOMEM;
keir@20462 1244 back = flexarray_make(16, 1);
keir@20462 1245 if (!back)
keir@20462 1246 return ERROR_NOMEM;
keir@20462 1247
keir@20462 1248 device.backend_devid = nic->devid;
keir@20462 1249 device.backend_domid = nic->backend_domid;
keir@20462 1250 device.backend_kind = DEVICE_VIF;
keir@20462 1251 device.devid = nic->devid;
keir@20462 1252 device.domid = nic->domid;
keir@20462 1253 device.kind = DEVICE_VIF;
keir@20462 1254
keir@20516 1255 flexarray_set(back, boffset++, "frontend-id");
keir@20462 1256 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->domid));
keir@20516 1257 flexarray_set(back, boffset++, "online");
keir@20516 1258 flexarray_set(back, boffset++, "1");
keir@20516 1259 flexarray_set(back, boffset++, "state");
keir@20462 1260 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1261 flexarray_set(back, boffset++, "script");
keir@20516 1262 flexarray_set(back, boffset++, nic->script);
keir@20516 1263 flexarray_set(back, boffset++, "mac");
keir@20462 1264 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1265 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1266 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20516 1267 flexarray_set(back, boffset++, "handle");
keir@20462 1268 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->devid));
keir@20462 1269
keir@20516 1270 flexarray_set(front, foffset++, "backend-id");
keir@20462 1271 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->backend_domid));
keir@20516 1272 flexarray_set(front, foffset++, "state");
keir@20462 1273 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1274 flexarray_set(front, foffset++, "handle");
keir@20462 1275 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->devid));
keir@20516 1276 flexarray_set(front, foffset++, "mac");
keir@20462 1277 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1278 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1279 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20462 1280 if (0 /* protocol != native*/) {
keir@20516 1281 flexarray_set(front, foffset++, "protocol");
keir@20516 1282 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
keir@20462 1283 }
keir@20462 1284
keir@20462 1285 libxl_device_generic_add(ctx, &device,
keir@20462 1286 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20462 1287 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20462 1288
keir@20462 1289 /* FIXME: wait for plug */
keir@20516 1290 flexarray_free(back);
keir@20516 1291 flexarray_free(front);
keir@20462 1292 return 0;
keir@20462 1293 }
keir@20462 1294
keir@20626 1295 int libxl_device_nic_del(struct libxl_ctx *ctx,
keir@20626 1296 libxl_device_nic *nic, int wait)
keir@20462 1297 {
keir@20626 1298 libxl_device device;
keir@20462 1299
keir@20626 1300 device.backend_devid = nic->devid;
keir@20626 1301 device.backend_domid = nic->backend_domid;
keir@20626 1302 device.backend_kind = DEVICE_VIF;
keir@20626 1303 device.devid = nic->devid;
keir@20626 1304 device.domid = nic->domid;
keir@20626 1305 device.kind = DEVICE_VIF;
keir@20626 1306
keir@20626 1307 return libxl_device_del(ctx, &device, wait);
keir@20462 1308 }
keir@20462 1309
keir@20462 1310 /******************************************************************************/
keir@20509 1311 int libxl_device_console_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
keir@20462 1312 {
keir@20509 1313 flexarray_t *front;
keir@20509 1314 flexarray_t *back;
keir@20509 1315 unsigned int boffset = 0;
keir@20509 1316 unsigned int foffset = 0;
keir@20509 1317 libxl_device device;
keir@20509 1318
keir@20509 1319 if (console->build_state) {
keir@20509 1320 xs_transaction_t t;
keir@20509 1321 char **ents = (char **) libxl_calloc(ctx, 9, sizeof(char *));
keir@20516 1322 ents[0] = "console/port";
keir@20509 1323 ents[1] = libxl_sprintf(ctx, "%"PRIu32, console->build_state->console_port);
keir@20516 1324 ents[2] = "console/ring-ref";
keir@20509 1325 ents[3] = libxl_sprintf(ctx, "%lu", console->build_state->console_mfn);
keir@20516 1326 ents[4] = "console/limit";
keir@20509 1327 ents[5] = libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT);
keir@20516 1328 ents[6] = "console/type";
keir@20509 1329 if (console->constype == CONSTYPE_XENCONSOLED)
keir@20509 1330 ents[7] = "xenconsoled";
keir@20509 1331 else
keir@20509 1332 ents[7] = "ioemu";
keir@20509 1333 retry_transaction:
keir@20509 1334 t = xs_transaction_start(ctx->xsh);
keir@20516 1335 libxl_xs_writev(ctx, t, libxl_xs_get_dompath(ctx, console->domid), ents);
keir@20509 1336 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20509 1337 if (errno == EAGAIN)
keir@20509 1338 goto retry_transaction;
keir@20509 1339 }
keir@20509 1340
keir@20509 1341 front = flexarray_make(16, 1);
keir@20509 1342 if (!front)
keir@20509 1343 return ERROR_NOMEM;
keir@20509 1344 back = flexarray_make(16, 1);
keir@20509 1345 if (!back)
keir@20509 1346 return ERROR_NOMEM;
keir@20509 1347
keir@20509 1348 device.backend_devid = console->devid;
keir@20509 1349 device.backend_domid = console->backend_domid;
keir@20509 1350 device.backend_kind = DEVICE_CONSOLE;
keir@20509 1351 device.devid = console->devid;
keir@20509 1352 device.domid = console->domid;
keir@20509 1353 device.kind = DEVICE_CONSOLE;
keir@20509 1354
keir@20516 1355 flexarray_set(back, boffset++, "frontend-id");
keir@20509 1356 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", console->domid));
keir@20516 1357 flexarray_set(back, boffset++, "online");
keir@20516 1358 flexarray_set(back, boffset++, "1");
keir@20516 1359 flexarray_set(back, boffset++, "state");
keir@20509 1360 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1361 flexarray_set(back, boffset++, "domain");
keir@20516 1362 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20516 1363 flexarray_set(back, boffset++, "protocol");
keir@20516 1364 flexarray_set(back, boffset++, LIBXL_XENCONSOLE_PROTOCOL);
keir@20509 1365
keir@20516 1366 flexarray_set(front, foffset++, "backend-id");
keir@20509 1367 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", console->backend_domid));
keir@20516 1368 flexarray_set(front, foffset++, "state");
keir@20509 1369 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1370 flexarray_set(front, foffset++, "limit");
keir@20509 1371 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT));
keir@20516 1372 flexarray_set(front, foffset++, "protocol");
keir@20516 1373 flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL);
keir@20516 1374 flexarray_set(front, foffset++, "type");
keir@20509 1375 if (console->constype == CONSTYPE_XENCONSOLED)
keir@20516 1376 flexarray_set(front, foffset++, "xenconsoled");
keir@20509 1377 else
keir@20516 1378 flexarray_set(front, foffset++, "ioemu");
keir@20509 1379
keir@20509 1380 libxl_device_generic_add(ctx, &device,
keir@20509 1381 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 1382 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20516 1383 flexarray_free(back);
keir@20516 1384 flexarray_free(front);
keir@20509 1385
keir@20509 1386 return 0;
keir@20509 1387 }
keir@20509 1388
keir@20509 1389 /******************************************************************************/
keir@20509 1390 int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
keir@20509 1391 {
keir@20509 1392 flexarray_t *front;
keir@20509 1393 flexarray_t *back;
keir@20509 1394 unsigned int boffset = 0;
keir@20509 1395 unsigned int foffset = 0;
keir@20509 1396 libxl_device device;
keir@20509 1397
keir@20509 1398 front = flexarray_make(16, 1);
keir@20509 1399 if (!front)
keir@20509 1400 return ERROR_NOMEM;
keir@20509 1401 back = flexarray_make(16, 1);
keir@20509 1402 if (!back)
keir@20509 1403 return ERROR_NOMEM;
keir@20509 1404
keir@20509 1405 device.backend_devid = vkb->devid;
keir@20509 1406 device.backend_domid = vkb->backend_domid;
keir@20509 1407 device.backend_kind = DEVICE_VKBD;
keir@20509 1408 device.devid = vkb->devid;
keir@20509 1409 device.domid = vkb->domid;
keir@20509 1410 device.kind = DEVICE_VKBD;
keir@20509 1411
keir@20516 1412 flexarray_set(back, boffset++, "frontend-id");
keir@20509 1413 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vkb->domid));
keir@20516 1414 flexarray_set(back, boffset++, "online");
keir@20516 1415 flexarray_set(back, boffset++, "1");
keir@20516 1416 flexarray_set(back, boffset++, "state");
keir@20509 1417 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1418 flexarray_set(back, boffset++, "domain");
keir@20516 1419 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20509 1420
keir@20516 1421 flexarray_set(front, foffset++, "backend-id");
keir@20509 1422 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vkb->backend_domid));
keir@20516 1423 flexarray_set(front, foffset++, "state");
keir@20509 1424 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 1425
keir@20509 1426 libxl_device_generic_add(ctx, &device,
keir@20509 1427 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 1428 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20516 1429 flexarray_free(back);
keir@20516 1430 flexarray_free(front);
keir@20509 1431
keir@20509 1432 return 0;
keir@20462 1433 }
keir@20462 1434
keir@20462 1435 int libxl_device_vkb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 1436 {
keir@20462 1437 return ERROR_NI;
keir@20462 1438 }
keir@20462 1439
keir@20462 1440 int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 1441 {
keir@20462 1442 return ERROR_NI;
keir@20462 1443 }
keir@20462 1444
keir@20637 1445 libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t domid, int *num)
keir@20637 1446 {
keir@20637 1447 char *be_path_tap, *be_path_vbd;
keir@20637 1448 libxl_device_disk *disks = NULL;
keir@20637 1449 char **l = NULL;
keir@20637 1450 unsigned int numl;
keir@20637 1451 int num_disks = 0, i;
keir@20637 1452 char *type;
keir@20637 1453
keir@20637 1454 be_path_vbd = libxl_sprintf(ctx, "%s/backend/vbd/%d", libxl_xs_get_dompath(ctx, 0), domid);
keir@20637 1455 be_path_tap = libxl_sprintf(ctx, "%s/backend/tap/%d", libxl_xs_get_dompath(ctx, 0), domid);
keir@20637 1456
keir@20637 1457 l = libxl_xs_directory(ctx, XBT_NULL, be_path_vbd, &numl);
keir@20637 1458 if (l) {
keir@20637 1459 num_disks += numl;
keir@20637 1460 disks = realloc(disks, sizeof(libxl_device_disk) * num_disks);
keir@20637 1461 for (i = 0; i < numl; i++) {
keir@20637 1462 disks[i].backend_domid = 0;
keir@20637 1463 disks[i].domid = domid;
keir@20637 1464 disks[i].physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/params", be_path_vbd, l[i]));
keir@20637 1465 libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/type", be_path_vbd, l[i])), &(disks[i].phystype));
keir@20637 1466 disks[i].virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/dev", be_path_vbd, l[i]));
keir@20637 1467 disks[i].unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/removable", be_path_vbd, l[i])));
keir@20637 1468 if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/mode", be_path_vbd, l[i])), "w"))
keir@20637 1469 disks[i].readwrite = 1;
keir@20637 1470 else
keir@20637 1471 disks[i].readwrite = 0;
keir@20637 1472 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[i]))));
keir@20637 1473 disks[i].is_cdrom = !strcmp(type, "cdrom");
keir@20637 1474 }
keir@20637 1475 free(l);
keir@20637 1476 }
keir@20637 1477 l = libxl_xs_directory(ctx, XBT_NULL, be_path_tap, &numl);
keir@20637 1478 if (l) {
keir@20637 1479 num_disks += numl;
keir@20637 1480 disks = realloc(disks, sizeof(libxl_device_disk) * num_disks);
keir@20637 1481 for (i = 0; i < numl; i++) {
keir@20637 1482 disks[i].backend_domid = 0;
keir@20637 1483 disks[i].domid = domid;
keir@20637 1484 disks[i].physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/params", be_path_tap, l[i]));
keir@20637 1485 libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/type", be_path_tap, l[i])), &(disks[i].phystype));
keir@20637 1486 disks[i].virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/dev", be_path_tap, l[i]));
keir@20637 1487 disks[i].unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/removable", be_path_tap, l[i])));
keir@20637 1488 if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/mode", be_path_tap, l[i])), "w"))
keir@20637 1489 disks[i].readwrite = 1;
keir@20637 1490 else
keir@20637 1491 disks[i].readwrite = 0;
keir@20637 1492 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[i]))));
keir@20637 1493 disks[i].is_cdrom = !strcmp(type, "cdrom");
keir@20637 1494 }
keir@20637 1495 free(l);
keir@20637 1496 }
keir@20637 1497 *num = num_disks;
keir@20637 1498 return disks;
keir@20637 1499 }
keir@20637 1500
keir@20637 1501 int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20637 1502 {
keir@20637 1503 int num, i;
keir@20637 1504 uint32_t stubdomid;
keir@20637 1505 libxl_device_disk *disks;
keir@20637 1506
keir@20637 1507 if (!disk->physpath) {
keir@20637 1508 disk->physpath = "";
keir@20637 1509 disk->phystype = PHYSTYPE_PHY;
keir@20637 1510 }
keir@20637 1511 disks = libxl_device_disk_list(ctx, domid, &num);
keir@20637 1512 for (i = 0; i < num; i++) {
keir@20637 1513 if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath))
keir@20637 1514 /* found */
keir@20637 1515 break;
keir@20637 1516 }
keir@20637 1517 if (i == num) {
keir@20637 1518 XL_LOG(ctx, XL_LOG_ERROR, "Virtual device not found");
keir@20637 1519 return -1;
keir@20637 1520 }
keir@20637 1521 libxl_device_disk_del(ctx, disks + i, 1);
keir@20637 1522 libxl_device_disk_add(ctx, domid, disk);
keir@20637 1523 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20637 1524 if (stubdomid) {
keir@20781 1525 disks[i].domid = stubdomid;
keir@20637 1526 libxl_device_disk_del(ctx, disks + i, 1);
keir@20781 1527 disk->domid = stubdomid;
keir@20637 1528 libxl_device_disk_add(ctx, stubdomid, disk);
keir@20781 1529 disk->domid = domid;
keir@20637 1530 }
keir@20637 1531 return 0;
keir@20637 1532 }
keir@20637 1533
keir@20462 1534 /******************************************************************************/
keir@20509 1535 static int libxl_build_xenpv_qemu_args(struct libxl_ctx *ctx,
keir@20509 1536 libxl_device_vfb *vfb,
keir@20509 1537 int num_console,
keir@20509 1538 libxl_device_console *console,
keir@20509 1539 libxl_device_model_info *info) {
keir@20509 1540 int i = 0, j = 0, num = 0;
keir@20509 1541 memset(info, 0x00, sizeof(libxl_device_model_info));
keir@20509 1542
keir@20509 1543 info->vnc = vfb->vnc;
keir@20509 1544 if (vfb->vnclisten)
keir@20509 1545 info->vnclisten = libxl_sprintf(ctx, "%s", vfb->vnclisten);
keir@20509 1546 info->vncdisplay = vfb->vncdisplay;
keir@20509 1547 info->vncunused = vfb->vncunused;
keir@20509 1548 if (vfb->keymap)
keir@20509 1549 info->keymap = libxl_sprintf(ctx, "%s", vfb->keymap);
keir@20509 1550 info->sdl = vfb->sdl;
keir@20509 1551 info->opengl = vfb->opengl;
keir@20509 1552 for (i = 0; i < num_console; i++) {
keir@20509 1553 if (console->constype == CONSTYPE_IOEMU)
keir@20509 1554 num++;
keir@20509 1555 }
keir@20509 1556 if (num > 0) {
keir@20599 1557 uint32_t guest_domid = libxl_is_stubdom(ctx, vfb->domid);
keir@20599 1558 if (guest_domid) {
keir@20599 1559 char *filename;
keir@20599 1560 char *name = libxl_sprintf(ctx, "qemu-dm-%s", libxl_domid_to_name(ctx, guest_domid));
keir@20599 1561 libxl_create_logfile(ctx, name, &filename);
keir@20599 1562 info->serial = libxl_sprintf(ctx, "file:%s", filename);
keir@20599 1563 free(filename);
keir@20599 1564 } else {
keir@20599 1565 info->serial = "pty";
keir@20599 1566 }
keir@20509 1567 num--;
keir@20509 1568 }
keir@20509 1569 if (num > 0) {
keir@20509 1570 info->extra = (char **) libxl_calloc(ctx, num * 2 + 1, sizeof(char *));
keir@20509 1571 for (j = 0; j < num * 2; j = j + 2) {
keir@20509 1572 info->extra[j] = "-serial";
keir@20509 1573 info->extra[j + 1] = "pty";
keir@20509 1574 }
keir@20509 1575 info->extra[j] = NULL;
keir@20509 1576 }
keir@20509 1577 info->domid = vfb->domid;
keir@20509 1578 info->dom_name = libxl_domid_to_name(ctx, vfb->domid);
keir@20509 1579 info->device_model = "/usr/lib/xen/bin/qemu-dm";
keir@20509 1580 info->type = XENPV;
keir@20509 1581 return 0;
keir@20509 1582 }
keir@20509 1583
keir@20509 1584 int libxl_create_xenpv_qemu(struct libxl_ctx *ctx, libxl_device_vfb *vfb,
keir@20514 1585 int num_console, libxl_device_console *console,
keir@20514 1586 struct libxl_device_model_starting **starting_r)
keir@20509 1587 {
keir@20509 1588 libxl_device_model_info info;
keir@20509 1589
keir@20509 1590 libxl_build_xenpv_qemu_args(ctx, vfb, num_console, console, &info);
keir@20542 1591 libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r);
keir@20509 1592 return 0;
keir@20509 1593 }
keir@20509 1594
keir@20509 1595 int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
keir@20462 1596 {
keir@20509 1597 flexarray_t *front;
keir@20509 1598 flexarray_t *back;
keir@20509 1599 unsigned int boffset = 0;
keir@20509 1600 unsigned int foffset = 0;
keir@20509 1601 libxl_device device;
keir@20509 1602
keir@20509 1603 front = flexarray_make(16, 1);
keir@20509 1604 if (!front)
keir@20509 1605 return ERROR_NOMEM;
keir@20509 1606 back = flexarray_make(16, 1);
keir@20509 1607 if (!back)
keir@20509 1608 return ERROR_NOMEM;
keir@20509 1609
keir@20509 1610 device.backend_devid = vfb->devid;
keir@20509 1611 device.backend_domid = vfb->backend_domid;
keir@20509 1612 device.backend_kind = DEVICE_VFB;
keir@20509 1613 device.devid = vfb->devid;
keir@20509 1614 device.domid = vfb->domid;
keir@20509 1615 device.kind = DEVICE_VFB;
keir@20509 1616
keir@20516 1617 flexarray_set(back, boffset++, "frontend-id");
keir@20509 1618 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->domid));
keir@20516 1619 flexarray_set(back, boffset++, "online");
keir@20516 1620 flexarray_set(back, boffset++, "1");
keir@20516 1621 flexarray_set(back, boffset++, "state");
keir@20509 1622 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1623 flexarray_set(back, boffset++, "domain");
keir@20516 1624 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20516 1625 flexarray_set(back, boffset++, "vnc");
keir@20509 1626 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vnc));
keir@20516 1627 flexarray_set(back, boffset++, "vnclisten");
keir@20516 1628 flexarray_set(back, boffset++, vfb->vnclisten);
keir@20516 1629 flexarray_set(back, boffset++, "vncdisplay");
keir@20509 1630 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncdisplay));
keir@20516 1631 flexarray_set(back, boffset++, "vncunused");
keir@20509 1632 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncunused));
keir@20516 1633 flexarray_set(back, boffset++, "sdl");
keir@20509 1634 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->sdl));
keir@20516 1635 flexarray_set(back, boffset++, "opengl");
keir@20509 1636 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->opengl));
keir@20509 1637 if (vfb->xauthority) {
keir@20516 1638 flexarray_set(back, boffset++, "xauthority");
keir@20516 1639 flexarray_set(back, boffset++, vfb->xauthority);
keir@20509 1640 }
keir@20509 1641 if (vfb->display) {
keir@20516 1642 flexarray_set(back, boffset++, "display");
keir@20516 1643 flexarray_set(back, boffset++, vfb->display);
keir@20509 1644 }
keir@20509 1645
keir@20516 1646 flexarray_set(front, foffset++, "backend-id");
keir@20509 1647 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vfb->backend_domid));
keir@20516 1648 flexarray_set(front, foffset++, "state");
keir@20509 1649 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 1650
keir@20509 1651 libxl_device_generic_add(ctx, &device,
keir@20509 1652 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 1653 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20509 1654 flexarray_free(front);
keir@20509 1655 flexarray_free(back);
keir@20509 1656
keir@20509 1657 return 0;
keir@20462 1658 }
keir@20462 1659
keir@20462 1660 int libxl_device_vfb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 1661 {
keir@20462 1662 return ERROR_NI;
keir@20462 1663 }
keir@20462 1664
keir@20462 1665 int libxl_device_vfb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 1666 {
keir@20462 1667 return ERROR_NI;
keir@20462 1668 }
keir@20462 1669
keir@20462 1670 /******************************************************************************/
keir@20482 1671
keir@20482 1672 int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
keir@20482 1673 unsigned int bus, unsigned int dev,
keir@20482 1674 unsigned int func, unsigned int vdevfn)
keir@20482 1675 {
keir@20482 1676 pcidev->domain = domain;
keir@20482 1677 pcidev->bus = bus;
keir@20482 1678 pcidev->dev = dev;
keir@20482 1679 pcidev->func = func;
keir@20482 1680 pcidev->vdevfn = vdevfn;
keir@20482 1681 return 0;
keir@20482 1682 }
keir@20482 1683
keir@20482 1684 static int libxl_create_pci_backend(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev, int num)
keir@20482 1685 {
keir@20482 1686 flexarray_t *front;
keir@20482 1687 flexarray_t *back;
keir@20482 1688 unsigned int boffset = 0;
keir@20482 1689 unsigned int foffset = 0;
keir@20482 1690 libxl_device device;
keir@20482 1691 int i;
keir@20482 1692
keir@20482 1693 front = flexarray_make(16, 1);
keir@20482 1694 if (!front)
keir@20482 1695 return ERROR_NOMEM;
keir@20482 1696 back = flexarray_make(16, 1);
keir@20482 1697 if (!back)
keir@20482 1698 return ERROR_NOMEM;
keir@20482 1699
keir@20512 1700 XL_LOG(ctx, XL_LOG_DEBUG, "Creating pci backend");
keir@20482 1701
keir@20482 1702 /* add pci device */
keir@20482 1703 device.backend_devid = 0;
keir@20482 1704 device.backend_domid = 0;
keir@20482 1705 device.backend_kind = DEVICE_PCI;
keir@20482 1706 device.devid = 0;
keir@20482 1707 device.domid = domid;
keir@20482 1708 device.kind = DEVICE_PCI;
keir@20482 1709
keir@20516 1710 flexarray_set(back, boffset++, "frontend-id");
keir@20482 1711 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", domid));
keir@20516 1712 flexarray_set(back, boffset++, "online");
keir@20516 1713 flexarray_set(back, boffset++, "1");
keir@20516 1714 flexarray_set(back, boffset++, "state");
keir@20482 1715 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1716 flexarray_set(back, boffset++, "domain");
keir@20516 1717 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid));
keir@20482 1718 for (i = 0; i < num; i++) {
keir@20482 1719 flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", i));
keir@20482 1720 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 1721 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", i));
keir@20482 1722 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 1723 if (pcidev->vdevfn) {
keir@20482 1724 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", i));
keir@20482 1725 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", pcidev->vdevfn));
keir@20482 1726 }
keir@20482 1727 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", i));
keir@20482 1728 flexarray_set(back, boffset++, libxl_sprintf(ctx, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
keir@20482 1729 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", i));
keir@20482 1730 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20482 1731 }
keir@20516 1732 flexarray_set(back, boffset++, "num_devs");
keir@20482 1733 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num));
keir@20482 1734
keir@20516 1735 flexarray_set(front, foffset++, "backend-id");
keir@20482 1736 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 0));
keir@20516 1737 flexarray_set(front, foffset++, "state");
keir@20482 1738 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20482 1739
keir@20482 1740 libxl_device_generic_add(ctx, &device,
keir@20482 1741 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20482 1742 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20482 1743
keir@20482 1744 flexarray_free(back);
keir@20482 1745 flexarray_free(front);
keir@20482 1746 return 0;
keir@20482 1747 }
keir@20482 1748
keir@20482 1749 static int libxl_device_pci_add_xenstore(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 1750 {
keir@20482 1751 flexarray_t *back;
keir@20482 1752 char *num_devs, *be_path;
keir@20482 1753 int num = 0;
keir@20482 1754 unsigned int boffset = 0;
keir@20482 1755 xs_transaction_t t;
keir@20482 1756
keir@20516 1757 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid);
keir@20482 1758 num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", be_path));
keir@20482 1759 if (!num_devs)
keir@20482 1760 return libxl_create_pci_backend(ctx, domid, pcidev, 1);
keir@20482 1761
keir@20482 1762 if (!is_hvm(ctx, domid)) {
keir@20482 1763 if (libxl_wait_for_backend(ctx, be_path, "4") < 0)
keir@20482 1764 return -1;
keir@20482 1765 }
keir@20482 1766
keir@20482 1767 back = flexarray_make(16, 1);
keir@20482 1768 if (!back)
keir@20482 1769 return ERROR_NOMEM;
keir@20482 1770
keir@20512 1771 XL_LOG(ctx, XL_LOG_DEBUG, "Adding new pci device to xenstore");
keir@20482 1772 num = atoi(num_devs);
keir@20482 1773 flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", num));
keir@20482 1774 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 1775 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", num));
keir@20482 1776 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 1777 if (pcidev->vdevfn) {
keir@20482 1778 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", num));
keir@20482 1779 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", pcidev->vdevfn));
keir@20482 1780 }
keir@20482 1781 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", num));
keir@20482 1782 flexarray_set(back, boffset++, libxl_sprintf(ctx, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
keir@20482 1783 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", num));
keir@20482 1784 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20516 1785 flexarray_set(back, boffset++, "num_devs");
keir@20482 1786 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num + 1));
keir@20516 1787 flexarray_set(back, boffset++, "state");
keir@20482 1788 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 7));
keir@20482 1789
keir@20482 1790 retry_transaction:
keir@20482 1791 t = xs_transaction_start(ctx->xsh);
keir@20482 1792 libxl_xs_writev(ctx, t, be_path,
keir@20482 1793 libxl_xs_kvs_of_flexarray(ctx, back, boffset));
keir@20482 1794 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20482 1795 if (errno == EAGAIN)
keir@20482 1796 goto retry_transaction;
keir@20482 1797
keir@20482 1798 flexarray_free(back);
keir@20482 1799 return 0;
keir@20482 1800 }
keir@20482 1801
keir@20482 1802 static int libxl_device_pci_remove_xenstore(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20482 1803 {
keir@20542 1804 char *be_path, *num_devs_path, *num_devs, *xsdev, *tmp, *tmppath;
keir@20542 1805 int num, i, j;
keir@20482 1806 xs_transaction_t t;
keir@20482 1807 unsigned int domain = 0, bus = 0, dev = 0, func = 0;
keir@20482 1808
keir@20516 1809 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid);
keir@20482 1810 num_devs_path = libxl_sprintf(ctx, "%s/num_devs", be_path);
keir@20482 1811 num_devs = libxl_xs_read(ctx, XBT_NULL, num_devs_path);
keir@20482 1812 if (!num_devs)
keir@20482 1813 return -1;
keir@20482 1814 num = atoi(num_devs);
keir@20482 1815
keir@20482 1816 if (!is_hvm(ctx, domid)) {
keir@20482 1817 if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
keir@20542 1818 XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", be_path);
keir@20482 1819 return -1;
keir@20482 1820 }
keir@20482 1821 }
keir@20482 1822
keir@20482 1823 for (i = 0; i < num; i++) {
keir@20482 1824 xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20482 1825 sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
keir@20482 1826 if (domain == pcidev->domain && bus == pcidev->bus &&
keir@20482 1827 pcidev->dev == dev && pcidev->func == func) {
keir@20482 1828 break;
keir@20482 1829 }
keir@20482 1830 }
keir@20482 1831 if (i == num) {
keir@20512 1832 XL_LOG(ctx, XL_LOG_ERROR, "Couldn't find the device on xenstore");
keir@20482 1833 return -1;
keir@20482 1834 }
keir@20482 1835
keir@20482 1836 retry_transaction:
keir@20482 1837 t = xs_transaction_start(ctx->xsh);
keir@20542 1838 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i), "5", strlen("5"));
keir@20482 1839 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state", be_path), "7", strlen("7"));
keir@20482 1840 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20482 1841 if (errno == EAGAIN)
keir@20482 1842 goto retry_transaction;
keir@20542 1843
keir@20542 1844 if (!is_hvm(ctx, domid)) {
keir@20542 1845 if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
keir@20542 1846 XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", be_path);
keir@20542 1847 return -1;
keir@20542 1848 }
keir@20542 1849 }
keir@20542 1850
keir@20542 1851 retry_transaction2:
keir@20542 1852 t = xs_transaction_start(ctx->xsh);
keir@20542 1853 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i));
keir@20542 1854 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, i));
keir@20542 1855 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20542 1856 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, i));
keir@20542 1857 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
keir@20542 1858 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
keir@20542 1859 libxl_xs_write(ctx, t, num_devs_path, "%d", num - 1);
keir@20542 1860 for (j = i + 1; j < num; j++) {
keir@20542 1861 tmppath = libxl_sprintf(ctx, "%s/state-%d", be_path, j);
keir@20542 1862 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 1863 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 1864 xs_rm(ctx->xsh, t, tmppath);
keir@20542 1865 tmppath = libxl_sprintf(ctx, "%s/dev-%d", be_path, j);
keir@20542 1866 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 1867 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 1868 xs_rm(ctx->xsh, t, tmppath);
keir@20542 1869 tmppath = libxl_sprintf(ctx, "%s/key-%d", be_path, j);
keir@20542 1870 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 1871 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 1872 xs_rm(ctx->xsh, t, tmppath);
keir@20542 1873 tmppath = libxl_sprintf(ctx, "%s/vdev-%d", be_path, j);
keir@20542 1874 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 1875 if (tmp) {
keir@20542 1876 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 1877 xs_rm(ctx->xsh, t, tmppath);
keir@20542 1878 }
keir@20542 1879 tmppath = libxl_sprintf(ctx, "%s/opts-%d", be_path, j);
keir@20542 1880 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 1881 if (tmp) {
keir@20542 1882 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 1883 xs_rm(ctx->xsh, t, tmppath);
keir@20542 1884 }
keir@20542 1885 tmppath = libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j);
keir@20542 1886 tmp = libxl_xs_read(ctx, t, tmppath);
keir@20542 1887 if (tmp) {
keir@20542 1888 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j - 1), tmp, strlen(tmp));
keir@20542 1889 xs_rm(ctx->xsh, t, tmppath);
keir@20542 1890 }
keir@20542 1891 }
keir@20542 1892 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 1893 if (errno == EAGAIN)
keir@20542 1894 goto retry_transaction2;
keir@20542 1895
keir@20542 1896 if (num == 1) {
keir@20542 1897 char *fe_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend", be_path));
keir@20542 1898 libxl_device_destroy(ctx, be_path, 1);
keir@20542 1899 xs_rm(ctx->xsh, XBT_NULL, be_path);
keir@20542 1900 xs_rm(ctx->xsh, XBT_NULL, fe_path);
keir@20542 1901 return 0;
keir@20542 1902 }
keir@20542 1903
keir@20482 1904 return 0;
keir@20462 1905 }
keir@20462 1906
keir@20482 1907 int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 1908 {
keir@20779 1909 char *path;
keir@20482 1910 char *state, *vdevfn;
keir@20482 1911 int rc, hvm;
keir@20542 1912 int stubdomid = 0;
keir@20482 1913
keir@20482 1914 /* TODO: check if the device can be assigned */
keir@20482 1915
keir@20482 1916 libxl_device_pci_flr(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1917
keir@20779 1918 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20779 1919 if (stubdomid != 0) {
keir@20542 1920 libxl_device_pci pcidev_s = *pcidev;
keir@20542 1921 libxl_device_pci_add(ctx, stubdomid, &pcidev_s);
keir@20542 1922 }
keir@20542 1923
keir@20482 1924 hvm = is_hvm(ctx, domid);
keir@20482 1925 if (hvm) {
keir@20514 1926 if (libxl_wait_for_device_model(ctx, domid, "running", 0,0) < 0) {
keir@20482 1927 return -1;
keir@20482 1928 }
keir@20779 1929 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 1930 state = libxl_xs_read(ctx, XBT_NULL, path);
keir@20779 1931 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 1932 if (pcidev->vdevfn)
keir@20482 1933 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF_VDEVFN, pcidev->domain,
keir@20482 1934 pcidev->bus, pcidev->dev, pcidev->func, pcidev->vdevfn);
keir@20482 1935 else
keir@20482 1936 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
keir@20482 1937 pcidev->bus, pcidev->dev, pcidev->func);
keir@20779 1938 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid);
keir@20482 1939 xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins"));
keir@20514 1940 if (libxl_wait_for_device_model(ctx, domid, "pci-inserted", 0,0) < 0)
keir@20512 1941 XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
keir@20779 1942 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 1943 vdevfn = libxl_xs_read(ctx, XBT_NULL, path);
keir@20482 1944 sscanf(vdevfn + 2, "%x", &pcidev->vdevfn);
keir@20779 1945 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 1946 xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
keir@20482 1947 } else {
keir@20542 1948 char *sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
keir@20482 1949 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1950 FILE *f = fopen(sysfs_path, "r");
keir@20482 1951 unsigned int start = 0, end = 0, flags = 0, size = 0;
keir@20482 1952 int irq = 0;
keir@20482 1953 int i;
keir@20482 1954
keir@20482 1955 if (f == NULL) {
keir@20512 1956 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 1957 return -1;
keir@20482 1958 }
keir@20482 1959 for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
keir@20512 1960 fscanf(f, "0x%x 0x%x 0x%x", &start, &end, &flags);
keir@20482 1961 size = end - start + 1;
keir@20482 1962 if (start) {
keir@20482 1963 if (flags & PCI_BAR_IO) {
keir@20482 1964 rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 1);
keir@20482 1965 if (rc < 0)
keir@20512 1966 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_ioport_permission error 0x%x/0x%x", start, size);
keir@20482 1967 } else {
keir@20482 1968 rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT,
keir@20482 1969 (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 1);
keir@20482 1970 if (rc < 0)
keir@20512 1971 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_iomem_permission error 0x%x/0x%x", start, size);
keir@20482 1972 }
keir@20482 1973 }
keir@20482 1974 }
keir@20482 1975 fclose(f);
keir@20542 1976 sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", pcidev->domain,
keir@20482 1977 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1978 f = fopen(sysfs_path, "r");
keir@20482 1979 if (f == NULL) {
keir@20512 1980 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 1981 goto out;
keir@20482 1982 }
keir@20482 1983 fscanf(f, "%u", &irq);
keir@20482 1984 if (irq) {
keir@20482 1985 rc = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
keir@20482 1986 if (rc < 0) {
keir@20512 1987 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_physdev_map_pirq irq=%d", irq);
keir@20482 1988 }
keir@20482 1989 rc = xc_domain_irq_permission(ctx->xch, domid, irq, 1);
keir@20482 1990 if (rc < 0) {
keir@20512 1991 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_irq_permission irq=%d", irq);
keir@20482 1992 }
keir@20482 1993 }
keir@20482 1994 fclose(f);
keir@20482 1995 }
keir@20482 1996 out:
keir@20542 1997 if (!libxl_is_stubdom(ctx, domid)) {
keir@20779 1998 rc = xc_assign_device(ctx->xch, domid, pcidev->value);
keir@20779 1999 if (rc < 0)
keir@20542 2000 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_assign_device failed");
keir@20542 2001 }
keir@20482 2002
keir@20482 2003 libxl_device_pci_add_xenstore(ctx, domid, pcidev);
keir@20482 2004 return 0;
keir@20462 2005 }
keir@20462 2006
keir@20482 2007 int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 2008 {
keir@20779 2009 char *path;
keir@20482 2010 char *state;
keir@20482 2011 int hvm, rc;
keir@20542 2012 int stubdomid = 0;
keir@20482 2013
keir@20482 2014 /* TODO: check if the device can be detached */
keir@20542 2015 libxl_device_pci_remove_xenstore(ctx, domid, pcidev);
keir@20482 2016
keir@20482 2017 hvm = is_hvm(ctx, domid);
keir@20482 2018 if (hvm) {
keir@20514 2019 if (libxl_wait_for_device_model(ctx, domid, "running", 0,0) < 0) {
keir@20482 2020 return -1;
keir@20482 2021 }
keir@20779 2022 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 2023 state = libxl_xs_read(ctx, XBT_NULL, path);
keir@20779 2024 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 2025 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
keir@20482 2026 pcidev->bus, pcidev->dev, pcidev->func);
keir@20779 2027 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid);
keir@20482 2028 xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem"));
keir@20514 2029 if (libxl_wait_for_device_model(ctx, domid, "pci-removed", 0,0) < 0) {
keir@20512 2030 XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
keir@20482 2031 return -1;
keir@20482 2032 }
keir@20779 2033 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid);
keir@20482 2034 xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
keir@20482 2035 } else {
keir@20542 2036 char *sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
keir@20482 2037 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2038 FILE *f = fopen(sysfs_path, "r");
keir@20482 2039 unsigned int start = 0, end = 0, flags = 0, size = 0;
keir@20482 2040 int irq = 0;
keir@20482 2041 int i;
keir@20482 2042
keir@20482 2043 if (f == NULL) {
keir@20512 2044 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 2045 goto skip1;
keir@20482 2046 }
keir@20482 2047 for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
keir@20482 2048 fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags);
keir@20482 2049 size = end - start + 1;
keir@20482 2050 if (start) {
keir@20482 2051 if (flags & PCI_BAR_IO) {
keir@20482 2052 rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 0);
keir@20482 2053 if (rc < 0)
keir@20512 2054 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_ioport_permission error 0x%x/0x%x", start, size);
keir@20482 2055 } else {
keir@20482 2056 rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT,
keir@20482 2057 (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 0);
keir@20482 2058 if (rc < 0)
keir@20512 2059 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_iomem_permission error 0x%x/0x%x", start, size);
keir@20482 2060 }
keir@20482 2061 }
keir@20482 2062 }
keir@20482 2063 fclose(f);
keir@20482 2064 skip1:
keir@20542 2065 sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", pcidev->domain,
keir@20482 2066 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2067 f = fopen(sysfs_path, "r");
keir@20482 2068 if (f == NULL) {
keir@20512 2069 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 2070 goto out;
keir@20482 2071 }
keir@20482 2072 fscanf(f, "%u", &irq);
keir@20482 2073 if (irq) {
keir@20482 2074 rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
keir@20482 2075 if (rc < 0) {
keir@20512 2076 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_physdev_map_pirq irq=%d", irq);
keir@20482 2077 }
keir@20482 2078 rc = xc_domain_irq_permission(ctx->xch, domid, irq, 0);
keir@20482 2079 if (rc < 0) {
keir@20512 2080 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_irq_permission irq=%d", irq);
keir@20482 2081 }
keir@20482 2082 }
keir@20482 2083 fclose(f);
keir@20482 2084 }
keir@20482 2085 out:
keir@20482 2086 libxl_device_pci_flr(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 2087
keir@20542 2088 if (!libxl_is_stubdom(ctx, domid)) {
keir@20779 2089 rc = xc_deassign_device(ctx->xch, domid, pcidev->value);
keir@20779 2090 if (rc < 0)
keir@20542 2091 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_deassign_device failed");
keir@20542 2092 }
keir@20542 2093
keir@20779 2094 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20779 2095 if (stubdomid != 0) {
keir@20542 2096 libxl_device_pci pcidev_s = *pcidev;
keir@20542 2097 libxl_device_pci_remove(ctx, stubdomid, &pcidev_s);
keir@20542 2098 }
keir@20542 2099
keir@20482 2100 return 0;
keir@20462 2101 }
keir@20482 2102
keir@20482 2103 libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t domid, int *num)
keir@20482 2104 {
keir@20482 2105 char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts;
keir@20482 2106 int n, i;
keir@20482 2107 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
keir@20482 2108 libxl_device_pci *pcidevs;
keir@20482 2109
keir@20516 2110 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid);
keir@20482 2111 num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", be_path));
keir@20482 2112 if (!num_devs) {
keir@20482 2113 *num = 0;
keir@20482 2114 return NULL;
keir@20482 2115 }
keir@20482 2116 n = atoi(num_devs);
keir@20779 2117 pcidevs = calloc(n, sizeof(libxl_device_pci));
keir@20482 2118 *num = n;
keir@20482 2119
keir@20482 2120 for (i = 0; i < n; i++) {
keir@20482 2121 xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20482 2122 sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
keir@20482 2123 xsvdevfn = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
keir@20482 2124 if (xsvdevfn)
keir@20482 2125 vdevfn = strtol(xsvdevfn, (char **) NULL, 16);
keir@20482 2126 libxl_device_pci_init(pcidevs + i, domain, bus, dev, func, vdevfn);
keir@20482 2127 xsopts = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
keir@20482 2128 if (xsopts) {
keir@20482 2129 char *saveptr;
keir@20482 2130 char *p = strtok_r(xsopts, ",=", &saveptr);
keir@20482 2131 do {
keir@20482 2132 while (*p == ' ')
keir@20482 2133 p++;
keir@20482 2134 if (!strcmp(p, "msitranslate")) {
keir@20482 2135 p = strtok_r(NULL, ",=", &saveptr);
keir@20482 2136 pcidevs[i].msitranslate = atoi(p);
keir@20482 2137 } else if (!strcmp(p, "power_mgmt")) {
keir@20482 2138 p = strtok_r(NULL, ",=", &saveptr);
keir@20482 2139 pcidevs[i].power_mgmt = atoi(p);
keir@20482 2140 }
keir@20482 2141 } while ((p = strtok_r(NULL, ",=", &saveptr)) != NULL);
keir@20482 2142 }
keir@20482 2143 }
keir@20482 2144 return pcidevs;
keir@20482 2145 }
keir@20482 2146
keir@20482 2147 int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20482 2148 {
keir@20482 2149 libxl_device_pci *pcidevs;
keir@20482 2150 int num, i;
keir@20482 2151
keir@20482 2152 pcidevs = libxl_device_pci_list(ctx, domid, &num);
keir@20482 2153 for (i = 0; i < num; i++) {
keir@20482 2154 if (libxl_device_pci_remove(ctx, domid, pcidevs + i) < 0)
keir@20482 2155 return -1;
keir@20482 2156 }
keir@20516 2157 free(pcidevs);
keir@20482 2158 return 0;
keir@20482 2159 }
keir@20482 2160
keir@20647 2161 int libxl_set_memory_target(struct libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb)
keir@20647 2162 {
keir@20647 2163 int rc = 0;
keir@20647 2164 uint32_t videoram;
keir@20647 2165 char *videoram_s = NULL;
keir@20647 2166 char *dompath = libxl_xs_get_dompath(ctx, domid);
keir@20542 2167
keir@20647 2168 videoram_s = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/videoram", dompath));
keir@20647 2169 if (!videoram_s)
keir@20647 2170 return -1;
keir@20647 2171 videoram = atoi(videoram_s);
keir@20647 2172
keir@20647 2173 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", dompath), "%lu", target_memkb);
keir@20779 2174 rc = xc_domain_setmaxmem(ctx->xch, domid, target_memkb + LIBXL_MAXMEM_CONSTANT);
keir@20779 2175 if (rc != 0)
keir@20779 2176 return rc;
keir@20647 2177 rc = xc_domain_memory_set_pod_target(ctx->xch, domid, (target_memkb - videoram) / 4, NULL, NULL, NULL);
keir@20647 2178 return rc;
keir@20647 2179 }