debuggers.hg

annotate tools/libxl/libxl.c @ 20632:e0351b16a747

libxenlight: physmap slack for pv domains

Contemplate a memory space slack for PV domains,
since they do ballooning (or flipping network rx)
and need some extra room in their pfn space.

Note that this does not allocate any extra memory
to the domain, it simply extends the physmap with
some extra room for "bounce bufffering back" pfn's
that are yielded to dom0.

The default slack is set at 8MB.

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