debuggers.hg

annotate tools/libxl/libxl.c @ 20512:b72f27350703

libxenlight: Clean up logging arrangements

* Introduce new variants of the logging functions which include
errno values (converted using strerror) in the messages passed to
the
application's logging callback.

* Use the new errno-including logging functions everywhere where
appropriate. In general, xc_... functions return errno values or 0;
xs_... functions return 0 or -1 (or some such) setting errno.

* When libxl_xs_get_dompath fails, do not treat it as an allocation
error. It isn't: it usually means xenstored failed.

* Remove many spurious \n's from log messages. (The applications log
callback is expected to add a \n if it wants to do that, so libxl's
logging functions should be passed strings without \n.)

Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Nov 23 06:59:06 2009 +0000 (2009-11-23)
parents 014579af0350
children 20063cea1606
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@20462 17 #include <stdio.h>
keir@20462 18 #include <string.h>
keir@20462 19 #include <stdlib.h>
keir@20462 20 #include <sys/stat.h>
keir@20462 21 #include <sys/types.h>
keir@20462 22 #include <fcntl.h>
keir@20462 23 #include <sys/select.h>
keir@20462 24 #include <signal.h>
keir@20468 25 #include <unistd.h> /* for write, unlink and close */
keir@20509 26 #include <stdint.h>
keir@20509 27 #include <inttypes.h>
keir@20462 28 #include "libxl.h"
keir@20462 29 #include "libxl_utils.h"
keir@20462 30 #include "libxl_internal.h"
keir@20462 31 #include "flexarray.h"
keir@20462 32
keir@20462 33 int libxl_ctx_init(struct libxl_ctx *ctx)
keir@20462 34 {
keir@20462 35 memset(ctx, 0, sizeof(struct libxl_ctx));
keir@20462 36 ctx->alloc_maxsize = 256;
keir@20462 37 ctx->alloc_ptrs = calloc(ctx->alloc_maxsize, sizeof(void *));
keir@20462 38 if (!ctx->alloc_ptrs)
keir@20462 39 return ERROR_NOMEM;
keir@20462 40
keir@20462 41 ctx->xch = xc_interface_open();
keir@20462 42 ctx->xsh = xs_daemon_open();
keir@20462 43 return 0;
keir@20462 44 }
keir@20462 45
keir@20462 46 int libxl_ctx_free(struct libxl_ctx *ctx)
keir@20462 47 {
keir@20462 48 libxl_free_all(ctx);
keir@20462 49 free(ctx->alloc_ptrs);
keir@20462 50 ctx->alloc_ptrs = NULL;
keir@20462 51 xc_interface_close(ctx->xch);
keir@20462 52 xs_daemon_close(ctx->xsh);
keir@20462 53 return 0;
keir@20462 54 }
keir@20462 55
keir@20462 56 int libxl_ctx_set_log(struct libxl_ctx *ctx, libxl_log_callback log_callback, void *log_data)
keir@20462 57 {
keir@20462 58 ctx->log_callback = log_callback;
keir@20462 59 ctx->log_userdata = log_data;
keir@20462 60 return 0;
keir@20462 61 }
keir@20462 62
keir@20462 63 /******************************************************************************/
keir@20462 64
keir@20462 65 int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info,
keir@20462 66 uint32_t *domid)
keir@20462 67 {
keir@20462 68 int flags, ret, i;
keir@20468 69 char *uuid_string;
keir@20462 70 char *rw_paths[] = { "device" };
keir@20462 71 char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
keir@20462 72 "control", "attr", "data", "messages" };
keir@20462 73 char *dom_path, *vm_path, *vss_path;
keir@20462 74 struct xs_permissions roperm[2];
keir@20462 75 struct xs_permissions rwperm[1];
keir@20462 76 xs_transaction_t t;
keir@20468 77 xen_domain_handle_t handle;
keir@20462 78
keir@20468 79 uuid_string = libxl_uuid_to_string(ctx, info->uuid);
keir@20462 80 if (!uuid_string) {
keir@20462 81 XL_LOG(ctx, XL_LOG_ERROR, "missing uuid");
keir@20462 82 return ERROR_FAIL;
keir@20462 83 }
keir@20462 84
keir@20462 85 flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
keir@20462 86 flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
keir@20462 87 *domid = 0;
keir@20462 88
keir@20468 89 /* XXX handle has to be initialised here.
keir@20468 90 * info->uuid != xen_domain_handle_t
keir@20468 91 * See:
keir@20468 92 * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
keir@20468 93 * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm
keir@20468 94 *
keir@20468 95 * A DCE 1.1 compatible source representation of UUIDs.
keir@20468 96 *
keir@20468 97 * struct uuid {
keir@20468 98 * uint32_t time_low;
keir@20468 99 * uint16_t time_mid;
keir@20468 100 * uint16_t time_hi_and_version;
keir@20468 101 * uint8_t clock_seq_hi_and_reserved;
keir@20468 102 * uint8_t clock_seq_low;
keir@20468 103 * uint8_t node[_UUID_NODE_LEN];
keir@20468 104 * };
keir@20468 105 */
keir@20468 106
keir@20468 107 ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
keir@20462 108 if (ret < 0) {
keir@20512 109 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain creation fail");
keir@20462 110 return ERROR_FAIL;
keir@20462 111 }
keir@20462 112
keir@20462 113 dom_path = libxl_xs_get_dompath(ctx, *domid);
keir@20512 114 if (!dom_path)
keir@20512 115 return ERROR_FAIL;
keir@20512 116
keir@20462 117 vm_path = libxl_sprintf(ctx, "/vm/%s", uuid_string);
keir@20462 118 vss_path = libxl_sprintf(ctx, "/vss/%s", uuid_string);
keir@20512 119 if (!vm_path || !vss_path) {
keir@20462 120 XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate create paths");
keir@20462 121 return ERROR_FAIL;
keir@20462 122 }
keir@20462 123
keir@20462 124 roperm[0].id = 0;
keir@20462 125 roperm[0].perms = XS_PERM_NONE;
keir@20462 126 roperm[1].id = *domid;
keir@20462 127 roperm[1].perms = XS_PERM_READ;
keir@20462 128 rwperm[0].id = *domid;
keir@20462 129 rwperm[0].perms = XS_PERM_NONE;
keir@20462 130
keir@20462 131 retry_transaction:
keir@20462 132 t = xs_transaction_start(ctx->xsh);
keir@20462 133 xs_rm(ctx->xsh, t, dom_path);
keir@20462 134 xs_mkdir(ctx->xsh, t, dom_path);
keir@20462 135 xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm));
keir@20462 136
keir@20462 137 xs_rm(ctx->xsh, t, vm_path);
keir@20462 138 xs_mkdir(ctx->xsh, t, vm_path);
keir@20462 139 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
keir@20462 140
keir@20462 141 xs_rm(ctx->xsh, t, vss_path);
keir@20462 142 xs_mkdir(ctx->xsh, t, vss_path);
keir@20462 143 xs_set_permissions(ctx->xsh, t, vss_path, rwperm, ARRAY_SIZE(rwperm));
keir@20462 144
keir@20462 145 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vm", dom_path), vm_path, strlen(vm_path));
keir@20462 146 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vss", dom_path), vss_path, strlen(vss_path));
keir@20462 147 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", dom_path), info->name, strlen(info->name));
keir@20462 148
keir@20462 149 for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
keir@20462 150 char *path = libxl_sprintf(ctx, "%s/%s", dom_path, rw_paths[i]);
keir@20462 151 xs_mkdir(ctx->xsh, t, path);
keir@20462 152 xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm));
keir@20462 153 libxl_free(ctx, path);
keir@20462 154 }
keir@20462 155 for (i = 0; i < ARRAY_SIZE(ro_paths); i++) {
keir@20462 156 char *path = libxl_sprintf(ctx, "%s/%s", dom_path, ro_paths[i]);
keir@20462 157 xs_mkdir(ctx->xsh, t, path);
keir@20462 158 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
keir@20462 159 libxl_free(ctx, path);
keir@20462 160 }
keir@20462 161
keir@20462 162 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
keir@20462 163 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", vm_path), info->name, strlen(info->name));
keir@20462 164
keir@20462 165 libxl_xs_writev(ctx, t, dom_path, info->xsdata);
keir@20462 166 libxl_xs_writev(ctx, t, libxl_sprintf(ctx, "%s/platform", dom_path), info->platformdata);
keir@20462 167
keir@20462 168 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
keir@20462 169
keir@20462 170 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20462 171 if (errno == EAGAIN)
keir@20462 172 goto retry_transaction;
keir@20462 173 return 0;
keir@20462 174 }
keir@20462 175
keir@20509 176 libxl_domain_build_state *libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid)
keir@20462 177 {
keir@20509 178 libxl_domain_build_state *state = (libxl_domain_build_state *) libxl_calloc(ctx, 1, sizeof(libxl_domain_build_state));
keir@20462 179 char **vments = NULL, **localents = NULL;
keir@20462 180
keir@20509 181 build_pre(ctx, domid, info, state);
keir@20462 182 if (info->hvm) {
keir@20509 183 build_hvm(ctx, domid, info, state);
keir@20509 184 vments = libxl_calloc(ctx, 5, sizeof(char *));
keir@20462 185 vments[0] = libxl_sprintf(ctx, "rtc/timeoffset");
keir@20462 186 vments[1] = libxl_sprintf(ctx, "%s", (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "");
keir@20509 187 vments[2] = libxl_sprintf(ctx, "image/ostype");
keir@20509 188 vments[3] = libxl_sprintf(ctx, "hvm");
keir@20462 189 } else {
keir@20509 190 build_pv(ctx, domid, info, state);
keir@20509 191 vments = libxl_calloc(ctx, 9, sizeof(char *));
keir@20509 192 vments[0] = libxl_sprintf(ctx, "image/ostype");
keir@20509 193 vments[1] = libxl_sprintf(ctx, "linux");
keir@20509 194 vments[2] = libxl_sprintf(ctx, "image/kernel");
keir@20509 195 vments[3] = libxl_sprintf(ctx, info->kernel);
keir@20509 196 vments[4] = libxl_sprintf(ctx, "image/ramdisk");
keir@20509 197 vments[5] = libxl_sprintf(ctx, info->u.pv.ramdisk);
keir@20509 198 vments[6] = libxl_sprintf(ctx, "image/cmdline");
keir@20509 199 vments[7] = libxl_sprintf(ctx, info->u.pv.cmdline);
keir@20462 200 }
keir@20509 201 build_post(ctx, domid, info, state, vments, localents);
keir@20509 202 return state;
keir@20462 203 }
keir@20462 204
keir@20462 205 int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info,
keir@20462 206 uint32_t domid, int fd)
keir@20462 207 {
keir@20462 208 libxl_domain_build_state state;
keir@20462 209 char **vments = NULL, **localents = NULL;
keir@20462 210
keir@20462 211 memset(&state, '\0', sizeof(state));
keir@20462 212
keir@20462 213 build_pre(ctx, domid, info, &state);
keir@20462 214 restore_common(ctx, domid, info, &state, fd);
keir@20462 215 if (info->hvm) {
keir@20462 216 vments = libxl_calloc(ctx, 4, sizeof(char *));
keir@20462 217 vments[0] = libxl_sprintf(ctx, "rtc/timeoffset");
keir@20462 218 vments[1] = libxl_sprintf(ctx, "%s", (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "");
keir@20462 219 } else {
keir@20462 220 localents = libxl_calloc(ctx, 4 * 2, sizeof(char *));
keir@20462 221 localents[0] = libxl_sprintf(ctx, "serial/0/limit");
keir@20462 222 localents[1] = libxl_sprintf(ctx, "%d", 65536);
keir@20462 223 localents[2] = libxl_sprintf(ctx, "console/port");
keir@20462 224 localents[3] = libxl_sprintf(ctx, "%d", state.console_port);
keir@20462 225 localents[4] = libxl_sprintf(ctx, "console/ring-ref");
keir@20462 226 localents[5] = libxl_sprintf(ctx, "%ld", state.console_mfn);
keir@20462 227 }
keir@20462 228 build_post(ctx, domid, info, &state, vments, localents);
keir@20462 229 return 0;
keir@20462 230 }
keir@20462 231
keir@20462 232 struct libxl_dominfo * libxl_domain_list(struct libxl_ctx *ctx, int *nb_domain)
keir@20462 233 {
keir@20462 234 struct libxl_dominfo *ptr;
keir@20462 235 int index, i, ret, first_domain;
keir@20462 236 xc_domaininfo_t info[16];
keir@20462 237 int size = 16;
keir@20462 238
keir@20462 239 first_domain = 1;
keir@20462 240 index = 0;
keir@20462 241 ptr = libxl_calloc(ctx, size, sizeof(struct libxl_dominfo));
keir@20462 242 if (!ptr)
keir@20462 243 return NULL;
keir@20462 244 redo:
keir@20462 245 ret = xc_domain_getinfolist(ctx->xch, first_domain, 16, info);
keir@20462 246 for (i = 0; i < ret; i++) {
keir@20462 247 if (index == size) {
keir@20462 248 struct libxl_dominfo *ptr2;
keir@20462 249
keir@20462 250 ptr2 = libxl_calloc(ctx, size * 2, sizeof(struct libxl_dominfo));
keir@20462 251 if (!ptr2) {
keir@20462 252 libxl_free(ctx, ptr);
keir@20462 253 return NULL;
keir@20462 254 }
keir@20462 255 memcpy(ptr2, ptr, sizeof(struct libxl_dominfo) * size);
keir@20462 256 libxl_free(ctx, ptr);
keir@20462 257 ptr = ptr2;
keir@20462 258 size *= 2;
keir@20462 259 }
keir@20462 260 memcpy(ptr[index].uuid, info[i].handle, 16 * sizeof(uint8_t));
keir@20462 261 ptr[index].domid = info[i].domain;
keir@20462 262 first_domain = info[i].domain + 1;
keir@20462 263 index++;
keir@20462 264 }
keir@20462 265 if (ret == 16)
keir@20462 266 goto redo;
keir@20462 267 *nb_domain = index;
keir@20462 268 return ptr;
keir@20462 269 }
keir@20462 270
keir@20462 271 xc_dominfo_t * libxl_domain_infolist(struct libxl_ctx *ctx, int *nb_domain)
keir@20462 272 {
keir@20462 273 int index, first_domain;
keir@20462 274 xc_dominfo_t *info;
keir@20462 275 int size = 1024;
keir@20462 276
keir@20462 277 first_domain = 0;
keir@20462 278 index = 0;
keir@20462 279 info = (xc_dominfo_t *) libxl_calloc(ctx, size, sizeof(xc_dominfo_t));
keir@20462 280 if (!info) {
keir@20462 281 *nb_domain = 0;
keir@20462 282 return NULL;
keir@20462 283 }
keir@20462 284 *nb_domain = xc_domain_getinfo(ctx->xch, first_domain, 1024, info);
keir@20462 285 return info;
keir@20462 286 }
keir@20462 287
keir@20462 288 int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info *info,
keir@20462 289 uint32_t domid, int fd)
keir@20462 290 {
keir@20462 291 int hvm = 1;
keir@20462 292 int live = 0;
keir@20462 293 int debug = 0;
keir@20462 294 char savesig[] = "XenSavedDomain\n";
keir@20462 295
keir@20462 296 write(fd, savesig, strlen(savesig));
keir@20462 297
keir@20462 298 core_suspend(ctx, domid, fd, hvm, live, debug);
keir@20462 299
keir@20462 300 return 0;
keir@20462 301 }
keir@20462 302
keir@20462 303 int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 304 {
keir@20462 305 xc_domain_pause(ctx->xch, domid);
keir@20462 306 return 0;
keir@20462 307 }
keir@20462 308
keir@20462 309 int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 310 {
keir@20462 311 xc_domain_unpause(ctx->xch, domid);
keir@20462 312 return 0;
keir@20462 313 }
keir@20462 314
keir@20462 315 static char *req_table[] = {
keir@20462 316 [0] = "poweroff",
keir@20462 317 [1] = "reboot",
keir@20462 318 [2] = "suspend",
keir@20462 319 [3] = "crash",
keir@20462 320 [4] = "halt",
keir@20462 321 };
keir@20462 322
keir@20462 323 int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req)
keir@20462 324 {
keir@20462 325 char *shutdown_path;
keir@20462 326 char *dom_path;
keir@20462 327
keir@20462 328 if (req > ARRAY_SIZE(req_table))
keir@20462 329 return ERROR_INVAL;
keir@20462 330
keir@20462 331 dom_path = libxl_xs_get_dompath(ctx, domid);
keir@20512 332 if (!dom_path)
keir@20512 333 return ERROR_FAIL;
keir@20512 334
keir@20462 335 shutdown_path = libxl_sprintf(ctx, "%s/control/shutdown", dom_path);
keir@20462 336
keir@20462 337 xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], strlen(req_table[req]));
keir@20462 338 if (/* hvm */ 0) {
keir@20462 339 unsigned long acpi_s_state = 0;
keir@20462 340 unsigned long pvdriver = 0;
keir@20462 341 xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, &acpi_s_state);
keir@20462 342 xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
keir@20462 343 if (!pvdriver && acpi_s_state != 0)
keir@20462 344 xc_domain_shutdown(ctx->xch, domid, req);
keir@20462 345 }
keir@20462 346 return 0;
keir@20462 347 }
keir@20462 348
keir@20462 349 static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 350 {
keir@20462 351 char *pid;
keir@20462 352 int ret;
keir@20462 353
keir@20462 354 pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/image/device-model-pid", domid));
keir@20462 355 if (!pid) {
keir@20512 356 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't find device model's pid");
keir@20462 357 return -1;
keir@20462 358 }
keir@20462 359 xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", domid));
keir@20462 360
keir@20462 361 ret = kill(atoi(pid), SIGHUP);
keir@20462 362 if (ret < 0 && errno == ESRCH) {
keir@20512 363 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model already exited");
keir@20462 364 ret = 0;
keir@20462 365 } else if (ret == 0) {
keir@20512 366 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model signaled");
keir@20462 367 ret = 0;
keir@20462 368 } else {
keir@20512 369 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to kill Device Model [%d]",
keir@20512 370 atoi(pid));
keir@20462 371 }
keir@20462 372 return ret;
keir@20462 373 }
keir@20462 374
keir@20462 375 int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force)
keir@20462 376 {
keir@20462 377 char *dom_path, vm_path[41];
keir@20468 378 xen_uuid_t *uuid;
keir@20512 379 int rc;
keir@20462 380
keir@20462 381 dom_path = libxl_xs_get_dompath(ctx, domid);
keir@20512 382 if (!dom_path)
keir@20462 383 return -1;
keir@20512 384
keir@20462 385 if (libxl_domid_to_uuid(ctx, &uuid, domid) < 0) {
keir@20512 386 XL_LOG(ctx, XL_LOG_ERROR, "failed ot get uuid for %d", domid);
keir@20462 387 return -1;
keir@20462 388 }
keir@20482 389 if (libxl_device_pci_shutdown(ctx, domid) < 0)
keir@20512 390 XL_LOG(ctx, XL_LOG_ERROR, "pci shutdown failed for domid %d", domid);
keir@20462 391 xs_write(ctx->xsh, XBT_NULL,
keir@20462 392 libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid),
keir@20462 393 "shutdown", strlen("shutdown"));
keir@20512 394 rc = xc_domain_pause(ctx->xch, domid);
keir@20512 395 if (rc < 0) {
keir@20512 396 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_pause failed for %d", domid);
keir@20462 397 return -1;
keir@20462 398 }
keir@20512 399 rc = xc_domain_destroy(ctx->xch, domid);
keir@20512 400 if (rc < 0) {
keir@20512 401 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
keir@20462 402 return -1;
keir@20462 403 }
keir@20462 404 if (libxl_devices_destroy(ctx, domid, force) < 0)
keir@20512 405 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d", domid);
keir@20462 406 if (libxl_destroy_device_model(ctx, domid) < 0)
keir@20512 407 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_device_model failed for %d", domid);
keir@20462 408 if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
keir@20512 409 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", dom_path);
keir@20468 410 snprintf(vm_path, sizeof(vm_path), "/vm/%s", libxl_uuid_to_string(ctx, uuid));
keir@20462 411 if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
keir@20512 412 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vm_path);
keir@20462 413 return 0;
keir@20462 414 }
keir@20462 415
keir@20462 416 static char ** libxl_build_device_model_args(struct libxl_ctx *ctx,
keir@20462 417 libxl_device_model_info *info,
keir@20462 418 libxl_device_nic *vifs,
keir@20462 419 int num_vifs)
keir@20462 420 {
keir@20462 421 int num = 0, i;
keir@20462 422 flexarray_t *dm_args;
keir@20462 423 dm_args = flexarray_make(16, 1);
keir@20462 424 if (!dm_args)
keir@20462 425 return NULL;
keir@20462 426
keir@20462 427 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "qemu-dm"));
keir@20462 428 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-d"));
keir@20462 429
keir@20462 430 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->domid));
keir@20462 431
keir@20462 432 if (info->dom_name) {
keir@20462 433 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-domain-name"));
keir@20462 434 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->dom_name));
keir@20462 435 }
keir@20462 436 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
keir@20462 437 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-vnc"));
keir@20462 438 if (info->vncdisplay) {
keir@20462 439 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
keir@20462 440 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:%d", info->vnclisten, info->vncdisplay));
keir@20462 441 } else {
keir@20462 442 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "127.0.0.1:%d", info->vncdisplay));
keir@20462 443 }
keir@20462 444 } else if (info->vnclisten) {
keir@20462 445 if (strchr(info->vnclisten, ':') != NULL) {
keir@20462 446 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->vnclisten));
keir@20462 447 } else {
keir@20462 448 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:0", info->vnclisten));
keir@20462 449 }
keir@20462 450 } else {
keir@20462 451 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "127.0.0.1:0"));
keir@20462 452 }
keir@20462 453 if (info->vncunused) {
keir@20462 454 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-vncunused"));
keir@20462 455 }
keir@20462 456 }
keir@20462 457 if (info->sdl || info->opengl) {
keir@20462 458 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-sdl"));
keir@20462 459 if (info->opengl) {
keir@20462 460 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-disable-opengl"));
keir@20462 461 }
keir@20462 462 }
keir@20462 463 if (info->keymap) {
keir@20462 464 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-k"));
keir@20462 465 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->keymap));
keir@20462 466 }
keir@20462 467 if (info->nographic && (!info->sdl && !info->vnc)) {
keir@20462 468 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-nographic"));
keir@20462 469 }
keir@20462 470 if (info->serial) {
keir@20462 471 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-serial"));
keir@20462 472 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->serial));
keir@20462 473 }
keir@20509 474 if (info->type == XENFV) {
keir@20509 475 if (info->videoram) {
keir@20509 476 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-videoram"));
keir@20509 477 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->videoram));
keir@20509 478 }
keir@20509 479 if (info->stdvga) {
keir@20509 480 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-std-vga"));
keir@20509 481 }
keir@20509 482
keir@20509 483 if (info->boot) {
keir@20509 484 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-boot"));
keir@20509 485 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->boot));
keir@20509 486 }
keir@20509 487 if (info->usb) {
keir@20509 488 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-usb"));
keir@20509 489 if (info->usbdevice) {
keir@20509 490 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-usbdevice"));
keir@20509 491 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->usbdevice));
keir@20509 492 }
keir@20509 493 }
keir@20509 494 if (info->apic) {
keir@20509 495 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-acpi"));
keir@20509 496 }
keir@20509 497 for (i = 0; i < num_vifs; i++) {
keir@20509 498 if (vifs[i].nictype == NICTYPE_IOEMU) {
keir@20509 499 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-net"));
keir@20509 500 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "nic,vlan=%d,macaddr=%s,model=%s",
keir@20509 501 vifs[i].devid, vifs[i].smac, vifs[i].model));
keir@20509 502 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-net"));
keir@20509 503 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "tap,vlan=%d,ifname=%s,bridge=%s",
keir@20509 504 vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
keir@20509 505 }
keir@20462 506 }
keir@20462 507 }
keir@20509 508 for (i = 0; info->extra && info->extra[i] != NULL; i++)
keir@20509 509 flexarray_set(dm_args, num++, info->extra[i]);
keir@20462 510 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-M"));
keir@20509 511 if (info->type == XENPV)
keir@20509 512 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "xenpv"));
keir@20509 513 else
keir@20509 514 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "xenfv"));
keir@20462 515 flexarray_set(dm_args, num++, NULL);
keir@20462 516
keir@20462 517 return (char **) flexarray_contents(dm_args);
keir@20462 518 }
keir@20462 519
keir@20462 520 int libxl_create_device_model(struct libxl_ctx *ctx,
keir@20462 521 libxl_device_model_info *info,
keir@20462 522 libxl_device_nic *vifs, int num_vifs)
keir@20462 523 {
keir@20462 524 char *dom_path, *path, *logfile, *logfile_new;
keir@20462 525 char *kvs[3];
keir@20462 526 struct stat stat_buf;
keir@20462 527 int logfile_w, null, pid;
keir@20462 528 int i;
keir@20462 529 char **args;
keir@20462 530
keir@20462 531 args = libxl_build_device_model_args(ctx, info, vifs, num_vifs);
keir@20462 532 if (!args)
keir@20462 533 return ERROR_FAIL;
keir@20462 534
keir@20462 535 dom_path = libxl_xs_get_dompath(ctx, info->domid);
keir@20512 536 if (!dom_path)
keir@20512 537 return ERROR_FAIL;
keir@20462 538
keir@20462 539 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid);
keir@20462 540 xs_mkdir(ctx->xsh, XBT_NULL, path);
keir@20462 541
keir@20462 542 logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log", info->dom_name);
keir@20462 543 if (stat(logfile, &stat_buf) == 0) {
keir@20462 544 /* file exists, rotate */
keir@20462 545 logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.10", info->dom_name);
keir@20462 546 unlink(logfile);
keir@20462 547 for (i = 9; i > 0; i--) {
keir@20462 548 logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.%d", info->dom_name, i);
keir@20462 549 logfile_new = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.%d", info->dom_name, i + 1);
keir@20462 550 rename(logfile, logfile_new);
keir@20462 551 }
keir@20462 552 logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log", info->dom_name);
keir@20462 553 logfile_new = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.1", info->dom_name);
keir@20462 554 rename(logfile, logfile_new);
keir@20462 555 }
keir@20462 556 logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log", info->dom_name);
keir@20467 557 logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
keir@20462 558 null = open("/dev/null", O_RDONLY);
keir@20462 559 pid = libxl_exec(ctx, null, logfile_w, logfile_w, info->device_model, args);
keir@20462 560 close(null);
keir@20462 561 close(logfile_w);
keir@20462 562
keir@20462 563 kvs[0] = libxl_sprintf(ctx, "image/device-model-pid");
keir@20462 564 kvs[1] = libxl_sprintf(ctx, "%d", pid);
keir@20462 565 kvs[2] = NULL;
keir@20462 566 libxl_xs_writev(ctx, XBT_NULL, dom_path, kvs);
keir@20462 567
keir@20462 568 return 0;
keir@20462 569 }
keir@20462 570
keir@20462 571 /******************************************************************************/
keir@20462 572 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20462 573 {
keir@20462 574 flexarray_t *front;
keir@20462 575 flexarray_t *back;
keir@20462 576 char *backend_type;
keir@20462 577 unsigned int boffset = 0;
keir@20462 578 unsigned int foffset = 0;
keir@20462 579 int devid;
keir@20462 580 libxl_device device;
keir@20462 581
keir@20462 582 front = flexarray_make(16, 1);
keir@20462 583 if (!front)
keir@20462 584 return ERROR_NOMEM;
keir@20462 585 back = flexarray_make(16, 1);
keir@20462 586 if (!back) /* leaks front if error */
keir@20462 587 return ERROR_NOMEM;
keir@20462 588
keir@20462 589 backend_type = device_disk_backend_type_of_phystype(disk->phystype);
keir@20462 590 devid = device_disk_dev_number(disk->virtpath);
keir@20462 591
keir@20462 592 device.backend_devid = devid;
keir@20462 593 device.backend_domid = disk->backend_domid;
keir@20462 594 device.devid = devid;
keir@20462 595 device.domid = disk->domid;
keir@20462 596 device.kind = DEVICE_VBD;
keir@20462 597
keir@20462 598 switch (disk->phystype) {
keir@20462 599 case PHYSTYPE_FILE:
keir@20462 600 return ERROR_NI; /* FIXME */
keir@20462 601 break;
keir@20462 602 case PHYSTYPE_PHY: {
keir@20462 603 int major, minor;
keir@20462 604
keir@20509 605 device_physdisk_major_minor(disk->physpath, &major, &minor);
keir@20462 606 flexarray_set(back, boffset++, libxl_sprintf(ctx, "physical-device"));
keir@20462 607 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, minor));
keir@20462 608
keir@20462 609 flexarray_set(back, boffset++, libxl_sprintf(ctx, "params"));
keir@20462 610 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", disk->physpath));
keir@20462 611
keir@20462 612 device.backend_kind = DEVICE_VBD;
keir@20462 613 break;
keir@20462 614 }
keir@20462 615 case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD:
keir@20462 616 flexarray_set(back, boffset++, libxl_sprintf(ctx, "params"));
keir@20462 617 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s",
keir@20462 618 device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20462 619
keir@20462 620 device.backend_kind = DEVICE_TAP;
keir@20462 621 break;
keir@20462 622 }
keir@20462 623
keir@20462 624 flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
keir@20462 625 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", disk->domid));
keir@20462 626 flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
keir@20462 627 flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
keir@20462 628 flexarray_set(back, boffset++, libxl_sprintf(ctx, "removable"));
keir@20462 629 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", (disk->unpluggable) ? 1 : 0));
keir@20509 630 flexarray_set(back, boffset++, libxl_sprintf(ctx, "bootable"));
keir@20509 631 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20462 632 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
keir@20462 633 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20462 634 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev"));
keir@20462 635 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", disk->virtpath));
keir@20462 636 flexarray_set(back, boffset++, libxl_sprintf(ctx, "type"));
keir@20462 637 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", backend_type));
keir@20462 638 flexarray_set(back, boffset++, libxl_sprintf(ctx, "mode"));
keir@20462 639 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", (disk->readwrite) ? "w" : "r"));
keir@20462 640
keir@20462 641 flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
keir@20462 642 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", disk->backend_domid));
keir@20462 643 flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
keir@20462 644 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20462 645 flexarray_set(front, foffset++, libxl_sprintf(ctx, "virtual-device"));
keir@20462 646 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", devid));
keir@20462 647 flexarray_set(front, foffset++, libxl_sprintf(ctx, "device-type"));
keir@20462 648 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%s", (disk->is_cdrom) ? "cdrom" : "disk"));
keir@20462 649
keir@20462 650 if (0 /* protocol != native*/) {
keir@20462 651 flexarray_set(front, foffset++, libxl_sprintf(ctx, "protocol"));
keir@20462 652 flexarray_set(front, foffset++, libxl_sprintf(ctx, "x86_32-abi")); /* hardcoded ! */
keir@20462 653 }
keir@20462 654
keir@20462 655 libxl_device_generic_add(ctx, &device,
keir@20462 656 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20462 657 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20462 658 /* leaks both flexarray here */
keir@20462 659 return 0;
keir@20462 660 }
keir@20462 661
keir@20462 662 int libxl_device_disk_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 663 {
keir@20462 664 return ERROR_NI;
keir@20462 665 }
keir@20462 666
keir@20462 667 int libxl_device_disk_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 668 {
keir@20462 669 return ERROR_NI;
keir@20462 670 }
keir@20462 671
keir@20462 672 /******************************************************************************/
keir@20462 673 int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
keir@20462 674 {
keir@20462 675 flexarray_t *front;
keir@20462 676 flexarray_t *back;
keir@20462 677 unsigned int boffset = 0;
keir@20462 678 unsigned int foffset = 0;
keir@20462 679 libxl_device device;
keir@20462 680
keir@20462 681 front = flexarray_make(16, 1);
keir@20462 682 if (!front)
keir@20462 683 return ERROR_NOMEM;
keir@20462 684 back = flexarray_make(16, 1);
keir@20462 685 if (!back)
keir@20462 686 return ERROR_NOMEM;
keir@20462 687
keir@20462 688 device.backend_devid = nic->devid;
keir@20462 689 device.backend_domid = nic->backend_domid;
keir@20462 690 device.backend_kind = DEVICE_VIF;
keir@20462 691 device.devid = nic->devid;
keir@20462 692 device.domid = nic->domid;
keir@20462 693 device.kind = DEVICE_VIF;
keir@20462 694
keir@20462 695 flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
keir@20462 696 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->domid));
keir@20462 697 flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
keir@20462 698 flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
keir@20462 699 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
keir@20462 700 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20462 701 flexarray_set(back, boffset++, libxl_sprintf(ctx, "script"));
keir@20462 702 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", nic->script));
keir@20462 703 flexarray_set(back, boffset++, libxl_sprintf(ctx, "mac"));
keir@20462 704 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 705 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 706 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20462 707 flexarray_set(back, boffset++, libxl_sprintf(ctx, "handle"));
keir@20462 708 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->devid));
keir@20462 709
keir@20462 710 flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
keir@20462 711 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->backend_domid));
keir@20462 712 flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
keir@20462 713 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20462 714 flexarray_set(front, foffset++, libxl_sprintf(ctx, "handle"));
keir@20462 715 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->devid));
keir@20462 716 flexarray_set(front, foffset++, libxl_sprintf(ctx, "mac"));
keir@20462 717 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 718 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 719 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20462 720 if (0 /* protocol != native*/) {
keir@20462 721 flexarray_set(front, foffset++, libxl_sprintf(ctx, "protocol"));
keir@20462 722 flexarray_set(front, foffset++, libxl_sprintf(ctx, "x86_32-abi")); /* hardcoded ! */
keir@20462 723 }
keir@20462 724
keir@20462 725 libxl_device_generic_add(ctx, &device,
keir@20462 726 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20462 727 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20462 728
keir@20462 729 /* FIXME: wait for plug */
keir@20462 730 return 0;
keir@20462 731 }
keir@20462 732
keir@20462 733 int libxl_device_nic_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 734 {
keir@20462 735 return ERROR_NI;
keir@20462 736 }
keir@20462 737
keir@20462 738 int libxl_device_nic_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 739 {
keir@20462 740 return ERROR_NI;
keir@20462 741 }
keir@20462 742
keir@20462 743 /******************************************************************************/
keir@20509 744 int libxl_device_console_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
keir@20462 745 {
keir@20509 746 flexarray_t *front;
keir@20509 747 flexarray_t *back;
keir@20509 748 unsigned int boffset = 0;
keir@20509 749 unsigned int foffset = 0;
keir@20509 750 libxl_device device;
keir@20509 751
keir@20509 752 if (console->build_state) {
keir@20509 753 xs_transaction_t t;
keir@20509 754 char **ents = (char **) libxl_calloc(ctx, 9, sizeof(char *));
keir@20509 755 ents[0] = libxl_sprintf(ctx, "console/port");
keir@20509 756 ents[1] = libxl_sprintf(ctx, "%"PRIu32, console->build_state->console_port);
keir@20509 757 ents[2] = libxl_sprintf(ctx, "console/ring-ref");
keir@20509 758 ents[3] = libxl_sprintf(ctx, "%lu", console->build_state->console_mfn);
keir@20509 759 ents[4] = libxl_sprintf(ctx, "console/limit");
keir@20509 760 ents[5] = libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT);
keir@20509 761 ents[6] = libxl_sprintf(ctx, "console/type");
keir@20509 762 if (console->constype == CONSTYPE_XENCONSOLED)
keir@20509 763 ents[7] = "xenconsoled";
keir@20509 764 else
keir@20509 765 ents[7] = "ioemu";
keir@20509 766 retry_transaction:
keir@20509 767 t = xs_transaction_start(ctx->xsh);
keir@20509 768 libxl_xs_writev(ctx, t, xs_get_domain_path(ctx->xsh, console->domid), ents);
keir@20509 769 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20509 770 if (errno == EAGAIN)
keir@20509 771 goto retry_transaction;
keir@20509 772 }
keir@20509 773
keir@20509 774 front = flexarray_make(16, 1);
keir@20509 775 if (!front)
keir@20509 776 return ERROR_NOMEM;
keir@20509 777 back = flexarray_make(16, 1);
keir@20509 778 if (!back)
keir@20509 779 return ERROR_NOMEM;
keir@20509 780
keir@20509 781 device.backend_devid = console->devid;
keir@20509 782 device.backend_domid = console->backend_domid;
keir@20509 783 device.backend_kind = DEVICE_CONSOLE;
keir@20509 784 device.devid = console->devid;
keir@20509 785 device.domid = console->domid;
keir@20509 786 device.kind = DEVICE_CONSOLE;
keir@20509 787
keir@20509 788 flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
keir@20509 789 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", console->domid));
keir@20509 790 flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
keir@20509 791 flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
keir@20509 792 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
keir@20509 793 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 794 flexarray_set(back, boffset++, libxl_sprintf(ctx, "domain"));
keir@20509 795 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", libxl_domid_to_name(ctx, domid)));
keir@20509 796 flexarray_set(back, boffset++, libxl_sprintf(ctx, "protocol"));
keir@20509 797 flexarray_set(back, boffset++, libxl_sprintf(ctx, LIBXL_XENCONSOLE_PROTOCOL));
keir@20509 798
keir@20509 799 flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
keir@20509 800 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", console->backend_domid));
keir@20509 801 flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
keir@20509 802 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 803 flexarray_set(front, foffset++, libxl_sprintf(ctx, "limit"));
keir@20509 804 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT));
keir@20509 805 flexarray_set(front, foffset++, libxl_sprintf(ctx, "protocol"));
keir@20509 806 flexarray_set(front, foffset++, libxl_sprintf(ctx, LIBXL_XENCONSOLE_PROTOCOL));
keir@20509 807 flexarray_set(front, foffset++, libxl_sprintf(ctx, "type"));
keir@20509 808 if (console->constype == CONSTYPE_XENCONSOLED)
keir@20509 809 flexarray_set(front, foffset++, libxl_sprintf(ctx, "xenconsoled"));
keir@20509 810 else
keir@20509 811 flexarray_set(front, foffset++, libxl_sprintf(ctx, "ioemu"));
keir@20509 812
keir@20509 813 libxl_device_generic_add(ctx, &device,
keir@20509 814 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 815 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20509 816
keir@20509 817
keir@20509 818 return 0;
keir@20509 819 }
keir@20509 820
keir@20509 821 /******************************************************************************/
keir@20509 822 int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
keir@20509 823 {
keir@20509 824 flexarray_t *front;
keir@20509 825 flexarray_t *back;
keir@20509 826 unsigned int boffset = 0;
keir@20509 827 unsigned int foffset = 0;
keir@20509 828 libxl_device device;
keir@20509 829
keir@20509 830 front = flexarray_make(16, 1);
keir@20509 831 if (!front)
keir@20509 832 return ERROR_NOMEM;
keir@20509 833 back = flexarray_make(16, 1);
keir@20509 834 if (!back)
keir@20509 835 return ERROR_NOMEM;
keir@20509 836
keir@20509 837 device.backend_devid = vkb->devid;
keir@20509 838 device.backend_domid = vkb->backend_domid;
keir@20509 839 device.backend_kind = DEVICE_VKBD;
keir@20509 840 device.devid = vkb->devid;
keir@20509 841 device.domid = vkb->domid;
keir@20509 842 device.kind = DEVICE_VKBD;
keir@20509 843
keir@20509 844 flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
keir@20509 845 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vkb->domid));
keir@20509 846 flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
keir@20509 847 flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
keir@20509 848 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
keir@20509 849 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 850 flexarray_set(back, boffset++, libxl_sprintf(ctx, "domain"));
keir@20509 851 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", libxl_domid_to_name(ctx, domid)));
keir@20509 852
keir@20509 853 flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
keir@20509 854 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vkb->backend_domid));
keir@20509 855 flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
keir@20509 856 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 857
keir@20509 858 libxl_device_generic_add(ctx, &device,
keir@20509 859 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 860 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20509 861
keir@20509 862 return 0;
keir@20462 863 }
keir@20462 864
keir@20462 865 int libxl_device_vkb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 866 {
keir@20462 867 return ERROR_NI;
keir@20462 868 }
keir@20462 869
keir@20462 870 int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 871 {
keir@20462 872 return ERROR_NI;
keir@20462 873 }
keir@20462 874
keir@20462 875 /******************************************************************************/
keir@20509 876 static int libxl_build_xenpv_qemu_args(struct libxl_ctx *ctx,
keir@20509 877 libxl_device_vfb *vfb,
keir@20509 878 int num_console,
keir@20509 879 libxl_device_console *console,
keir@20509 880 libxl_device_model_info *info) {
keir@20509 881 int i = 0, j = 0, num = 0;
keir@20509 882 memset(info, 0x00, sizeof(libxl_device_model_info));
keir@20509 883
keir@20509 884 info->vnc = vfb->vnc;
keir@20509 885 if (vfb->vnclisten)
keir@20509 886 info->vnclisten = libxl_sprintf(ctx, "%s", vfb->vnclisten);
keir@20509 887 info->vncdisplay = vfb->vncdisplay;
keir@20509 888 info->vncunused = vfb->vncunused;
keir@20509 889 if (vfb->keymap)
keir@20509 890 info->keymap = libxl_sprintf(ctx, "%s", vfb->keymap);
keir@20509 891 info->sdl = vfb->sdl;
keir@20509 892 info->opengl = vfb->opengl;
keir@20509 893 for (i = 0; i < num_console; i++) {
keir@20509 894 if (console->constype == CONSTYPE_IOEMU)
keir@20509 895 num++;
keir@20509 896 }
keir@20509 897 if (num > 0) {
keir@20509 898 info->serial = "pty";
keir@20509 899 num--;
keir@20509 900 }
keir@20509 901 if (num > 0) {
keir@20509 902 info->extra = (char **) libxl_calloc(ctx, num * 2 + 1, sizeof(char *));
keir@20509 903 for (j = 0; j < num * 2; j = j + 2) {
keir@20509 904 info->extra[j] = "-serial";
keir@20509 905 info->extra[j + 1] = "pty";
keir@20509 906 }
keir@20509 907 info->extra[j] = NULL;
keir@20509 908 }
keir@20509 909 info->domid = vfb->domid;
keir@20509 910 info->dom_name = libxl_domid_to_name(ctx, vfb->domid);
keir@20509 911 info->device_model = "/usr/lib/xen/bin/qemu-dm";
keir@20509 912 info->type = XENPV;
keir@20509 913 return 0;
keir@20509 914 }
keir@20509 915
keir@20509 916 int libxl_create_xenpv_qemu(struct libxl_ctx *ctx, libxl_device_vfb *vfb,
keir@20509 917 int num_console, libxl_device_console *console)
keir@20509 918 {
keir@20509 919 libxl_device_model_info info;
keir@20509 920
keir@20509 921 libxl_build_xenpv_qemu_args(ctx, vfb, num_console, console, &info);
keir@20509 922 libxl_create_device_model(ctx, &info, NULL, 0);
keir@20509 923 return 0;
keir@20509 924 }
keir@20509 925
keir@20509 926 int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
keir@20462 927 {
keir@20509 928 flexarray_t *front;
keir@20509 929 flexarray_t *back;
keir@20509 930 unsigned int boffset = 0;
keir@20509 931 unsigned int foffset = 0;
keir@20509 932 libxl_device device;
keir@20509 933
keir@20509 934 front = flexarray_make(16, 1);
keir@20509 935 if (!front)
keir@20509 936 return ERROR_NOMEM;
keir@20509 937 back = flexarray_make(16, 1);
keir@20509 938 if (!back)
keir@20509 939 return ERROR_NOMEM;
keir@20509 940
keir@20509 941 device.backend_devid = vfb->devid;
keir@20509 942 device.backend_domid = vfb->backend_domid;
keir@20509 943 device.backend_kind = DEVICE_VFB;
keir@20509 944 device.devid = vfb->devid;
keir@20509 945 device.domid = vfb->domid;
keir@20509 946 device.kind = DEVICE_VFB;
keir@20509 947
keir@20509 948 flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
keir@20509 949 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->domid));
keir@20509 950 flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
keir@20509 951 flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
keir@20509 952 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
keir@20509 953 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 954 flexarray_set(back, boffset++, libxl_sprintf(ctx, "domain"));
keir@20509 955 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", libxl_domid_to_name(ctx, domid)));
keir@20509 956 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vnc"));
keir@20509 957 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vnc));
keir@20509 958 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vnclisten"));
keir@20509 959 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", vfb->vnclisten));
keir@20509 960 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vncdisplay"));
keir@20509 961 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncdisplay));
keir@20509 962 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vncunused"));
keir@20509 963 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncunused));
keir@20509 964 flexarray_set(back, boffset++, libxl_sprintf(ctx, "sdl"));
keir@20509 965 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->sdl));
keir@20509 966 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opengl"));
keir@20509 967 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->opengl));
keir@20509 968 if (vfb->xauthority) {
keir@20509 969 flexarray_set(back, boffset++, libxl_sprintf(ctx, "xauthority"));
keir@20509 970 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", vfb->xauthority));
keir@20509 971 }
keir@20509 972 if (vfb->display) {
keir@20509 973 flexarray_set(back, boffset++, libxl_sprintf(ctx, "display"));
keir@20509 974 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", vfb->display));
keir@20509 975 }
keir@20509 976
keir@20509 977 flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
keir@20509 978 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vfb->backend_domid));
keir@20509 979 flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
keir@20509 980 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20509 981
keir@20509 982 libxl_device_generic_add(ctx, &device,
keir@20509 983 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20509 984 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20509 985 flexarray_free(front);
keir@20509 986 flexarray_free(back);
keir@20509 987
keir@20509 988 return 0;
keir@20462 989 }
keir@20462 990
keir@20462 991 int libxl_device_vfb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 992 {
keir@20462 993 return ERROR_NI;
keir@20462 994 }
keir@20462 995
keir@20462 996 int libxl_device_vfb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 997 {
keir@20462 998 return ERROR_NI;
keir@20462 999 }
keir@20462 1000
keir@20462 1001 /******************************************************************************/
keir@20482 1002
keir@20482 1003 int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain,
keir@20482 1004 unsigned int bus, unsigned int dev,
keir@20482 1005 unsigned int func, unsigned int vdevfn)
keir@20482 1006 {
keir@20482 1007 pcidev->domain = domain;
keir@20482 1008 pcidev->bus = bus;
keir@20482 1009 pcidev->dev = dev;
keir@20482 1010 pcidev->func = func;
keir@20482 1011 pcidev->vdevfn = vdevfn;
keir@20482 1012 return 0;
keir@20482 1013 }
keir@20482 1014
keir@20482 1015 static int libxl_create_pci_backend(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev, int num)
keir@20482 1016 {
keir@20482 1017 flexarray_t *front;
keir@20482 1018 flexarray_t *back;
keir@20482 1019 unsigned int boffset = 0;
keir@20482 1020 unsigned int foffset = 0;
keir@20482 1021 libxl_device device;
keir@20482 1022 int i;
keir@20482 1023
keir@20482 1024 front = flexarray_make(16, 1);
keir@20482 1025 if (!front)
keir@20482 1026 return ERROR_NOMEM;
keir@20482 1027 back = flexarray_make(16, 1);
keir@20482 1028 if (!back)
keir@20482 1029 return ERROR_NOMEM;
keir@20482 1030
keir@20512 1031 XL_LOG(ctx, XL_LOG_DEBUG, "Creating pci backend");
keir@20482 1032
keir@20482 1033 /* add pci device */
keir@20482 1034 device.backend_devid = 0;
keir@20482 1035 device.backend_domid = 0;
keir@20482 1036 device.backend_kind = DEVICE_PCI;
keir@20482 1037 device.devid = 0;
keir@20482 1038 device.domid = domid;
keir@20482 1039 device.kind = DEVICE_PCI;
keir@20482 1040
keir@20482 1041 flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
keir@20482 1042 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", domid));
keir@20482 1043 flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
keir@20482 1044 flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
keir@20482 1045 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
keir@20482 1046 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20482 1047 flexarray_set(back, boffset++, libxl_sprintf(ctx, "domain"));
keir@20482 1048 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", libxl_domid_to_name(ctx, domid)));
keir@20482 1049 for (i = 0; i < num; i++) {
keir@20482 1050 flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", i));
keir@20482 1051 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 1052 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", i));
keir@20482 1053 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 1054 if (pcidev->vdevfn) {
keir@20482 1055 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", i));
keir@20482 1056 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", pcidev->vdevfn));
keir@20482 1057 }
keir@20482 1058 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", i));
keir@20482 1059 flexarray_set(back, boffset++, libxl_sprintf(ctx, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
keir@20482 1060 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", i));
keir@20482 1061 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20482 1062 }
keir@20482 1063 flexarray_set(back, boffset++, libxl_sprintf(ctx, "num_devs"));
keir@20482 1064 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num));
keir@20482 1065
keir@20482 1066 flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
keir@20482 1067 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 0));
keir@20482 1068 flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
keir@20482 1069 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20482 1070
keir@20482 1071 libxl_device_generic_add(ctx, &device,
keir@20482 1072 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20482 1073 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20482 1074
keir@20482 1075 flexarray_free(back);
keir@20482 1076 flexarray_free(front);
keir@20482 1077 return 0;
keir@20482 1078 }
keir@20482 1079
keir@20482 1080 static int libxl_device_pci_add_xenstore(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 1081 {
keir@20482 1082 flexarray_t *back;
keir@20482 1083 char *num_devs, *be_path;
keir@20482 1084 int num = 0;
keir@20482 1085 unsigned int boffset = 0;
keir@20482 1086 xs_transaction_t t;
keir@20482 1087
keir@20482 1088 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", xs_get_domain_path(ctx->xsh, 0), domid);
keir@20482 1089 num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", be_path));
keir@20482 1090 if (!num_devs)
keir@20482 1091 return libxl_create_pci_backend(ctx, domid, pcidev, 1);
keir@20482 1092
keir@20482 1093 if (!is_hvm(ctx, domid)) {
keir@20482 1094 if (libxl_wait_for_backend(ctx, be_path, "4") < 0)
keir@20482 1095 return -1;
keir@20482 1096 }
keir@20482 1097
keir@20482 1098 back = flexarray_make(16, 1);
keir@20482 1099 if (!back)
keir@20482 1100 return ERROR_NOMEM;
keir@20482 1101
keir@20512 1102 XL_LOG(ctx, XL_LOG_DEBUG, "Adding new pci device to xenstore");
keir@20482 1103 num = atoi(num_devs);
keir@20482 1104 flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", num));
keir@20482 1105 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 1106 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", num));
keir@20482 1107 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func));
keir@20482 1108 if (pcidev->vdevfn) {
keir@20482 1109 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", num));
keir@20482 1110 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", pcidev->vdevfn));
keir@20482 1111 }
keir@20482 1112 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", num));
keir@20482 1113 flexarray_set(back, boffset++, libxl_sprintf(ctx, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt));
keir@20482 1114 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", num));
keir@20482 1115 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20482 1116 flexarray_set(back, boffset++, libxl_sprintf(ctx, "num_devs"));
keir@20482 1117 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num + 1));
keir@20482 1118 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
keir@20482 1119 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 7));
keir@20482 1120
keir@20482 1121 retry_transaction:
keir@20482 1122 t = xs_transaction_start(ctx->xsh);
keir@20482 1123 libxl_xs_writev(ctx, t, be_path,
keir@20482 1124 libxl_xs_kvs_of_flexarray(ctx, back, boffset));
keir@20482 1125 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20482 1126 if (errno == EAGAIN)
keir@20482 1127 goto retry_transaction;
keir@20482 1128
keir@20482 1129 flexarray_free(back);
keir@20482 1130 return 0;
keir@20482 1131 }
keir@20482 1132
keir@20482 1133 static int libxl_device_pci_remove_xenstore(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20482 1134 {
keir@20482 1135 char *be_path, *num_devs_path, *num_devs, *xsdev;
keir@20482 1136 int num, i;
keir@20482 1137 xs_transaction_t t;
keir@20482 1138 unsigned int domain = 0, bus = 0, dev = 0, func = 0;
keir@20482 1139
keir@20482 1140 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", xs_get_domain_path(ctx->xsh, 0), domid);
keir@20482 1141 num_devs_path = libxl_sprintf(ctx, "%s/num_devs", be_path);
keir@20482 1142 num_devs = libxl_xs_read(ctx, XBT_NULL, num_devs_path);
keir@20482 1143 if (!num_devs)
keir@20482 1144 return -1;
keir@20482 1145 num = atoi(num_devs);
keir@20482 1146 if (num == 1) {
keir@20482 1147 libxl_device_destroy(ctx, be_path, 1);
keir@20482 1148 xs_rm(ctx->xsh, XBT_NULL, be_path);
keir@20482 1149 return 0;
keir@20482 1150 }
keir@20482 1151
keir@20482 1152 if (!is_hvm(ctx, domid)) {
keir@20482 1153 if (libxl_wait_for_backend(ctx, be_path, "4") < 0) {
keir@20512 1154 XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready");
keir@20482 1155 return -1;
keir@20482 1156 }
keir@20482 1157 }
keir@20482 1158
keir@20482 1159 for (i = 0; i < num; i++) {
keir@20482 1160 xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20482 1161 sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
keir@20482 1162 if (domain == pcidev->domain && bus == pcidev->bus &&
keir@20482 1163 pcidev->dev == dev && pcidev->func == func) {
keir@20482 1164 break;
keir@20482 1165 }
keir@20482 1166 }
keir@20482 1167 if (i == num) {
keir@20512 1168 XL_LOG(ctx, XL_LOG_ERROR, "Couldn't find the device on xenstore");
keir@20482 1169 return -1;
keir@20482 1170 }
keir@20482 1171
keir@20482 1172 retry_transaction:
keir@20482 1173 t = xs_transaction_start(ctx->xsh);
keir@20482 1174 libxl_xs_write(ctx, t, num_devs_path, "%d", num - 1);
keir@20482 1175 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i), "6", strlen("6"));
keir@20482 1176 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state", be_path), "7", strlen("7"));
keir@20482 1177 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20482 1178 if (errno == EAGAIN)
keir@20482 1179 goto retry_transaction;
keir@20482 1180 return 0;
keir@20462 1181 }
keir@20462 1182
keir@20482 1183 int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 1184 {
keir@20482 1185 char path[50];
keir@20482 1186 char *state, *vdevfn;
keir@20482 1187 int rc, hvm;
keir@20482 1188
keir@20482 1189 /* TODO: check if the device can be assigned */
keir@20482 1190
keir@20482 1191 libxl_device_pci_flr(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1192
keir@20482 1193 hvm = is_hvm(ctx, domid);
keir@20482 1194 if (hvm) {
keir@20482 1195 if (libxl_wait_for_device_model(ctx, domid, "running") < 0) {
keir@20482 1196 return -1;
keir@20482 1197 }
keir@20482 1198 snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/state", domid);
keir@20482 1199 state = libxl_xs_read(ctx, XBT_NULL, path);
keir@20482 1200 snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 1201 if (pcidev->vdevfn)
keir@20482 1202 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF_VDEVFN, pcidev->domain,
keir@20482 1203 pcidev->bus, pcidev->dev, pcidev->func, pcidev->vdevfn);
keir@20482 1204 else
keir@20482 1205 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
keir@20482 1206 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1207 snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/command", domid);
keir@20482 1208 xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins"));
keir@20482 1209 if (libxl_wait_for_device_model(ctx, domid, "pci-inserted") < 0)
keir@20512 1210 XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
keir@20482 1211 snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 1212 vdevfn = libxl_xs_read(ctx, XBT_NULL, path);
keir@20482 1213 sscanf(vdevfn + 2, "%x", &pcidev->vdevfn);
keir@20482 1214 snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/state", domid);
keir@20482 1215 xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
keir@20482 1216 } else {
keir@20482 1217 char *sysfs_path = libxl_sprintf(ctx, "SYSFS_PCI_DEV/"PCI_BDF"/resource", pcidev->domain,
keir@20482 1218 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1219 FILE *f = fopen(sysfs_path, "r");
keir@20482 1220 unsigned int start = 0, end = 0, flags = 0, size = 0;
keir@20482 1221 int irq = 0;
keir@20482 1222 int i;
keir@20482 1223
keir@20482 1224 if (f == NULL) {
keir@20512 1225 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 1226 return -1;
keir@20482 1227 }
keir@20482 1228 for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
keir@20512 1229 fscanf(f, "0x%x 0x%x 0x%x", &start, &end, &flags);
keir@20482 1230 size = end - start + 1;
keir@20482 1231 if (start) {
keir@20482 1232 if (flags & PCI_BAR_IO) {
keir@20482 1233 rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 1);
keir@20482 1234 if (rc < 0)
keir@20512 1235 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_ioport_permission error 0x%x/0x%x", start, size);
keir@20482 1236 } else {
keir@20482 1237 rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT,
keir@20482 1238 (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 1);
keir@20482 1239 if (rc < 0)
keir@20512 1240 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_iomem_permission error 0x%x/0x%x", start, size);
keir@20482 1241 }
keir@20482 1242 }
keir@20482 1243 }
keir@20482 1244 fclose(f);
keir@20482 1245 sysfs_path = libxl_sprintf(ctx, "SYSFS_PCI_DEV/"PCI_BDF"/irq", pcidev->domain,
keir@20482 1246 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1247 f = fopen(sysfs_path, "r");
keir@20482 1248 if (f == NULL) {
keir@20512 1249 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 1250 goto out;
keir@20482 1251 }
keir@20482 1252 fscanf(f, "%u", &irq);
keir@20482 1253 if (irq) {
keir@20482 1254 rc = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq);
keir@20482 1255 if (rc < 0) {
keir@20512 1256 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_physdev_map_pirq irq=%d", irq);
keir@20482 1257 }
keir@20482 1258 rc = xc_domain_irq_permission(ctx->xch, domid, irq, 1);
keir@20482 1259 if (rc < 0) {
keir@20512 1260 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_irq_permission irq=%d", irq);
keir@20482 1261 }
keir@20482 1262 }
keir@20482 1263 fclose(f);
keir@20482 1264 }
keir@20482 1265 out:
keir@20482 1266 if ((rc = xc_assign_device(ctx->xch, domid, pcidev->value)) < 0)
keir@20512 1267 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_assign_device failed");
keir@20482 1268
keir@20482 1269 libxl_device_pci_add_xenstore(ctx, domid, pcidev);
keir@20482 1270 return 0;
keir@20462 1271 }
keir@20462 1272
keir@20482 1273 int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev)
keir@20462 1274 {
keir@20482 1275 char path[50];
keir@20482 1276 char *state;
keir@20482 1277 int hvm, rc;
keir@20482 1278
keir@20482 1279 /* TODO: check if the device can be detached */
keir@20482 1280
keir@20482 1281 hvm = is_hvm(ctx, domid);
keir@20482 1282 if (hvm) {
keir@20482 1283 if (libxl_wait_for_device_model(ctx, domid, "running") < 0) {
keir@20482 1284 return -1;
keir@20482 1285 }
keir@20482 1286 snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/state", domid);
keir@20482 1287 state = libxl_xs_read(ctx, XBT_NULL, path);
keir@20482 1288 snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/parameter", domid);
keir@20482 1289 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain,
keir@20482 1290 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1291 snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/command", domid);
keir@20482 1292 xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem"));
keir@20482 1293 if (libxl_wait_for_device_model(ctx, domid, "pci-removed") < 0) {
keir@20512 1294 XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time");
keir@20482 1295 return -1;
keir@20482 1296 }
keir@20482 1297 snprintf(path, sizeof(path), "/local/domain/0/device-model/%d/state", domid);
keir@20482 1298 xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state));
keir@20482 1299 } else {
keir@20482 1300 char *sysfs_path = libxl_sprintf(ctx, "SYSFS_PCI_DEV/"PCI_BDF"/resource", pcidev->domain,
keir@20482 1301 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1302 FILE *f = fopen(sysfs_path, "r");
keir@20482 1303 unsigned int start = 0, end = 0, flags = 0, size = 0;
keir@20482 1304 int irq = 0;
keir@20482 1305 int i;
keir@20482 1306
keir@20482 1307 if (f == NULL) {
keir@20512 1308 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 1309 goto skip1;
keir@20482 1310 }
keir@20482 1311 for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) {
keir@20482 1312 fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags);
keir@20482 1313 size = end - start + 1;
keir@20482 1314 if (start) {
keir@20482 1315 if (flags & PCI_BAR_IO) {
keir@20482 1316 rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 0);
keir@20482 1317 if (rc < 0)
keir@20512 1318 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_ioport_permission error 0x%x/0x%x", start, size);
keir@20482 1319 } else {
keir@20482 1320 rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT,
keir@20482 1321 (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 0);
keir@20482 1322 if (rc < 0)
keir@20512 1323 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_iomem_permission error 0x%x/0x%x", start, size);
keir@20482 1324 }
keir@20482 1325 }
keir@20482 1326 }
keir@20482 1327 fclose(f);
keir@20482 1328 skip1:
keir@20482 1329 sysfs_path = libxl_sprintf(ctx, "SYSFS_PCI_DEV/"PCI_BDF"/irq", pcidev->domain,
keir@20482 1330 pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1331 f = fopen(sysfs_path, "r");
keir@20482 1332 if (f == NULL) {
keir@20512 1333 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path);
keir@20482 1334 goto out;
keir@20482 1335 }
keir@20482 1336 fscanf(f, "%u", &irq);
keir@20482 1337 if (irq) {
keir@20482 1338 rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq);
keir@20482 1339 if (rc < 0) {
keir@20512 1340 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_physdev_map_pirq irq=%d", irq);
keir@20482 1341 }
keir@20482 1342 rc = xc_domain_irq_permission(ctx->xch, domid, irq, 0);
keir@20482 1343 if (rc < 0) {
keir@20512 1344 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_irq_permission irq=%d", irq);
keir@20482 1345 }
keir@20482 1346 }
keir@20482 1347 fclose(f);
keir@20482 1348 }
keir@20482 1349 out:
keir@20482 1350 libxl_device_pci_remove_xenstore(ctx, domid, pcidev);
keir@20482 1351
keir@20482 1352 libxl_device_pci_flr(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
keir@20482 1353
keir@20482 1354 if ((rc = xc_deassign_device(ctx->xch, domid, pcidev->value)) < 0)
keir@20512 1355 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_deassign_device failed");
keir@20482 1356 return 0;
keir@20462 1357 }
keir@20482 1358
keir@20482 1359 libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t domid, int *num)
keir@20482 1360 {
keir@20482 1361 char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts;
keir@20482 1362 int n, i;
keir@20482 1363 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0;
keir@20482 1364 libxl_device_pci *pcidevs;
keir@20482 1365
keir@20482 1366 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", xs_get_domain_path(ctx->xsh, 0), domid);
keir@20482 1367 num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", be_path));
keir@20482 1368 if (!num_devs) {
keir@20482 1369 *num = 0;
keir@20482 1370 return NULL;
keir@20482 1371 }
keir@20482 1372 n = atoi(num_devs);
keir@20482 1373 pcidevs = (libxl_device_pci *) libxl_calloc(ctx, n, sizeof(libxl_device_pci));
keir@20482 1374 *num = n;
keir@20482 1375
keir@20482 1376 for (i = 0; i < n; i++) {
keir@20482 1377 xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", be_path, i));
keir@20482 1378 sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func);
keir@20482 1379 xsvdevfn = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i));
keir@20482 1380 if (xsvdevfn)
keir@20482 1381 vdevfn = strtol(xsvdevfn, (char **) NULL, 16);
keir@20482 1382 libxl_device_pci_init(pcidevs + i, domain, bus, dev, func, vdevfn);
keir@20482 1383 xsopts = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/opts-%d", be_path, i));
keir@20482 1384 if (xsopts) {
keir@20482 1385 char *saveptr;
keir@20482 1386 char *p = strtok_r(xsopts, ",=", &saveptr);
keir@20482 1387 do {
keir@20482 1388 while (*p == ' ')
keir@20482 1389 p++;
keir@20482 1390 if (!strcmp(p, "msitranslate")) {
keir@20482 1391 p = strtok_r(NULL, ",=", &saveptr);
keir@20482 1392 pcidevs[i].msitranslate = atoi(p);
keir@20482 1393 } else if (!strcmp(p, "power_mgmt")) {
keir@20482 1394 p = strtok_r(NULL, ",=", &saveptr);
keir@20482 1395 pcidevs[i].power_mgmt = atoi(p);
keir@20482 1396 }
keir@20482 1397 } while ((p = strtok_r(NULL, ",=", &saveptr)) != NULL);
keir@20482 1398 }
keir@20482 1399 }
keir@20482 1400 return pcidevs;
keir@20482 1401 }
keir@20482 1402
keir@20482 1403 int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20482 1404 {
keir@20482 1405 libxl_device_pci *pcidevs;
keir@20482 1406 int num, i;
keir@20482 1407
keir@20482 1408 pcidevs = libxl_device_pci_list(ctx, domid, &num);
keir@20482 1409 for (i = 0; i < num; i++) {
keir@20482 1410 if (libxl_device_pci_remove(ctx, domid, pcidevs + i) < 0)
keir@20482 1411 return -1;
keir@20482 1412 }
keir@20482 1413 return 0;
keir@20482 1414 }
keir@20482 1415