debuggers.hg

annotate tools/libxl/libxl.c @ 20566:5b724b482f37

libxenlight: implement blktap2 support

This patch implements blktap2 support in libxenlight; blktap2 is only
enabled if it is actually supported by the host, otherwise we fall
back to the previous code. Also for the moment we pretend that disk
type file is actually tap:aio.

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