debuggers.hg

annotate tools/libxl/libxl.c @ 20509:014579af0350

libxenlight: implement support for pv guests

This patch makes pv guest work correctly with libxenlight. It also
implements support for vfb and vkbd, starting qemu in xenpv mode. Both
xenconsole and qemu are supported as console backends.

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