debuggers.hg

annotate tools/libxl/libxl.c @ 20801:74ca2cb026a5

libxenlight: remove any uuid dependancies from xl

uuid handles in create and now create_device_model need to fill the
uuid field by client. the uuid field happens to be the exact same size
as the standard uuid (sixteen 8 bits values).

stubdom need to have a uuid when created, so using the one in
create_device_model.

this permits the client library to generate the uuid in any way it see
fits (even if it's not compliant to any standard), and simplify
installation of the libxenlight header.

xl converted from libuuid generated uuid to generated through random()
C call. need to be fixed if anyone plan to use xl for anything
seriously apart from developing libxl.

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