debuggers.hg

annotate tools/libxl/libxl.c @ 20513:20063cea1606

libxenlight: correct broken osdeps.[ch] and make #includes consistent

osdeps.[hc] previously mistakenly declared and defined [v]asprintf.
These functions are available in the libc on most platforms. Also,
osdeps.h is used by xc.c but xc.c is not part of the library, so
osdeps.h is part of the public interface and should have a better
name.

So now, instead:

* osdeps.h is libxl_osdeps.h.

* _GNU_SOURCE is #defined in libxl_osdeps.h so that we get the system
[v]asprintf (and various other functions)

* libxl_osdeps.h is included first in every libxl*.c file (it needs
to be before any system headers so that _GNU_SOURCE) takes effect.

* osdeps.[hc] only provide their own reimplementation of [v]asprintf
if NEED_OWN_ASPRINTF is defined. Currently it is not ever defined
but this is provided for any platform which needs it.

* While I was editing the #includes in each .c file, I put them all
into the same order: "libxl_osdeps.h", then system headers,
then local headers.

* xs.h is included in libxl.h. This is needed for "bool"; it has to
not be typedefed in libxl.h because otherwise we get a duplicate
definition when including xs.h.

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