debuggers.hg
annotate tools/libxl/libxl.c @ 21849:cb1ca77e4b77
libxl: add function to attach/detach a disk to/from the local VM
Useful if you need to read a guest filesystem (e.g. pygrub).
I'm not overly thrilled with the implementation WRT tap interfaces,
particularly WRT to detach. I was unable to find a way to get at the
paramters necessary to call tap_ctl_destroy so I assumed for now it
that is OK to assume that the tap device is going to be wanted for the
actual domain at some point in the immediate future and hence there is
no pressing need to destroy it.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Useful if you need to read a guest filesystem (e.g. pygrub).
I'm not overly thrilled with the implementation WRT tap interfaces,
particularly WRT to detach. I was unable to find a way to get at the
paramters necessary to call tap_ctl_destroy so I assumed for now it
that is OK to assume that the tap device is going to be wanted for the
actual domain at some point in the immediate future and hence there is
no pressing need to destroy it.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author | Ian Jackson <Ian.Jackson@eu.citrix.com> |
---|---|
date | Wed Jul 14 16:44:18 2010 +0100 (2010-07-14) |
parents | df18254561b2 |
children | 3e5baecab949 |
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> |
Ian@21848 | 25 #include <sys/mman.h> |
keir@20514 | 26 #include <sys/wait.h> |
keir@20462 | 27 #include <signal.h> |
keir@20468 | 28 #include <unistd.h> /* for write, unlink and close */ |
keir@20509 | 29 #include <stdint.h> |
keir@20509 | 30 #include <inttypes.h> |
keir@20514 | 31 #include <assert.h> |
keir@20513 | 32 |
keir@20462 | 33 #include "libxl.h" |
keir@20462 | 34 #include "libxl_utils.h" |
keir@20462 | 35 #include "libxl_internal.h" |
keir@20462 | 36 #include "flexarray.h" |
keir@21632 | 37 #include "tap-ctl.h" |
keir@20462 | 38 |
keir@20860 | 39 #define PAGE_TO_MEMKB(pages) ((pages) * 4) |
keir@20860 | 40 |
keir@21532 | 41 int libxl_ctx_init(struct libxl_ctx *ctx, int version, xentoollog_logger *lg) |
keir@20462 | 42 { |
keir@20788 | 43 if (version != LIBXL_VERSION) |
keir@20788 | 44 return ERROR_VERSION; |
keir@20462 | 45 memset(ctx, 0, sizeof(struct libxl_ctx)); |
keir@21532 | 46 ctx->lg = lg; |
keir@20462 | 47 ctx->alloc_maxsize = 256; |
keir@20462 | 48 ctx->alloc_ptrs = calloc(ctx->alloc_maxsize, sizeof(void *)); |
keir@20462 | 49 if (!ctx->alloc_ptrs) |
keir@20462 | 50 return ERROR_NOMEM; |
keir@21266 | 51 memset(&ctx->version_info, 0, sizeof(libxl_version_info)); |
keir@20462 | 52 |
keir@21532 | 53 ctx->xch = xc_interface_open(lg,lg,0); |
keir@21529 | 54 if (!ctx->xch) { |
keir@21681 | 55 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, |
keir@21681 | 56 "cannot open libxc handle"); |
keir@20819 | 57 free(ctx->alloc_ptrs); |
keir@20819 | 58 return ERROR_FAIL; |
keir@20819 | 59 } |
keir@20819 | 60 |
keir@20462 | 61 ctx->xsh = xs_daemon_open(); |
keir@20819 | 62 if (!ctx->xsh) { |
keir@21681 | 63 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, |
keir@21681 | 64 "cannot connect to xenstore"); |
keir@20819 | 65 xc_interface_close(ctx->xch); |
keir@20819 | 66 free(ctx->alloc_ptrs); |
keir@20819 | 67 return ERROR_FAIL; |
keir@20819 | 68 } |
keir@20462 | 69 return 0; |
keir@20462 | 70 } |
keir@20462 | 71 |
keir@20462 | 72 int libxl_ctx_free(struct libxl_ctx *ctx) |
keir@20462 | 73 { |
keir@20462 | 74 libxl_free_all(ctx); |
keir@20462 | 75 free(ctx->alloc_ptrs); |
keir@20462 | 76 xc_interface_close(ctx->xch); |
keir@21186 | 77 if (ctx->xsh) xs_daemon_close(ctx->xsh); |
keir@20462 | 78 return 0; |
keir@20462 | 79 } |
keir@20462 | 80 |
keir@20462 | 81 /******************************************************************************/ |
keir@20462 | 82 |
keir@20462 | 83 int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info, |
keir@20462 | 84 uint32_t *domid) |
keir@20462 | 85 { |
keir@21184 | 86 int flags, ret, i, rc; |
keir@20468 | 87 char *uuid_string; |
keir@20646 | 88 char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"}; |
keir@20462 | 89 char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers", |
keir@20646 | 90 "control", "attr", "messages" }; |
keir@20462 | 91 char *dom_path, *vm_path, *vss_path; |
keir@20462 | 92 struct xs_permissions roperm[2]; |
keir@20462 | 93 struct xs_permissions rwperm[1]; |
keir@20462 | 94 xs_transaction_t t; |
keir@20468 | 95 xen_domain_handle_t handle; |
keir@20462 | 96 |
keir@21188 | 97 uuid_string = libxl_uuid2string(ctx, info->uuid); |
keir@21188 | 98 if (!uuid_string) return ERROR_NOMEM; |
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@21274 | 102 flags |= info->oos ? 0 : XEN_DOMCTL_CDF_oos_off; |
keir@20824 | 103 *domid = -1; |
keir@20462 | 104 |
keir@20580 | 105 /* Ultimately, handle is an array of 16 uint8_t, same as uuid */ |
keir@20580 | 106 memcpy(handle, info->uuid, sizeof(xen_domain_handle_t)); |
keir@20468 | 107 |
keir@20468 | 108 ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid); |
keir@20462 | 109 if (ret < 0) { |
keir@20512 | 110 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain creation fail"); |
keir@20462 | 111 return ERROR_FAIL; |
keir@20462 | 112 } |
keir@20462 | 113 |
keir@21368 | 114 ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid); |
keir@21368 | 115 if (ret < 0) { |
keir@21368 | 116 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain move fail"); |
keir@21368 | 117 return ERROR_FAIL; |
keir@21368 | 118 } |
keir@21368 | 119 |
keir@20462 | 120 dom_path = libxl_xs_get_dompath(ctx, *domid); |
keir@20512 | 121 if (!dom_path) |
keir@20512 | 122 return ERROR_FAIL; |
keir@20512 | 123 |
keir@20462 | 124 vm_path = libxl_sprintf(ctx, "/vm/%s", uuid_string); |
keir@20462 | 125 vss_path = libxl_sprintf(ctx, "/vss/%s", uuid_string); |
keir@20512 | 126 if (!vm_path || !vss_path) { |
keir@20462 | 127 XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate create paths"); |
keir@20462 | 128 return ERROR_FAIL; |
keir@20462 | 129 } |
keir@20462 | 130 |
keir@20462 | 131 roperm[0].id = 0; |
keir@20462 | 132 roperm[0].perms = XS_PERM_NONE; |
keir@20462 | 133 roperm[1].id = *domid; |
keir@20462 | 134 roperm[1].perms = XS_PERM_READ; |
keir@20462 | 135 rwperm[0].id = *domid; |
keir@20462 | 136 rwperm[0].perms = XS_PERM_NONE; |
keir@20462 | 137 |
keir@20462 | 138 retry_transaction: |
keir@20462 | 139 t = xs_transaction_start(ctx->xsh); |
keir@20462 | 140 xs_rm(ctx->xsh, t, dom_path); |
keir@20462 | 141 xs_mkdir(ctx->xsh, t, dom_path); |
keir@20462 | 142 xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm)); |
keir@20462 | 143 |
keir@20462 | 144 xs_rm(ctx->xsh, t, vm_path); |
keir@20462 | 145 xs_mkdir(ctx->xsh, t, vm_path); |
keir@20462 | 146 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm)); |
keir@20462 | 147 |
keir@20462 | 148 xs_rm(ctx->xsh, t, vss_path); |
keir@20462 | 149 xs_mkdir(ctx->xsh, t, vss_path); |
keir@20462 | 150 xs_set_permissions(ctx->xsh, t, vss_path, rwperm, ARRAY_SIZE(rwperm)); |
keir@20462 | 151 |
keir@20462 | 152 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vm", dom_path), vm_path, strlen(vm_path)); |
keir@20462 | 153 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vss", dom_path), vss_path, strlen(vss_path)); |
keir@21184 | 154 rc = libxl_domain_rename(ctx, *domid, 0, info->name, t); |
keir@21184 | 155 if (rc) return rc; |
keir@20462 | 156 |
keir@20462 | 157 for (i = 0; i < ARRAY_SIZE(rw_paths); i++) { |
keir@20462 | 158 char *path = libxl_sprintf(ctx, "%s/%s", dom_path, rw_paths[i]); |
keir@20462 | 159 xs_mkdir(ctx->xsh, t, path); |
keir@20462 | 160 xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm)); |
keir@20462 | 161 libxl_free(ctx, path); |
keir@20462 | 162 } |
keir@20462 | 163 for (i = 0; i < ARRAY_SIZE(ro_paths); i++) { |
keir@20462 | 164 char *path = libxl_sprintf(ctx, "%s/%s", dom_path, ro_paths[i]); |
keir@20462 | 165 xs_mkdir(ctx->xsh, t, path); |
keir@20462 | 166 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm)); |
keir@20462 | 167 libxl_free(ctx, path); |
keir@20462 | 168 } |
keir@20462 | 169 |
keir@20462 | 170 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/uuid", vm_path), uuid_string, strlen(uuid_string)); |
keir@20462 | 171 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", vm_path), info->name, strlen(info->name)); |
keir@21389 | 172 if (info->poolname) |
keir@21389 | 173 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/pool_name", vm_path), info->poolname, strlen(info->poolname)); |
keir@20462 | 174 |
keir@20462 | 175 libxl_xs_writev(ctx, t, dom_path, info->xsdata); |
keir@20462 | 176 libxl_xs_writev(ctx, t, libxl_sprintf(ctx, "%s/platform", dom_path), info->platformdata); |
keir@20462 | 177 |
keir@20462 | 178 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1); |
keir@20462 | 179 |
keir@20462 | 180 if (!xs_transaction_end(ctx->xsh, t, 0)) |
keir@20462 | 181 if (errno == EAGAIN) |
keir@20462 | 182 goto retry_transaction; |
keir@20462 | 183 return 0; |
keir@20462 | 184 } |
keir@20462 | 185 |
keir@21184 | 186 int libxl_domain_rename(struct libxl_ctx *ctx, uint32_t domid, |
keir@21184 | 187 const char *old_name, const char *new_name, |
keir@21184 | 188 xs_transaction_t trans) { |
keir@21184 | 189 char *dom_path = 0; |
keir@21184 | 190 const char *name_path; |
keir@21184 | 191 char *got_old_name; |
keir@21184 | 192 unsigned int got_old_len; |
keir@21184 | 193 xs_transaction_t our_trans = 0; |
keir@21184 | 194 int rc; |
keir@21184 | 195 |
keir@21184 | 196 dom_path = libxl_xs_get_dompath(ctx, domid); |
keir@21184 | 197 if (!dom_path) goto x_nomem; |
keir@21184 | 198 |
keir@21184 | 199 name_path= libxl_sprintf(ctx, "%s/name", dom_path); |
keir@21184 | 200 if (!name_path) goto x_nomem; |
keir@21184 | 201 |
keir@21184 | 202 retry_transaction: |
keir@21184 | 203 if (!trans) { |
keir@21184 | 204 trans = our_trans = xs_transaction_start(ctx->xsh); |
keir@21184 | 205 if (!our_trans) { |
keir@21184 | 206 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, |
keir@21184 | 207 "create xs transaction for domain (re)name"); |
keir@21184 | 208 goto x_fail; |
keir@21184 | 209 } |
keir@21184 | 210 } |
keir@21184 | 211 |
keir@21184 | 212 if (old_name) { |
keir@21184 | 213 got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len); |
keir@21184 | 214 if (!got_old_name) { |
keir@21184 | 215 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, "check old name" |
keir@21184 | 216 " for domain %"PRIu32" allegedly named `%s'", |
keir@21184 | 217 domid, old_name); |
keir@21184 | 218 goto x_fail; |
keir@21184 | 219 } |
keir@21184 | 220 if (strcmp(old_name, got_old_name)) { |
keir@21184 | 221 XL_LOG(ctx, XL_LOG_ERROR, "domain %"PRIu32" allegedly named " |
keir@21184 | 222 "`%s' is actually named `%s' - racing ?", |
keir@21184 | 223 domid, old_name, got_old_name); |
keir@21184 | 224 free(got_old_name); |
keir@21184 | 225 goto x_fail; |
keir@21184 | 226 } |
keir@21184 | 227 free(got_old_name); |
keir@21184 | 228 } |
keir@21184 | 229 if (!xs_write(ctx->xsh, trans, name_path, |
keir@21184 | 230 new_name, strlen(new_name))) { |
keir@21184 | 231 XL_LOG(ctx, XL_LOG_ERROR, "failed to write new name `%s'" |
keir@21184 | 232 " for domain %"PRIu32" previously named `%s'", |
keir@21531 | 233 new_name, domid, old_name); |
keir@21184 | 234 goto x_fail; |
keir@21184 | 235 } |
keir@21184 | 236 |
keir@21184 | 237 if (our_trans) { |
keir@21184 | 238 if (!xs_transaction_end(ctx->xsh, our_trans, 0)) { |
keir@21184 | 239 trans = our_trans = 0; |
keir@21184 | 240 if (errno != EAGAIN) { |
keir@21184 | 241 XL_LOG(ctx, XL_LOG_ERROR, "failed to commit new name `%s'" |
keir@21184 | 242 " for domain %"PRIu32" previously named `%s'", |
keir@21531 | 243 new_name, domid, old_name); |
keir@21184 | 244 goto x_fail; |
keir@21184 | 245 } |
keir@21184 | 246 XL_LOG(ctx, XL_LOG_DEBUG, "need to retry rename transaction" |
keir@21184 | 247 " for domain %"PRIu32" (name_path=\"%s\", new_name=\"%s\")", |
keir@21184 | 248 domid, name_path, new_name); |
keir@21184 | 249 goto retry_transaction; |
keir@21184 | 250 } |
keir@21184 | 251 our_trans = 0; |
keir@21184 | 252 } |
keir@21184 | 253 |
keir@21184 | 254 rc = 0; |
keir@21184 | 255 x_rc: |
keir@21184 | 256 if (dom_path) libxl_free(ctx, dom_path); |
keir@21184 | 257 if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1); |
keir@21184 | 258 return rc; |
keir@21184 | 259 |
keir@21184 | 260 x_fail: rc = ERROR_FAIL; goto x_rc; |
keir@21184 | 261 x_nomem: rc = ERROR_NOMEM; goto x_rc; |
keir@21184 | 262 } |
keir@21184 | 263 |
keir@20516 | 264 int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, libxl_domain_build_state *state) |
keir@20462 | 265 { |
keir@20462 | 266 char **vments = NULL, **localents = NULL; |
keir@21438 | 267 struct timeval start_time; |
keir@20829 | 268 int i, ret; |
keir@20829 | 269 |
keir@20829 | 270 ret = build_pre(ctx, domid, info, state); |
keir@20829 | 271 if (ret) goto out; |
keir@20462 | 272 |
keir@21438 | 273 gettimeofday(&start_time, NULL); |
keir@21438 | 274 |
keir@20462 | 275 if (info->hvm) { |
keir@20829 | 276 ret = build_hvm(ctx, domid, info, state); |
keir@20829 | 277 if (ret) goto out; |
keir@20829 | 278 |
keir@21438 | 279 vments = libxl_calloc(ctx, 7, sizeof(char *)); |
keir@20516 | 280 vments[0] = "rtc/timeoffset"; |
keir@20516 | 281 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : ""; |
keir@20516 | 282 vments[2] = "image/ostype"; |
keir@20516 | 283 vments[3] = "hvm"; |
keir@21438 | 284 vments[4] = "start_time"; |
keir@21438 | 285 vments[5] = libxl_sprintf(ctx, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); |
keir@20462 | 286 } else { |
keir@20829 | 287 ret = build_pv(ctx, domid, info, state); |
keir@20829 | 288 if (ret) goto out; |
keir@20829 | 289 |
keir@21438 | 290 vments = libxl_calloc(ctx, 11, sizeof(char *)); |
keir@20578 | 291 i = 0; |
keir@20578 | 292 vments[i++] = "image/ostype"; |
keir@20578 | 293 vments[i++] = "linux"; |
keir@20578 | 294 vments[i++] = "image/kernel"; |
Ian@21848 | 295 vments[i++] = (char*) info->kernel.path; |
keir@21438 | 296 vments[i++] = "start_time"; |
keir@21438 | 297 vments[i++] = libxl_sprintf(ctx, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); |
Ian@21848 | 298 if (info->u.pv.ramdisk.path) { |
keir@20578 | 299 vments[i++] = "image/ramdisk"; |
Ian@21848 | 300 vments[i++] = (char*) info->u.pv.ramdisk.path; |
keir@20578 | 301 } |
keir@20578 | 302 if (info->u.pv.cmdline) { |
keir@20578 | 303 vments[i++] = "image/cmdline"; |
keir@20578 | 304 vments[i++] = (char*) info->u.pv.cmdline; |
keir@20578 | 305 } |
keir@20462 | 306 } |
keir@20829 | 307 ret = build_post(ctx, domid, info, state, vments, localents); |
keir@20829 | 308 out: |
Ian@21848 | 309 libxl_file_reference_unmap(ctx, &info->kernel); |
Ian@21848 | 310 if (!info->hvm) |
Ian@21848 | 311 libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk); |
Ian@21848 | 312 |
keir@20829 | 313 return ret; |
keir@20462 | 314 } |
keir@20462 | 315 |
keir@20462 | 316 int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info, |
keir@20565 | 317 uint32_t domid, int fd, libxl_domain_build_state *state, |
keir@20565 | 318 libxl_device_model_info *dm_info) |
keir@20462 | 319 { |
keir@20462 | 320 char **vments = NULL, **localents = NULL; |
keir@21438 | 321 struct timeval start_time; |
keir@21183 | 322 int i, ret, esave, flags; |
keir@20462 | 323 |
keir@20829 | 324 ret = build_pre(ctx, domid, info, state); |
keir@20829 | 325 if (ret) goto out; |
keir@20829 | 326 |
keir@20829 | 327 ret = restore_common(ctx, domid, info, state, fd); |
keir@20829 | 328 if (ret) goto out; |
keir@20829 | 329 |
keir@21438 | 330 gettimeofday(&start_time, NULL); |
keir@21438 | 331 |
keir@20462 | 332 if (info->hvm) { |
keir@21438 | 333 vments = libxl_calloc(ctx, 7, sizeof(char *)); |
keir@20516 | 334 vments[0] = "rtc/timeoffset"; |
keir@20516 | 335 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : ""; |
keir@20565 | 336 vments[2] = "image/ostype"; |
keir@20565 | 337 vments[3] = "hvm"; |
keir@21438 | 338 vments[4] = "start_time"; |
keir@21438 | 339 vments[5] = libxl_sprintf(ctx, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); |
keir@20462 | 340 } else { |
keir@21438 | 341 vments = libxl_calloc(ctx, 11, sizeof(char *)); |
keir@20627 | 342 i = 0; |
keir@20627 | 343 vments[i++] = "image/ostype"; |
keir@20627 | 344 vments[i++] = "linux"; |
keir@20627 | 345 vments[i++] = "image/kernel"; |
Ian@21848 | 346 vments[i++] = (char*) info->kernel.path; |
keir@21438 | 347 vments[i++] = "start_time"; |
keir@21438 | 348 vments[i++] = libxl_sprintf(ctx, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000); |
Ian@21848 | 349 if (info->u.pv.ramdisk.path) { |
keir@20627 | 350 vments[i++] = "image/ramdisk"; |
Ian@21848 | 351 vments[i++] = (char*) info->u.pv.ramdisk.path; |
keir@20627 | 352 } |
keir@20627 | 353 if (info->u.pv.cmdline) { |
keir@20627 | 354 vments[i++] = "image/cmdline"; |
keir@20627 | 355 vments[i++] = (char*) info->u.pv.cmdline; |
keir@20627 | 356 } |
keir@20462 | 357 } |
keir@20829 | 358 ret = build_post(ctx, domid, info, state, vments, localents); |
keir@20829 | 359 if (ret) goto out; |
keir@20829 | 360 |
keir@21417 | 361 dm_info->saved_state = NULL; |
keir@21417 | 362 if (info->hvm) { |
keir@21417 | 363 ret = asprintf(&dm_info->saved_state, |
keir@21417 | 364 "/var/lib/xen/qemu-save.%d", domid); |
keir@21417 | 365 ret = (ret < 0) ? ERROR_FAIL : 0; |
keir@21417 | 366 } |
keir@21417 | 367 |
keir@20829 | 368 out: |
Ian@21848 | 369 libxl_file_reference_unmap(ctx, &info->kernel); |
Ian@21848 | 370 if (!info->hvm) |
Ian@21848 | 371 libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk); |
Ian@21848 | 372 |
keir@21183 | 373 esave = errno; |
keir@21183 | 374 |
keir@21183 | 375 flags = fcntl(fd, F_GETFL); |
keir@21183 | 376 if (flags == -1) { |
keir@21183 | 377 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to get flags on restore fd"); |
keir@21183 | 378 } else { |
keir@21183 | 379 flags &= ~O_NONBLOCK; |
keir@21183 | 380 if (fcntl(fd, F_SETFL, flags) == -1) |
keir@21183 | 381 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to put restore fd" |
keir@21183 | 382 " back to blocking mode"); |
keir@21183 | 383 } |
keir@21183 | 384 |
keir@21183 | 385 errno = esave; |
keir@20829 | 386 return ret; |
keir@20462 | 387 } |
keir@20462 | 388 |
keir@20629 | 389 int libxl_domain_resume(struct libxl_ctx *ctx, uint32_t domid) |
keir@20629 | 390 { |
keir@20629 | 391 if (is_hvm(ctx, domid)) { |
keir@20629 | 392 XL_LOG(ctx, XL_LOG_DEBUG, "Called domain_resume on " |
keir@20629 | 393 "non-cooperative hvm domain %u", domid); |
keir@20629 | 394 return ERROR_NI; |
keir@20629 | 395 } |
keir@20629 | 396 if (xc_domain_resume(ctx->xch, domid, 1)) { |
keir@20629 | 397 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, |
keir@20629 | 398 "xc_domain_resume failed for domain %u", |
keir@20629 | 399 domid); |
keir@20629 | 400 return ERROR_FAIL; |
keir@20629 | 401 } |
keir@20629 | 402 if (!xs_resume_domain(ctx->xsh, domid)) { |
keir@20629 | 403 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, |
keir@20629 | 404 "xs_resume_domain failed for domain %u", |
keir@20629 | 405 domid); |
keir@20629 | 406 return ERROR_FAIL; |
keir@20629 | 407 } |
keir@20629 | 408 return 0; |
keir@20629 | 409 } |
keir@20629 | 410 |
keir@21189 | 411 static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo, |
keir@21189 | 412 struct libxl_dominfo *xlinfo) { |
keir@21189 | 413 memcpy(&(xlinfo->uuid), xcinfo->handle, sizeof(xen_domain_handle_t)); |
keir@21189 | 414 xlinfo->domid = xcinfo->domain; |
keir@21189 | 415 |
keir@21189 | 416 if (xcinfo->flags & XEN_DOMINF_dying) |
keir@21189 | 417 xlinfo->dying = 1; |
keir@21189 | 418 else if (xcinfo->flags & XEN_DOMINF_paused) |
keir@21189 | 419 xlinfo->paused = 1; |
keir@21189 | 420 else if (xcinfo->flags & XEN_DOMINF_blocked || |
keir@21189 | 421 xcinfo->flags & XEN_DOMINF_running) |
keir@21189 | 422 xlinfo->running = 1; |
keir@21189 | 423 xlinfo->max_memkb = PAGE_TO_MEMKB(xcinfo->tot_pages); |
keir@21189 | 424 xlinfo->cpu_time = xcinfo->cpu_time; |
keir@21189 | 425 xlinfo->vcpu_max_id = xcinfo->max_vcpu_id; |
keir@21189 | 426 xlinfo->vcpu_online = xcinfo->nr_online_vcpus; |
keir@21189 | 427 } |
keir@21189 | 428 |
keir@20860 | 429 struct libxl_dominfo * libxl_list_domain(struct libxl_ctx *ctx, int *nb_domain) |
keir@20462 | 430 { |
keir@20462 | 431 struct libxl_dominfo *ptr; |
keir@20867 | 432 int i, ret; |
keir@20822 | 433 xc_domaininfo_t info[1024]; |
keir@20822 | 434 int size = 1024; |
keir@20462 | 435 |
keir@20516 | 436 ptr = calloc(size, sizeof(struct libxl_dominfo)); |
keir@21189 | 437 if (!ptr) return NULL; |
keir@20822 | 438 |
keir@20860 | 439 ret = xc_domain_getinfolist(ctx->xch, 0, 1024, info); |
keir@21189 | 440 if (ret<0) return NULL; |
keir@20784 | 441 |
keir@21189 | 442 for (i = 0; i < ret; i++) { |
keir@21189 | 443 xcinfo2xlinfo(&info[i], &ptr[i]); |
keir@20462 | 444 } |
keir@20867 | 445 *nb_domain = ret; |
keir@20462 | 446 return ptr; |
keir@20462 | 447 } |
keir@20462 | 448 |
keir@21189 | 449 int libxl_domain_info(struct libxl_ctx *ctx, struct libxl_dominfo *info_r, |
keir@21189 | 450 uint32_t domid) { |
keir@21189 | 451 xc_domaininfo_t xcinfo; |
keir@21189 | 452 int ret; |
keir@21189 | 453 |
keir@21189 | 454 ret = xc_domain_getinfolist(ctx->xch, domid, 1, &xcinfo); |
keir@21189 | 455 if (ret<0) return ERROR_FAIL; |
keir@21189 | 456 if (ret==0 || xcinfo.domain != domid) return ERROR_INVAL; |
keir@21189 | 457 |
keir@21189 | 458 xcinfo2xlinfo(&xcinfo, info_r); |
keir@21189 | 459 return 0; |
keir@21189 | 460 } |
keir@21189 | 461 |
keir@21368 | 462 struct libxl_poolinfo * libxl_list_pool(struct libxl_ctx *ctx, int *nb_pool) |
keir@21368 | 463 { |
keir@21368 | 464 struct libxl_poolinfo *ptr; |
keir@21368 | 465 int i, ret; |
keir@21368 | 466 xc_cpupoolinfo_t info[256]; |
keir@21368 | 467 int size = 256; |
keir@21368 | 468 |
keir@21368 | 469 ptr = calloc(size, sizeof(struct libxl_poolinfo)); |
keir@21368 | 470 if (!ptr) return NULL; |
keir@21368 | 471 |
keir@21368 | 472 ret = xc_cpupool_getinfo(ctx->xch, 0, 256, info); |
keir@21368 | 473 if (ret<0) return NULL; |
keir@21368 | 474 |
keir@21368 | 475 for (i = 0; i < ret; i++) { |
keir@21368 | 476 ptr[i].poolid = info[i].cpupool_id; |
keir@21368 | 477 } |
keir@21368 | 478 *nb_pool = ret; |
keir@21368 | 479 return ptr; |
keir@21368 | 480 } |
keir@21368 | 481 |
keir@20860 | 482 /* this API call only list VM running on this host. a VM can be an aggregate of multiple domains. */ |
keir@20860 | 483 struct libxl_vminfo * libxl_list_vm(struct libxl_ctx *ctx, int *nb_vm) |
keir@20860 | 484 { |
keir@20860 | 485 struct libxl_vminfo *ptr; |
keir@20860 | 486 int index, i, ret; |
keir@20860 | 487 xc_domaininfo_t info[1024]; |
keir@20860 | 488 int size = 1024; |
keir@20860 | 489 |
keir@20860 | 490 ptr = calloc(size, sizeof(struct libxl_dominfo)); |
keir@20860 | 491 if (!ptr) |
keir@20860 | 492 return NULL; |
keir@20860 | 493 |
keir@20860 | 494 ret = xc_domain_getinfolist(ctx->xch, 1, 1024, info); |
keir@20860 | 495 for (index = i = 0; i < ret; i++) { |
keir@20860 | 496 if (libxl_is_stubdom(ctx, info[i].domain, NULL)) |
keir@20860 | 497 continue; |
keir@20860 | 498 memcpy(&(ptr[index].uuid), info[i].handle, sizeof(xen_domain_handle_t)); |
keir@20860 | 499 ptr[index].domid = info[i].domain; |
keir@20860 | 500 |
keir@20860 | 501 index++; |
keir@20860 | 502 } |
keir@20860 | 503 *nb_vm = index; |
keir@20860 | 504 return ptr; |
keir@20860 | 505 } |
keir@20860 | 506 |
keir@20462 | 507 int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info *info, |
keir@20462 | 508 uint32_t domid, int fd) |
keir@20462 | 509 { |
keir@20565 | 510 int hvm = is_hvm(ctx, domid); |
keir@20565 | 511 int live = info != NULL && info->flags & XL_SUSPEND_LIVE; |
keir@21543 | 512 int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG; |
keir@20462 | 513 |
keir@20462 | 514 core_suspend(ctx, domid, fd, hvm, live, debug); |
keir@20565 | 515 if (hvm) |
keir@21417 | 516 return save_device_model(ctx, domid, fd); |
keir@20462 | 517 return 0; |
keir@20462 | 518 } |
keir@20462 | 519 |
keir@20462 | 520 int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid) |
keir@20462 | 521 { |
keir@20462 | 522 xc_domain_pause(ctx->xch, domid); |
keir@20462 | 523 return 0; |
keir@20462 | 524 } |
keir@20462 | 525 |
keir@20462 | 526 int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid) |
keir@20462 | 527 { |
keir@20779 | 528 char *path; |
keir@20565 | 529 char *state; |
keir@20565 | 530 |
keir@20565 | 531 if (is_hvm(ctx, domid)) { |
keir@20779 | 532 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid); |
keir@20565 | 533 state = libxl_xs_read(ctx, XBT_NULL, path); |
keir@20565 | 534 if (state != NULL && !strcmp(state, "paused")) { |
Ian@21844 | 535 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid), "continue"); |
keir@20565 | 536 libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL); |
keir@20565 | 537 } |
keir@20565 | 538 } |
keir@20462 | 539 xc_domain_unpause(ctx->xch, domid); |
keir@20565 | 540 |
keir@20462 | 541 return 0; |
keir@20462 | 542 } |
keir@20462 | 543 |
keir@20462 | 544 static char *req_table[] = { |
keir@20462 | 545 [0] = "poweroff", |
keir@20462 | 546 [1] = "reboot", |
keir@20462 | 547 [2] = "suspend", |
keir@20462 | 548 [3] = "crash", |
keir@20462 | 549 [4] = "halt", |
keir@20462 | 550 }; |
keir@20462 | 551 |
keir@20462 | 552 int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req) |
keir@20462 | 553 { |
keir@20462 | 554 char *shutdown_path; |
keir@20462 | 555 char *dom_path; |
keir@20462 | 556 |
keir@20462 | 557 if (req > ARRAY_SIZE(req_table)) |
keir@20462 | 558 return ERROR_INVAL; |
keir@20462 | 559 |
keir@20462 | 560 dom_path = libxl_xs_get_dompath(ctx, domid); |
keir@20512 | 561 if (!dom_path) |
keir@20512 | 562 return ERROR_FAIL; |
keir@20512 | 563 |
keir@20462 | 564 shutdown_path = libxl_sprintf(ctx, "%s/control/shutdown", dom_path); |
keir@20462 | 565 |
keir@20462 | 566 xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], strlen(req_table[req])); |
keir@21552 | 567 if (is_hvm(ctx,domid)) { |
keir@20462 | 568 unsigned long acpi_s_state = 0; |
keir@20462 | 569 unsigned long pvdriver = 0; |
keir@20462 | 570 xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, &acpi_s_state); |
keir@20462 | 571 xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver); |
keir@21552 | 572 if (!pvdriver || acpi_s_state != 0) |
keir@20462 | 573 xc_domain_shutdown(ctx->xch, domid, req); |
keir@20462 | 574 } |
keir@20462 | 575 return 0; |
keir@20462 | 576 } |
keir@20462 | 577 |
keir@20637 | 578 int libxl_get_wait_fd(struct libxl_ctx *ctx, int *fd) |
keir@20545 | 579 { |
keir@20545 | 580 *fd = xs_fileno(ctx->xsh); |
keir@20545 | 581 return 0; |
keir@20545 | 582 } |
keir@20545 | 583 |
keir@20637 | 584 int libxl_wait_for_domain_death(struct libxl_ctx *ctx, uint32_t domid, libxl_waiter *waiter) |
keir@20637 | 585 { |
keir@20637 | 586 waiter->path = strdup("@releaseDomain"); |
keir@21417 | 587 if (asprintf(&(waiter->token), "%d", DOMAIN_DEATH) < 0) |
keir@21417 | 588 return -1; |
keir@20637 | 589 if (!xs_watch(ctx->xsh, waiter->path, waiter->token)) |
keir@20637 | 590 return -1; |
keir@20637 | 591 return 0; |
keir@20637 | 592 } |
keir@20637 | 593 |
keir@20637 | 594 int libxl_wait_for_disk_ejects(struct libxl_ctx *ctx, uint32_t guest_domid, libxl_device_disk *disks, int num_disks, libxl_waiter *waiter) |
keir@20637 | 595 { |
keir@20637 | 596 int i; |
keir@20637 | 597 uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid); |
keir@20637 | 598 |
keir@20637 | 599 if (!domid) |
keir@20637 | 600 domid = guest_domid; |
keir@20637 | 601 |
keir@20637 | 602 for (i = 0; i < num_disks; i++) { |
keir@21417 | 603 if (asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject", |
keir@21417 | 604 libxl_xs_get_dompath(ctx, domid), |
keir@21417 | 605 device_disk_dev_number(disks[i].virtpath)) < 0) |
keir@21417 | 606 return -1; |
keir@21417 | 607 if (asprintf(&(waiter[i].token), "%d", DISK_EJECT) < 0) |
keir@21417 | 608 return -1; |
keir@20637 | 609 xs_watch(ctx->xsh, waiter->path, waiter->token); |
keir@20637 | 610 } |
keir@20637 | 611 return 0; |
keir@20637 | 612 } |
keir@20637 | 613 |
keir@20637 | 614 int libxl_get_event(struct libxl_ctx *ctx, libxl_event *event) |
keir@20545 | 615 { |
keir@20545 | 616 unsigned int num; |
keir@20637 | 617 char **events = xs_read_watch(ctx->xsh, &num); |
keir@20637 | 618 if (num != 2) { |
keir@20637 | 619 free(events); |
keir@20637 | 620 return -1; |
keir@20637 | 621 } |
keir@20637 | 622 event->path = strdup(events[XS_WATCH_PATH]); |
keir@20637 | 623 event->token = strdup(events[XS_WATCH_TOKEN]); |
keir@20637 | 624 event->type = atoi(event->token); |
keir@20637 | 625 free(events); |
keir@20637 | 626 return 0; |
keir@20637 | 627 } |
keir@20637 | 628 |
keir@20637 | 629 int libxl_stop_waiting(struct libxl_ctx *ctx, libxl_waiter *waiter) |
keir@20637 | 630 { |
keir@20637 | 631 if (!xs_unwatch(ctx->xsh, waiter->path, waiter->token)) |
keir@20637 | 632 return -1; |
keir@20637 | 633 else |
keir@20637 | 634 return 0; |
keir@20637 | 635 } |
keir@20637 | 636 |
keir@20637 | 637 int libxl_free_event(libxl_event *event) |
keir@20637 | 638 { |
keir@20637 | 639 free(event->path); |
keir@20637 | 640 free(event->token); |
keir@20637 | 641 return 0; |
keir@20637 | 642 } |
keir@20637 | 643 |
keir@20637 | 644 int libxl_free_waiter(libxl_waiter *waiter) |
keir@20637 | 645 { |
keir@20637 | 646 free(waiter->path); |
keir@20637 | 647 free(waiter->token); |
keir@20637 | 648 return 0; |
keir@20637 | 649 } |
keir@20637 | 650 |
keir@20785 | 651 int libxl_event_get_domain_death_info(struct libxl_ctx *ctx, uint32_t domid, libxl_event *event, xc_domaininfo_t *info) |
keir@20637 | 652 { |
keir@20785 | 653 int rc = 0, ret; |
keir@20545 | 654 |
keir@20637 | 655 if (event && event->type == DOMAIN_DEATH) { |
keir@20785 | 656 ret = xc_domain_getinfolist(ctx->xch, domid, 1, info); |
keir@20785 | 657 if (ret == 1 && info->domain == domid) { |
keir@20785 | 658 if (info->flags & XEN_DOMINF_running || |
keir@20785 | 659 (!(info->flags & XEN_DOMINF_shutdown) && !(info->flags & XEN_DOMINF_dying))) |
keir@20545 | 660 goto out; |
keir@20545 | 661 rc = 1; |
keir@20545 | 662 goto out; |
keir@20545 | 663 } |
keir@20785 | 664 memset(info, 0, sizeof(xc_dominfo_t)); |
keir@20545 | 665 rc = 1; |
keir@20545 | 666 goto out; |
keir@20545 | 667 } |
keir@20545 | 668 out: |
keir@20545 | 669 return rc; |
keir@20545 | 670 } |
keir@20545 | 671 |
keir@20637 | 672 int libxl_event_get_disk_eject_info(struct libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_device_disk *disk) |
keir@20637 | 673 { |
keir@20637 | 674 if (event && event->type == DISK_EJECT) { |
keir@20637 | 675 char *path; |
keir@20637 | 676 char *backend; |
keir@20637 | 677 char *value = libxl_xs_read(ctx, XBT_NULL, event->path); |
keir@20637 | 678 |
keir@20637 | 679 if (!value || strcmp(value, "eject")) |
keir@20637 | 680 return 0; |
keir@20637 | 681 |
keir@20637 | 682 path = strdup(event->path); |
keir@20637 | 683 path[strlen(path) - 6] = '\0'; |
keir@20637 | 684 backend = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend", path)); |
keir@20637 | 685 |
keir@20637 | 686 disk->backend_domid = 0; |
keir@20637 | 687 disk->domid = domid; |
keir@20637 | 688 disk->physpath = NULL; |
keir@20637 | 689 disk->phystype = 0; |
keir@20637 | 690 /* this value is returned to the user: do not free right away */ |
keir@20637 | 691 disk->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev", backend)); |
keir@20637 | 692 disk->unpluggable = 1; |
keir@20637 | 693 disk->readwrite = 0; |
keir@20637 | 694 disk->is_cdrom = 1; |
keir@20637 | 695 |
keir@20637 | 696 free(path); |
keir@20637 | 697 return 1; |
keir@20637 | 698 } |
keir@20637 | 699 return 0; |
keir@20637 | 700 } |
keir@20637 | 701 |
keir@20462 | 702 static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid) |
keir@20462 | 703 { |
keir@20462 | 704 char *pid; |
keir@20462 | 705 int ret; |
keir@20462 | 706 |
keir@20462 | 707 pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/image/device-model-pid", domid)); |
keir@20462 | 708 if (!pid) { |
keir@20542 | 709 int stubdomid = libxl_get_stubdom_id(ctx, domid); |
keir@20542 | 710 if (!stubdomid) { |
keir@20542 | 711 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't find device model's pid"); |
keir@20542 | 712 return -1; |
keir@20542 | 713 } |
keir@20542 | 714 XL_LOG(ctx, XL_LOG_ERROR, "Device model is a stubdom, domid=%d\n", stubdomid); |
keir@20542 | 715 return libxl_domain_destroy(ctx, stubdomid, 0); |
keir@20462 | 716 } |
keir@20462 | 717 xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", domid)); |
keir@20462 | 718 |
keir@20462 | 719 ret = kill(atoi(pid), SIGHUP); |
keir@20462 | 720 if (ret < 0 && errno == ESRCH) { |
keir@20512 | 721 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model already exited"); |
keir@20462 | 722 ret = 0; |
keir@20462 | 723 } else if (ret == 0) { |
keir@20512 | 724 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model signaled"); |
keir@20462 | 725 ret = 0; |
keir@20462 | 726 } else { |
keir@20512 | 727 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to kill Device Model [%d]", |
keir@20512 | 728 atoi(pid)); |
keir@20462 | 729 } |
keir@20462 | 730 return ret; |
keir@20462 | 731 } |
keir@20462 | 732 |
keir@20462 | 733 int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force) |
keir@20462 | 734 { |
keir@20801 | 735 char *dom_path; |
keir@20779 | 736 char *vm_path, *vss_path, *xapi_path; |
keir@20628 | 737 int rc, dm_present; |
keir@20628 | 738 |
keir@20628 | 739 if (is_hvm(ctx, domid)) { |
keir@20628 | 740 dm_present = 1; |
keir@20628 | 741 } else { |
keir@20628 | 742 char *pid; |
keir@20628 | 743 pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/image/device-model-pid", domid)); |
keir@20628 | 744 dm_present = (pid != NULL); |
keir@20628 | 745 libxl_free(ctx, pid); |
keir@20628 | 746 } |
keir@20462 | 747 |
keir@20462 | 748 dom_path = libxl_xs_get_dompath(ctx, domid); |
keir@20512 | 749 if (!dom_path) |
keir@20462 | 750 return -1; |
keir@20512 | 751 |
keir@20482 | 752 if (libxl_device_pci_shutdown(ctx, domid) < 0) |
keir@20512 | 753 XL_LOG(ctx, XL_LOG_ERROR, "pci shutdown failed for domid %d", domid); |
keir@20628 | 754 if (dm_present) { |
keir@20628 | 755 xs_write(ctx->xsh, XBT_NULL, |
keir@20628 | 756 libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid), |
keir@20628 | 757 "shutdown", strlen("shutdown")); |
keir@20628 | 758 } |
keir@20512 | 759 rc = xc_domain_pause(ctx->xch, domid); |
keir@20512 | 760 if (rc < 0) { |
keir@20512 | 761 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_pause failed for %d", domid); |
keir@20462 | 762 return -1; |
keir@20462 | 763 } |
keir@20628 | 764 if (dm_present) { |
keir@20628 | 765 if (libxl_destroy_device_model(ctx, domid) < 0) |
keir@20628 | 766 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_device_model failed for %d", domid); |
keir@20628 | 767 } |
keir@20462 | 768 if (libxl_devices_destroy(ctx, domid, force) < 0) |
keir@20512 | 769 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d", domid); |
keir@20462 | 770 if (!xs_rm(ctx->xsh, XBT_NULL, dom_path)) |
keir@20512 | 771 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", dom_path); |
keir@20779 | 772 |
keir@20801 | 773 vm_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/vm", domid)); |
keir@20823 | 774 if (vm_path) |
keir@20823 | 775 if (!xs_rm(ctx->xsh, XBT_NULL, vm_path)) |
keir@20823 | 776 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vm_path); |
keir@20779 | 777 |
keir@20801 | 778 vss_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/vss", domid)); |
keir@20823 | 779 if (vss_path) |
keir@20823 | 780 if (!xs_rm(ctx->xsh, XBT_NULL, vss_path)) |
keir@20823 | 781 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vss_path); |
keir@20779 | 782 |
keir@20779 | 783 xapi_path = libxl_sprintf(ctx, "/xapi/%u", domid); |
keir@20823 | 784 if (xapi_path) |
keir@20823 | 785 if (!xs_rm(ctx->xsh, XBT_NULL, xapi_path)) |
keir@20823 | 786 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", xapi_path); |
keir@20779 | 787 |
keir@21190 | 788 libxl__userdata_destroyall(ctx, domid); |
keir@21190 | 789 |
keir@20545 | 790 rc = xc_domain_destroy(ctx->xch, domid); |
keir@20545 | 791 if (rc < 0) { |
keir@20545 | 792 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid); |
keir@20545 | 793 return -1; |
keir@20545 | 794 } |
keir@20462 | 795 return 0; |
keir@20462 | 796 } |
keir@20462 | 797 |
Ian@21847 | 798 int libxl_console_exec(struct libxl_ctx *ctx, uint32_t domid, int cons_num) |
keir@20564 | 799 { |
Ian@21847 | 800 char *p = libxl_sprintf(ctx, "%s/xenconsole", libxl_private_bindir_path()); |
Ian@21847 | 801 char *domid_s = libxl_sprintf(ctx, "%d", domid); |
Ian@21847 | 802 char *cons_num_s = libxl_sprintf(ctx, "%d", cons_num); |
Ian@21847 | 803 return execl(p, p, domid_s, "--num", cons_num_s, (void *)NULL) == 0 ? 0 : ERROR_FAIL; |
keir@20564 | 804 } |
keir@20564 | 805 |
keir@20462 | 806 static char ** libxl_build_device_model_args(struct libxl_ctx *ctx, |
keir@20462 | 807 libxl_device_model_info *info, |
keir@20462 | 808 libxl_device_nic *vifs, |
keir@20462 | 809 int num_vifs) |
keir@20462 | 810 { |
keir@20462 | 811 int num = 0, i; |
keir@20462 | 812 flexarray_t *dm_args; |
keir@20462 | 813 dm_args = flexarray_make(16, 1); |
keir@20462 | 814 if (!dm_args) |
keir@20462 | 815 return NULL; |
keir@20462 | 816 |
keir@20516 | 817 flexarray_set(dm_args, num++, "qemu-dm"); |
keir@20516 | 818 flexarray_set(dm_args, num++, "-d"); |
keir@20462 | 819 |
keir@20462 | 820 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->domid)); |
keir@20462 | 821 |
keir@20462 | 822 if (info->dom_name) { |
keir@20516 | 823 flexarray_set(dm_args, num++, "-domain-name"); |
keir@20516 | 824 flexarray_set(dm_args, num++, info->dom_name); |
keir@20462 | 825 } |
keir@20462 | 826 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) { |
keir@20516 | 827 flexarray_set(dm_args, num++, "-vnc"); |
keir@20462 | 828 if (info->vncdisplay) { |
keir@20462 | 829 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) { |
keir@21362 | 830 flexarray_set( |
keir@21362 | 831 dm_args, num++, |
keir@21362 | 832 libxl_sprintf(ctx, "%s:%d%s", |
keir@21362 | 833 info->vnclisten, |
keir@21362 | 834 info->vncdisplay, |
keir@21362 | 835 info->vncpasswd ? ",password" : "")); |
keir@20462 | 836 } else { |
keir@20462 | 837 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "127.0.0.1:%d", info->vncdisplay)); |
keir@20462 | 838 } |
keir@20462 | 839 } else if (info->vnclisten) { |
keir@20462 | 840 if (strchr(info->vnclisten, ':') != NULL) { |
keir@20516 | 841 flexarray_set(dm_args, num++, info->vnclisten); |
keir@20462 | 842 } else { |
keir@20462 | 843 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:0", info->vnclisten)); |
keir@20462 | 844 } |
keir@20462 | 845 } else { |
keir@20516 | 846 flexarray_set(dm_args, num++, "127.0.0.1:0"); |
keir@20462 | 847 } |
keir@20462 | 848 if (info->vncunused) { |
keir@20516 | 849 flexarray_set(dm_args, num++, "-vncunused"); |
keir@20462 | 850 } |
keir@20462 | 851 } |
keir@21378 | 852 if (info->sdl) { |
keir@20516 | 853 flexarray_set(dm_args, num++, "-sdl"); |
keir@20462 | 854 if (info->opengl) { |
keir@20516 | 855 flexarray_set(dm_args, num++, "-disable-opengl"); |
keir@20462 | 856 } |
keir@20462 | 857 } |
keir@20462 | 858 if (info->keymap) { |
keir@20516 | 859 flexarray_set(dm_args, num++, "-k"); |
keir@20516 | 860 flexarray_set(dm_args, num++, info->keymap); |
keir@20462 | 861 } |
keir@20462 | 862 if (info->nographic && (!info->sdl && !info->vnc)) { |
keir@20516 | 863 flexarray_set(dm_args, num++, "-nographic"); |
keir@20462 | 864 } |
keir@20462 | 865 if (info->serial) { |
keir@20516 | 866 flexarray_set(dm_args, num++, "-serial"); |
keir@20516 | 867 flexarray_set(dm_args, num++, info->serial); |
keir@20462 | 868 } |
keir@20509 | 869 if (info->type == XENFV) { |
Ian@21733 | 870 int ioemu_vifs = 0; |
Ian@21733 | 871 |
keir@20509 | 872 if (info->videoram) { |
keir@20516 | 873 flexarray_set(dm_args, num++, "-videoram"); |
keir@20509 | 874 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->videoram)); |
keir@20509 | 875 } |
keir@20509 | 876 if (info->stdvga) { |
keir@20516 | 877 flexarray_set(dm_args, num++, "-std-vga"); |
keir@20509 | 878 } |
keir@20509 | 879 |
keir@20509 | 880 if (info->boot) { |
keir@20516 | 881 flexarray_set(dm_args, num++, "-boot"); |
keir@20516 | 882 flexarray_set(dm_args, num++, info->boot); |
keir@20509 | 883 } |
keir@20509 | 884 if (info->usb) { |
keir@20516 | 885 flexarray_set(dm_args, num++, "-usb"); |
keir@20509 | 886 if (info->usbdevice) { |
keir@20516 | 887 flexarray_set(dm_args, num++, "-usbdevice"); |
keir@20516 | 888 flexarray_set(dm_args, num++, info->usbdevice); |
keir@20509 | 889 } |
keir@20509 | 890 } |
Ian@21801 | 891 if (info->soundhw) { |
Ian@21801 | 892 flexarray_set(dm_args, num++, "-soundhw"); |
Ian@21801 | 893 flexarray_set(dm_args, num++, info->soundhw); |
Ian@21801 | 894 } |
keir@20509 | 895 if (info->apic) { |
keir@20516 | 896 flexarray_set(dm_args, num++, "-acpi"); |
keir@20509 | 897 } |
keir@21570 | 898 if (info->vcpus > 1) { |
keir@21570 | 899 flexarray_set(dm_args, num++, "-vcpus"); |
keir@21570 | 900 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->vcpus)); |
keir@21570 | 901 } |
keir@21570 | 902 if (info->vcpu_avail) { |
keir@21570 | 903 flexarray_set(dm_args, num++, "-vcpu_avail"); |
keir@21570 | 904 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "0x%x", info->vcpu_avail)); |
keir@21570 | 905 } |
keir@20509 | 906 for (i = 0; i < num_vifs; i++) { |
keir@20509 | 907 if (vifs[i].nictype == NICTYPE_IOEMU) { |
keir@20780 | 908 char *smac = libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x", |
keir@20780 | 909 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2], |
keir@20780 | 910 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]); |
keir@20781 | 911 if (!vifs[i].ifname) |
keir@20781 | 912 vifs[i].ifname = libxl_sprintf(ctx, "tap%d.%d", info->domid, vifs[i].devid - 1); |
keir@20516 | 913 flexarray_set(dm_args, num++, "-net"); |
keir@20509 | 914 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "nic,vlan=%d,macaddr=%s,model=%s", |
keir@20780 | 915 vifs[i].devid, smac, vifs[i].model)); |
keir@20516 | 916 flexarray_set(dm_args, num++, "-net"); |
keir@20509 | 917 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "tap,vlan=%d,ifname=%s,bridge=%s", |
keir@20509 | 918 vifs[i].devid, vifs[i].ifname, vifs[i].bridge)); |
Ian@21733 | 919 ioemu_vifs++; |
keir@20509 | 920 } |
keir@20462 | 921 } |
Ian@21733 | 922 /* If we have no emulated nics, tell qemu not to create any */ |
Ian@21733 | 923 if ( ioemu_vifs == 0 ) { |
Ian@21733 | 924 flexarray_set(dm_args, num++, "-net"); |
Ian@21733 | 925 flexarray_set(dm_args, num++, "none"); |
Ian@21733 | 926 } |
keir@20462 | 927 } |
keir@20565 | 928 if (info->saved_state) { |
keir@20565 | 929 flexarray_set(dm_args, num++, "-loadvm"); |
keir@20565 | 930 flexarray_set(dm_args, num++, info->saved_state); |
keir@20565 | 931 } |
keir@20509 | 932 for (i = 0; info->extra && info->extra[i] != NULL; i++) |
keir@20509 | 933 flexarray_set(dm_args, num++, info->extra[i]); |
keir@20516 | 934 flexarray_set(dm_args, num++, "-M"); |
keir@20509 | 935 if (info->type == XENPV) |
keir@20516 | 936 flexarray_set(dm_args, num++, "xenpv"); |
keir@20509 | 937 else |
keir@20516 | 938 flexarray_set(dm_args, num++, "xenfv"); |
keir@20462 | 939 flexarray_set(dm_args, num++, NULL); |
keir@20462 | 940 |
keir@20462 | 941 return (char **) flexarray_contents(dm_args); |
keir@20462 | 942 } |
keir@20462 | 943 |
keir@20834 | 944 void dm_xenstore_record_pid(void *for_spawn, pid_t innerchild) |
keir@20834 | 945 { |
keir@20514 | 946 struct libxl_device_model_starting *starting = for_spawn; |
keir@20514 | 947 char *kvs[3]; |
keir@20820 | 948 int rc; |
keir@20820 | 949 struct xs_handle *xsh; |
keir@20514 | 950 |
keir@20820 | 951 xsh = xs_daemon_open(); |
keir@20514 | 952 /* we mustn't use the parent's handle in the child */ |
keir@20514 | 953 |
keir@20514 | 954 kvs[0] = "image/device-model-pid"; |
keir@21417 | 955 if (asprintf(&kvs[1], "%d", innerchild) < 0) |
keir@21417 | 956 return; |
keir@20514 | 957 kvs[2] = NULL; |
keir@20820 | 958 |
keir@20820 | 959 rc = xs_writev(xsh, XBT_NULL, starting->dom_path, kvs); |
keir@20820 | 960 if (rc) |
keir@20820 | 961 return; |
keir@20820 | 962 xs_daemon_close(xsh); |
keir@20514 | 963 } |
keir@20514 | 964 |
keir@20542 | 965 static int libxl_vfb_and_vkb_from_device_model_info(struct libxl_ctx *ctx, |
keir@20542 | 966 libxl_device_model_info *info, |
keir@20542 | 967 libxl_device_vfb *vfb, |
keir@20542 | 968 libxl_device_vkb *vkb) |
keir@20542 | 969 { |
keir@20542 | 970 memset(vfb, 0x00, sizeof(libxl_device_vfb)); |
keir@20542 | 971 memset(vkb, 0x00, sizeof(libxl_device_vkb)); |
keir@20542 | 972 |
keir@20542 | 973 vfb->backend_domid = 0; |
keir@20542 | 974 vfb->devid = 0; |
keir@20542 | 975 vfb->vnc = info->vnc; |
keir@20542 | 976 vfb->vnclisten = info->vnclisten; |
keir@20542 | 977 vfb->vncdisplay = info->vncdisplay; |
keir@20542 | 978 vfb->vncunused = info->vncunused; |
keir@21362 | 979 vfb->vncpasswd = info->vncpasswd; |
keir@20542 | 980 vfb->keymap = info->keymap; |
keir@20542 | 981 vfb->sdl = info->sdl; |
keir@20542 | 982 vfb->opengl = info->opengl; |
keir@20542 | 983 |
keir@20542 | 984 vkb->backend_domid = 0; |
keir@20542 | 985 vkb->devid = 0; |
keir@20542 | 986 return 0; |
keir@20542 | 987 } |
keir@20542 | 988 |
keir@20542 | 989 static int libxl_write_dmargs(struct libxl_ctx *ctx, int domid, int guest_domid, char **args) |
keir@20542 | 990 { |
keir@20542 | 991 int i; |
keir@20542 | 992 char *vm_path; |
keir@20542 | 993 char *dmargs, *path; |
keir@20542 | 994 int dmargs_size; |
keir@20542 | 995 struct xs_permissions roperm[2]; |
keir@20542 | 996 xs_transaction_t t; |
keir@20542 | 997 |
keir@20542 | 998 roperm[0].id = 0; |
keir@20542 | 999 roperm[0].perms = XS_PERM_NONE; |
keir@20542 | 1000 roperm[1].id = domid; |
keir@20542 | 1001 roperm[1].perms = XS_PERM_READ; |
keir@20542 | 1002 |
keir@20542 | 1003 vm_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/vm", guest_domid)); |
keir@20542 | 1004 |
keir@20542 | 1005 i = 0; |
keir@20542 | 1006 dmargs_size = 0; |
keir@20542 | 1007 while (args[i] != NULL) { |
keir@20542 | 1008 dmargs_size = dmargs_size + strlen(args[i]) + 1; |
keir@20542 | 1009 i++; |
keir@20542 | 1010 } |
keir@20542 | 1011 dmargs_size++; |
keir@20542 | 1012 dmargs = (char *) malloc(dmargs_size); |
keir@20542 | 1013 i = 1; |
keir@20542 | 1014 dmargs[0] = '\0'; |
keir@20542 | 1015 while (args[i] != NULL) { |
keir@20542 | 1016 if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) { |
keir@20542 | 1017 strcat(dmargs, " "); |
keir@20542 | 1018 strcat(dmargs, args[i]); |
keir@20542 | 1019 } |
keir@20542 | 1020 i++; |
keir@20542 | 1021 } |
keir@20542 | 1022 path = libxl_sprintf(ctx, "%s/image/dmargs", vm_path); |
keir@20542 | 1023 |
keir@20542 | 1024 retry_transaction: |
keir@20542 | 1025 t = xs_transaction_start(ctx->xsh); |
keir@20542 | 1026 xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs)); |
keir@20542 | 1027 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm)); |
keir@20542 | 1028 xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm)); |
keir@20542 | 1029 if (!xs_transaction_end(ctx->xsh, t, 0)) |
keir@20542 | 1030 if (errno == EAGAIN) |
keir@20542 | 1031 goto retry_transaction; |
keir@20542 | 1032 free(dmargs); |
keir@20542 | 1033 return 0; |
keir@20542 | 1034 } |
keir@20542 | 1035 |
keir@20542 | 1036 static int libxl_create_stubdom(struct libxl_ctx *ctx, |
keir@20542 | 1037 libxl_device_model_info *info, |
keir@20542 | 1038 libxl_device_disk *disks, int num_disks, |
keir@20542 | 1039 libxl_device_nic *vifs, int num_vifs, |
keir@20542 | 1040 libxl_device_vfb *vfb, |
keir@20542 | 1041 libxl_device_vkb *vkb, |
keir@20542 | 1042 libxl_device_model_starting **starting_r) |
keir@20542 | 1043 { |
keir@20843 | 1044 int i, num_console = 1, ret; |
keir@20570 | 1045 libxl_device_console *console; |
keir@20542 | 1046 libxl_domain_create_info c_info; |
keir@20542 | 1047 libxl_domain_build_info b_info; |
keir@20542 | 1048 libxl_domain_build_state state; |
keir@20542 | 1049 uint32_t domid; |
keir@20542 | 1050 char **args; |
keir@20542 | 1051 struct xs_permissions perm[2]; |
keir@20542 | 1052 xs_transaction_t t; |
keir@20594 | 1053 libxl_device_model_starting *dm_starting = 0; |
keir@20542 | 1054 |
keir@20542 | 1055 args = libxl_build_device_model_args(ctx, info, vifs, num_vifs); |
keir@20542 | 1056 if (!args) |
keir@20542 | 1057 return ERROR_FAIL; |
keir@20542 | 1058 |
keir@20542 | 1059 memset(&c_info, 0x00, sizeof(libxl_domain_create_info)); |
keir@20542 | 1060 c_info.hvm = 0; |
keir@20542 | 1061 c_info.name = libxl_sprintf(ctx, "%s-dm", libxl_domid_to_name(ctx, info->domid)); |
keir@20801 | 1062 for (i = 0; i < 16; i++) |
keir@20801 | 1063 c_info.uuid[i] = info->uuid[i]; |
keir@20542 | 1064 |
keir@20542 | 1065 memset(&b_info, 0x00, sizeof(libxl_domain_build_info)); |
keir@20542 | 1066 b_info.max_vcpus = 1; |
keir@20542 | 1067 b_info.max_memkb = 32 * 1024; |
keir@20647 | 1068 b_info.target_memkb = b_info.max_memkb; |
Ian@21848 | 1069 b_info.kernel.path = libxl_abs_path(ctx, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path()); |
keir@20542 | 1070 b_info.u.pv.cmdline = libxl_sprintf(ctx, " -d %d", info->domid); |
Ian@21848 | 1071 b_info.u.pv.ramdisk.path = ""; |
keir@20542 | 1072 b_info.u.pv.features = ""; |
keir@20542 | 1073 b_info.hvm = 0; |
keir@20542 | 1074 |
keir@20843 | 1075 ret = libxl_domain_make(ctx, &c_info, &domid); |
keir@20843 | 1076 if (ret) return ret; |
keir@20843 | 1077 ret = libxl_domain_build(ctx, &b_info, domid, &state); |
keir@20843 | 1078 if (ret) return ret; |
keir@20542 | 1079 |
keir@20542 | 1080 libxl_write_dmargs(ctx, domid, info->domid, args); |
keir@20843 | 1081 libxl_xs_write(ctx, XBT_NULL, |
keir@20843 | 1082 libxl_sprintf(ctx, "%s/image/device-model-domid", libxl_xs_get_dompath(ctx, info->domid)), |
keir@20843 | 1083 "%d", domid); |
keir@20843 | 1084 libxl_xs_write(ctx, XBT_NULL, |
keir@20843 | 1085 libxl_sprintf(ctx, "%s/target", libxl_xs_get_dompath(ctx, domid)), |
keir@20843 | 1086 "%d", info->domid); |
keir@20542 | 1087 xc_domain_set_target(ctx->xch, domid, info->domid); |
keir@20542 | 1088 xs_set_target(ctx->xsh, domid, info->domid); |
keir@20542 | 1089 |
keir@20542 | 1090 perm[0].id = domid; |
keir@20542 | 1091 perm[0].perms = XS_PERM_NONE; |
keir@20542 | 1092 perm[1].id = info->domid; |
keir@20542 | 1093 perm[1].perms = XS_PERM_READ; |
keir@20542 | 1094 retry_transaction: |
keir@20542 | 1095 t = xs_transaction_start(ctx->xsh); |
keir@20542 | 1096 xs_mkdir(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid)); |
keir@20542 | 1097 xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm)); |
keir@20635 | 1098 xs_mkdir(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/%d/device/vfs", domid)); |
keir@20635 | 1099 xs_set_permissions(ctx->xsh, t, libxl_sprintf(ctx, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm)); |
keir@20542 | 1100 if (!xs_transaction_end(ctx->xsh, t, 0)) |
keir@20542 | 1101 if (errno == EAGAIN) |
keir@20542 | 1102 goto retry_transaction; |
keir@20542 | 1103 |
keir@20542 | 1104 for (i = 0; i < num_disks; i++) { |
keir@20781 | 1105 disks[i].domid = domid; |
keir@20843 | 1106 ret = libxl_device_disk_add(ctx, domid, &disks[i]); |
keir@20843 | 1107 if (ret) return ret; |
keir@20542 | 1108 } |
keir@20542 | 1109 for (i = 0; i < num_vifs; i++) { |
keir@20781 | 1110 vifs[i].domid = domid; |
keir@20843 | 1111 ret = libxl_device_nic_add(ctx, domid, &vifs[i]); |
keir@20843 | 1112 if (ret) return ret; |
keir@20542 | 1113 } |
keir@20781 | 1114 vfb->domid = domid; |
keir@20843 | 1115 ret = libxl_device_vfb_add(ctx, domid, vfb); |
keir@20843 | 1116 if (ret) return ret; |
keir@20781 | 1117 vkb->domid = domid; |
keir@20843 | 1118 ret = libxl_device_vkb_add(ctx, domid, vkb); |
keir@20843 | 1119 if (ret) return ret; |
keir@20542 | 1120 |
keir@20570 | 1121 if (info->serial) |
keir@20570 | 1122 num_console++; |
keir@20843 | 1123 |
keir@20570 | 1124 console = libxl_calloc(ctx, num_console, sizeof(libxl_device_console)); |
keir@20843 | 1125 if (!console) |
keir@20843 | 1126 return ERROR_NOMEM; |
keir@20843 | 1127 |
keir@20570 | 1128 for (i = 0; i < num_console; i++) { |
keir@20781 | 1129 console[i].devid = i; |
keir@20781 | 1130 console[i].constype = CONSTYPE_IOEMU; |
keir@20781 | 1131 console[i].domid = domid; |
keir@20570 | 1132 if (!i) |
keir@20781 | 1133 console[i].build_state = &state; |
keir@20843 | 1134 ret = libxl_device_console_add(ctx, domid, &console[i]); |
keir@20843 | 1135 if (ret) return ret; |
keir@20570 | 1136 } |
keir@20594 | 1137 if (libxl_create_xenpv_qemu(ctx, vfb, num_console, console, &dm_starting) < 0) { |
keir@20594 | 1138 free(args); |
keir@20594 | 1139 return -1; |
keir@20594 | 1140 } |
keir@20594 | 1141 if (libxl_confirm_device_model_startup(ctx, dm_starting) < 0) { |
keir@20594 | 1142 free(args); |
keir@20594 | 1143 return -1; |
keir@20594 | 1144 } |
keir@20542 | 1145 |
keir@20542 | 1146 libxl_domain_unpause(ctx, domid); |
keir@20542 | 1147 |
keir@20594 | 1148 if (starting_r) { |
keir@20594 | 1149 *starting_r = libxl_calloc(ctx, sizeof(libxl_device_model_starting), 1); |
keir@20598 | 1150 (*starting_r)->domid = info->domid; |
keir@20594 | 1151 (*starting_r)->dom_path = libxl_xs_get_dompath(ctx, info->domid); |
keir@20594 | 1152 (*starting_r)->for_spawn = NULL; |
keir@20594 | 1153 } |
keir@20594 | 1154 |
keir@20542 | 1155 free(args); |
keir@20542 | 1156 return 0; |
keir@20542 | 1157 } |
keir@20542 | 1158 |
keir@20462 | 1159 int libxl_create_device_model(struct libxl_ctx *ctx, |
keir@20462 | 1160 libxl_device_model_info *info, |
keir@20542 | 1161 libxl_device_disk *disks, int num_disks, |
keir@20514 | 1162 libxl_device_nic *vifs, int num_vifs, |
keir@20514 | 1163 libxl_device_model_starting **starting_r) |
keir@20462 | 1164 { |
keir@20546 | 1165 char *path, *logfile; |
keir@20514 | 1166 int logfile_w, null; |
keir@20546 | 1167 int rc; |
keir@20462 | 1168 char **args; |
keir@20594 | 1169 struct libxl_device_model_starting buf_starting, *p; |
keir@21362 | 1170 xs_transaction_t t; |
keir@21362 | 1171 char *vm_path; |
keir@21362 | 1172 char **pass_stuff; |
keir@20514 | 1173 |
keir@20542 | 1174 if (strstr(info->device_model, "stubdom-dm")) { |
keir@20542 | 1175 libxl_device_vfb vfb; |
keir@20542 | 1176 libxl_device_vkb vkb; |
keir@20542 | 1177 |
keir@20542 | 1178 libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb); |
keir@20542 | 1179 return libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r); |
keir@20542 | 1180 } |
keir@20542 | 1181 |
keir@20462 | 1182 args = libxl_build_device_model_args(ctx, info, vifs, num_vifs); |
keir@20462 | 1183 if (!args) |
keir@20462 | 1184 return ERROR_FAIL; |
keir@20462 | 1185 |
keir@20462 | 1186 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid); |
keir@20462 | 1187 xs_mkdir(ctx->xsh, XBT_NULL, path); |
keir@21599 | 1188 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/disable_pf", path), "%d", !info->xen_platform_pci); |
keir@20462 | 1189 |
keir@20546 | 1190 libxl_create_logfile(ctx, libxl_sprintf(ctx, "qemu-dm-%s", info->dom_name), &logfile); |
keir@20467 | 1191 logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644); |
keir@20546 | 1192 free(logfile); |
keir@20462 | 1193 null = open("/dev/null", O_RDONLY); |
keir@20514 | 1194 |
keir@20514 | 1195 if (starting_r) { |
keir@20516 | 1196 rc = ERROR_NOMEM; |
keir@20594 | 1197 *starting_r = libxl_calloc(ctx, sizeof(libxl_device_model_starting), 1); |
keir@20516 | 1198 if (!*starting_r) goto xit; |
keir@20594 | 1199 p = *starting_r; |
keir@20611 | 1200 p->for_spawn = libxl_calloc(ctx, sizeof(struct libxl_spawn_starting), 1); |
keir@20594 | 1201 } else { |
keir@20594 | 1202 p = &buf_starting; |
keir@20594 | 1203 p->for_spawn = NULL; |
keir@20594 | 1204 } |
keir@20514 | 1205 |
keir@20594 | 1206 p->domid = info->domid; |
keir@20594 | 1207 p->dom_path = libxl_xs_get_dompath(ctx, info->domid); |
keir@20594 | 1208 if (!p->dom_path) { libxl_free(ctx, p); return ERROR_FAIL; } |
keir@20594 | 1209 |
keir@21362 | 1210 if (info->vncpasswd) { |
keir@21362 | 1211 retry_transaction: |
keir@21362 | 1212 /* Find uuid and the write the vnc password to xenstore for qemu. */ |
keir@21362 | 1213 t = xs_transaction_start(ctx->xsh); |
keir@21362 | 1214 vm_path = libxl_xs_read(ctx,t,libxl_sprintf(ctx, "%s/vm", p->dom_path)); |
keir@21362 | 1215 if (vm_path) { |
keir@21362 | 1216 /* Now write the vncpassword into it. */ |
keir@21362 | 1217 pass_stuff = libxl_calloc(ctx, 2, sizeof(char *)); |
keir@21362 | 1218 pass_stuff[0] = "vncpasswd"; |
keir@21362 | 1219 pass_stuff[1] = info->vncpasswd; |
keir@21362 | 1220 libxl_xs_writev(ctx,t,vm_path,pass_stuff); |
keir@21362 | 1221 if (!xs_transaction_end(ctx->xsh, t, 0)) |
keir@21362 | 1222 if (errno == EAGAIN) |
keir@21362 | 1223 goto retry_transaction; |
keir@21362 | 1224 } |
keir@21362 | 1225 } |
keir@21362 | 1226 |
keir@20594 | 1227 rc = libxl_spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid); |
keir@20514 | 1228 if (rc < 0) goto xit; |
keir@20514 | 1229 if (!rc) { /* inner child */ |
keir@20833 | 1230 libxl_exec(null, logfile_w, logfile_w, |
keir@21353 | 1231 libxl_abs_path(ctx, info->device_model, libxl_private_bindir_path()), |
keir@21353 | 1232 args); |
keir@20514 | 1233 } |
keir@20514 | 1234 |
keir@20514 | 1235 rc = 0; |
keir@20514 | 1236 xit: |
keir@20516 | 1237 free(args); |
keir@20462 | 1238 close(null); |
keir@20462 | 1239 close(logfile_w); |
keir@20462 | 1240 |
keir@20514 | 1241 return rc; |
keir@20514 | 1242 } |
keir@20514 | 1243 |
keir@20514 | 1244 int libxl_detach_device_model(struct libxl_ctx *ctx, |
keir@20779 | 1245 libxl_device_model_starting *starting) |
keir@20779 | 1246 { |
keir@20514 | 1247 int rc; |
keir@20594 | 1248 rc = libxl_spawn_detach(ctx, starting->for_spawn); |
keir@20594 | 1249 if (starting->for_spawn) libxl_free(ctx, starting->for_spawn); |
keir@20514 | 1250 libxl_free(ctx, starting); |
keir@20514 | 1251 return rc; |
keir@20514 | 1252 } |
keir@20462 | 1253 |
keir@20514 | 1254 |
keir@20514 | 1255 int libxl_confirm_device_model_startup(struct libxl_ctx *ctx, |
keir@20779 | 1256 libxl_device_model_starting *starting) |
keir@20779 | 1257 { |
keir@20514 | 1258 int problem = libxl_wait_for_device_model(ctx, starting->domid, "running", |
keir@20514 | 1259 libxl_spawn_check, |
keir@20594 | 1260 starting->for_spawn); |
keir@20514 | 1261 int detach = libxl_detach_device_model(ctx, starting); |
keir@20514 | 1262 return problem ? problem : detach; |
keir@20542 | 1263 return 0; |
keir@20462 | 1264 } |
keir@20462 | 1265 |
keir@20514 | 1266 |
keir@20462 | 1267 /******************************************************************************/ |
keir@20566 | 1268 |
keir@21632 | 1269 static char *get_blktap2_device(struct libxl_ctx *ctx, |
keir@21632 | 1270 const char *name, const char *type) |
keir@20566 | 1271 { |
keir@21632 | 1272 int minor = tap_ctl_find_minor(type, name); |
keir@21632 | 1273 if (minor < 0) |
keir@21632 | 1274 return NULL; |
keir@21632 | 1275 return libxl_sprintf(ctx, "/dev/xen/blktap-2/tapdev%d", minor); |
keir@21632 | 1276 } |
keir@21632 | 1277 |
keir@21632 | 1278 static char *make_blktap2_device(struct libxl_ctx *ctx, |
keir@21632 | 1279 const char *name, const char *type) |
keir@21632 | 1280 { |
keir@21647 | 1281 char *params, *devname = NULL; |
keir@21632 | 1282 int err; |
keir@21632 | 1283 params = libxl_sprintf(ctx, "%s:%s", type, name); |
keir@21632 | 1284 err = tap_ctl_create(params, &devname); |
keir@21647 | 1285 if (!err) |
keir@21647 | 1286 libxl_ptr_add(ctx, devname); |
keir@21647 | 1287 return err ? NULL : devname; |
keir@20566 | 1288 } |
keir@20566 | 1289 |
keir@20462 | 1290 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk) |
keir@20462 | 1291 { |
keir@20462 | 1292 flexarray_t *front; |
keir@20462 | 1293 flexarray_t *back; |
keir@20462 | 1294 char *backend_type; |
keir@20462 | 1295 unsigned int boffset = 0; |
keir@20462 | 1296 unsigned int foffset = 0; |
keir@20462 | 1297 int devid; |
keir@20462 | 1298 libxl_device device; |
keir@20566 | 1299 int major, minor; |
keir@20462 | 1300 |
keir@20462 | 1301 front = flexarray_make(16, 1); |
keir@20462 | 1302 if (!front) |
keir@20462 | 1303 return ERROR_NOMEM; |
keir@20462 | 1304 back = flexarray_make(16, 1); |
keir@20462 | 1305 if (!back) /* leaks front if error */ |
keir@20462 | 1306 return ERROR_NOMEM; |
keir@20462 | 1307 |
keir@20462 | 1308 backend_type = device_disk_backend_type_of_phystype(disk->phystype); |
keir@20462 | 1309 devid = device_disk_dev_number(disk->virtpath); |
keir@20947 | 1310 if (devid==-1) { |
keir@20947 | 1311 XL_LOG(ctx, XL_LOG_ERROR, "Invalid or unuspported" |
keir@20947 | 1312 " virtual disk identifier %s", disk->virtpath); |
keir@20947 | 1313 return ERROR_INVAL; |
keir@20947 | 1314 } |
keir@20462 | 1315 |
keir@20462 | 1316 device.backend_devid = devid; |
keir@20462 | 1317 device.backend_domid = disk->backend_domid; |
keir@20462 | 1318 device.devid = devid; |
keir@20462 | 1319 device.domid = disk->domid; |
keir@20462 | 1320 device.kind = DEVICE_VBD; |
keir@20462 | 1321 |
keir@20462 | 1322 switch (disk->phystype) { |
keir@20462 | 1323 case PHYSTYPE_PHY: { |
keir@20462 | 1324 |
keir@20509 | 1325 device_physdisk_major_minor(disk->physpath, &major, &minor); |
keir@20516 | 1326 flexarray_set(back, boffset++, "physical-device"); |
keir@20462 | 1327 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, minor)); |
keir@20462 | 1328 |
keir@20516 | 1329 flexarray_set(back, boffset++, "params"); |
keir@20516 | 1330 flexarray_set(back, boffset++, disk->physpath); |
keir@20462 | 1331 |
keir@20462 | 1332 device.backend_kind = DEVICE_VBD; |
keir@20462 | 1333 break; |
keir@20462 | 1334 } |
keir@20566 | 1335 case PHYSTYPE_FILE: |
keir@20566 | 1336 /* let's pretend is tap:aio for the moment */ |
keir@20566 | 1337 disk->phystype = PHYSTYPE_AIO; |
keir@21632 | 1338 case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD: { |
keir@21632 | 1339 const char *msg; |
keir@21632 | 1340 if (!tap_ctl_check(&msg)) { |
keir@21632 | 1341 const char *type = device_disk_string_of_phystype(disk->phystype); |
keir@21632 | 1342 char *dev; |
keir@21632 | 1343 dev = get_blktap2_device(ctx, disk->physpath, type); |
keir@21632 | 1344 if (!dev) |
keir@21632 | 1345 dev = make_blktap2_device(ctx, disk->physpath, type); |
keir@21632 | 1346 if (!dev) |
keir@21632 | 1347 return -1; |
keir@20566 | 1348 flexarray_set(back, boffset++, "tapdisk-params"); |
keir@20566 | 1349 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath)); |
keir@20566 | 1350 flexarray_set(back, boffset++, "params"); |
Ian@21845 | 1351 flexarray_set(back, boffset++, libxl_strdup(ctx, dev)); |
keir@20566 | 1352 backend_type = "phy"; |
keir@20566 | 1353 device_physdisk_major_minor(dev, &major, &minor); |
keir@20566 | 1354 flexarray_set(back, boffset++, "physical-device"); |
keir@20566 | 1355 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, minor)); |
keir@20566 | 1356 device.backend_kind = DEVICE_VBD; |
keir@20566 | 1357 |
keir@20566 | 1358 break; |
keir@20566 | 1359 } |
keir@20516 | 1360 flexarray_set(back, boffset++, "params"); |
keir@20462 | 1361 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s", |
keir@20462 | 1362 device_disk_string_of_phystype(disk->phystype), disk->physpath)); |
keir@20462 | 1363 |
keir@20462 | 1364 device.backend_kind = DEVICE_TAP; |
keir@20462 | 1365 break; |
keir@21632 | 1366 } |
keir@20846 | 1367 default: |
keir@20846 | 1368 XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", disk->phystype); |
keir@20846 | 1369 return ERROR_INVAL; |
keir@20462 | 1370 } |
keir@20462 | 1371 |
keir@20516 | 1372 flexarray_set(back, boffset++, "frontend-id"); |
keir@20462 | 1373 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", disk->domid)); |
keir@20516 | 1374 flexarray_set(back, boffset++, "online"); |
keir@20516 | 1375 flexarray_set(back, boffset++, "1"); |
keir@20516 | 1376 flexarray_set(back, boffset++, "removable"); |
keir@20462 | 1377 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", (disk->unpluggable) ? 1 : 0)); |
keir@20516 | 1378 flexarray_set(back, boffset++, "bootable"); |
keir@20509 | 1379 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 1380 flexarray_set(back, boffset++, "state"); |
keir@20462 | 1381 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 1382 flexarray_set(back, boffset++, "dev"); |
keir@20516 | 1383 flexarray_set(back, boffset++, disk->virtpath); |
keir@20516 | 1384 flexarray_set(back, boffset++, "type"); |
keir@20516 | 1385 flexarray_set(back, boffset++, backend_type); |
keir@20516 | 1386 flexarray_set(back, boffset++, "mode"); |
keir@20516 | 1387 flexarray_set(back, boffset++, disk->readwrite ? "w" : "r"); |
keir@20462 | 1388 |
keir@20516 | 1389 flexarray_set(front, foffset++, "backend-id"); |
keir@20462 | 1390 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", disk->backend_domid)); |
keir@20516 | 1391 flexarray_set(front, foffset++, "state"); |
keir@20462 | 1392 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 1393 flexarray_set(front, foffset++, "virtual-device"); |
keir@20462 | 1394 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", devid)); |
keir@20516 | 1395 flexarray_set(front, foffset++, "device-type"); |
keir@20516 | 1396 flexarray_set(front, foffset++, disk->is_cdrom ? "cdrom" : "disk"); |
keir@20462 | 1397 |
keir@20462 | 1398 if (0 /* protocol != native*/) { |
keir@20516 | 1399 flexarray_set(front, foffset++, "protocol"); |
keir@20516 | 1400 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */ |
keir@20462 | 1401 } |
keir@20462 | 1402 |
keir@20462 | 1403 libxl_device_generic_add(ctx, &device, |
keir@20462 | 1404 libxl_xs_kvs_of_flexarray(ctx, back, boffset), |
keir@20462 | 1405 libxl_xs_kvs_of_flexarray(ctx, front, foffset)); |
keir@20516 | 1406 flexarray_free(back); |
keir@20516 | 1407 flexarray_free(front); |
keir@20462 | 1408 return 0; |
keir@20462 | 1409 } |
keir@20462 | 1410 |
keir@20626 | 1411 int libxl_device_disk_del(struct libxl_ctx *ctx, |
keir@20626 | 1412 libxl_device_disk *disk, int wait) |
keir@20462 | 1413 { |
keir@20626 | 1414 libxl_device device; |
keir@20626 | 1415 int devid; |
keir@20462 | 1416 |
keir@20626 | 1417 devid = device_disk_dev_number(disk->virtpath); |
keir@20626 | 1418 device.backend_domid = disk->backend_domid; |
keir@20626 | 1419 device.backend_devid = devid; |
keir@20626 | 1420 device.backend_kind = |
keir@20626 | 1421 (disk->phystype == PHYSTYPE_PHY) ? DEVICE_VBD : DEVICE_TAP; |
keir@20626 | 1422 device.domid = disk->domid; |
keir@20626 | 1423 device.devid = devid; |
keir@20626 | 1424 device.kind = DEVICE_VBD; |
keir@20626 | 1425 return libxl_device_del(ctx, &device, wait); |
keir@20462 | 1426 } |
keir@20462 | 1427 |
Ian@21849 | 1428 const char * libxl_device_disk_local_attach(struct libxl_ctx *ctx, libxl_device_disk *disk) |
Ian@21849 | 1429 { |
Ian@21849 | 1430 char *dev = NULL; |
Ian@21849 | 1431 int phystype = disk->phystype; |
Ian@21849 | 1432 switch (phystype) { |
Ian@21849 | 1433 case PHYSTYPE_PHY: { |
Ian@21849 | 1434 fprintf(stderr, "attaching PHY disk %s to domain 0\n", disk->physpath); |
Ian@21849 | 1435 dev = disk->physpath; |
Ian@21849 | 1436 break; |
Ian@21849 | 1437 } |
Ian@21849 | 1438 case PHYSTYPE_FILE: |
Ian@21849 | 1439 /* let's pretend is tap:aio for the moment */ |
Ian@21849 | 1440 phystype = PHYSTYPE_AIO; |
Ian@21849 | 1441 case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD: { |
Ian@21849 | 1442 const char *msg; |
Ian@21849 | 1443 if (!tap_ctl_check(&msg)) { |
Ian@21849 | 1444 const char *type = device_disk_string_of_phystype(phystype); |
Ian@21849 | 1445 dev = get_blktap2_device(ctx, disk->physpath, type); |
Ian@21849 | 1446 if (!dev) |
Ian@21849 | 1447 dev = make_blktap2_device(ctx, disk->physpath, type); |
Ian@21849 | 1448 } |
Ian@21849 | 1449 break; |
Ian@21849 | 1450 } |
Ian@21849 | 1451 default: |
Ian@21849 | 1452 XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", phystype); |
Ian@21849 | 1453 break; |
Ian@21849 | 1454 } |
Ian@21849 | 1455 return dev; |
Ian@21849 | 1456 } |
Ian@21849 | 1457 |
Ian@21849 | 1458 int libxl_device_disk_local_detach(struct libxl_ctx *ctx, libxl_device_disk *disk) |
Ian@21849 | 1459 { |
Ian@21849 | 1460 /* Nothing to do for PHYSTYPE_PHY. */ |
Ian@21849 | 1461 |
Ian@21849 | 1462 /* |
Ian@21849 | 1463 * For other device types assume that the blktap2 process is |
Ian@21849 | 1464 * needed by the soon to be started domain and do nothing. |
Ian@21849 | 1465 */ |
Ian@21849 | 1466 |
Ian@21849 | 1467 return 0; |
Ian@21849 | 1468 } |
Ian@21849 | 1469 |
keir@20462 | 1470 /******************************************************************************/ |
keir@20462 | 1471 int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic) |
keir@20462 | 1472 { |
keir@20462 | 1473 flexarray_t *front; |
keir@20462 | 1474 flexarray_t *back; |
keir@20462 | 1475 unsigned int boffset = 0; |
keir@20462 | 1476 unsigned int foffset = 0; |
keir@20462 | 1477 libxl_device device; |
keir@21407 | 1478 char *dompath, **l; |
keir@21407 | 1479 unsigned int nb; |
keir@20462 | 1480 |
keir@20462 | 1481 front = flexarray_make(16, 1); |
keir@20462 | 1482 if (!front) |
keir@20462 | 1483 return ERROR_NOMEM; |
keir@20462 | 1484 back = flexarray_make(16, 1); |
keir@20462 | 1485 if (!back) |
keir@20462 | 1486 return ERROR_NOMEM; |
keir@20462 | 1487 |
keir@21407 | 1488 if (nic->devid == -1) { |
keir@21407 | 1489 if (!(dompath = libxl_xs_get_dompath(ctx, domid))) { |
keir@21407 | 1490 return ERROR_FAIL; |
keir@21407 | 1491 } |
keir@21407 | 1492 if (!(l = libxl_xs_directory(ctx, XBT_NULL, |
keir@21407 | 1493 libxl_sprintf(ctx, "%s/device/vif", dompath), &nb))) { |
keir@21407 | 1494 nic->devid = 0; |
keir@21407 | 1495 } else { |
keir@21407 | 1496 nic->devid = strtoul(l[nb - 1], NULL, 10) + 1; |
keir@21407 | 1497 libxl_free(ctx, l); |
keir@21407 | 1498 } |
keir@21407 | 1499 } |
keir@21407 | 1500 |
keir@20462 | 1501 device.backend_devid = nic->devid; |
keir@20462 | 1502 device.backend_domid = nic->backend_domid; |
keir@20462 | 1503 device.backend_kind = DEVICE_VIF; |
keir@20462 | 1504 device.devid = nic->devid; |
keir@20462 | 1505 device.domid = nic->domid; |
keir@20462 | 1506 device.kind = DEVICE_VIF; |
keir@20462 | 1507 |
keir@20516 | 1508 flexarray_set(back, boffset++, "frontend-id"); |
keir@20462 | 1509 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->domid)); |
keir@20516 | 1510 flexarray_set(back, boffset++, "online"); |
keir@20516 | 1511 flexarray_set(back, boffset++, "1"); |
keir@20516 | 1512 flexarray_set(back, boffset++, "state"); |
keir@20462 | 1513 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 1514 flexarray_set(back, boffset++, "script"); |
keir@20516 | 1515 flexarray_set(back, boffset++, nic->script); |
keir@20516 | 1516 flexarray_set(back, boffset++, "mac"); |
keir@20462 | 1517 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x", |
keir@20462 | 1518 nic->mac[0], nic->mac[1], nic->mac[2], |
keir@20462 | 1519 nic->mac[3], nic->mac[4], nic->mac[5])); |
Ian@21732 | 1520 flexarray_set(back, boffset++, "bridge"); |
Ian@21845 | 1521 flexarray_set(back, boffset++, libxl_strdup(ctx, nic->bridge)); |
keir@20516 | 1522 flexarray_set(back, boffset++, "handle"); |
keir@20462 | 1523 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->devid)); |
keir@20462 | 1524 |
keir@20516 | 1525 flexarray_set(front, foffset++, "backend-id"); |
keir@20462 | 1526 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->backend_domid)); |
keir@20516 | 1527 flexarray_set(front, foffset++, "state"); |
keir@20462 | 1528 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 1529 flexarray_set(front, foffset++, "handle"); |
keir@20462 | 1530 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->devid)); |
keir@20516 | 1531 flexarray_set(front, foffset++, "mac"); |
keir@20462 | 1532 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x", |
keir@20462 | 1533 nic->mac[0], nic->mac[1], nic->mac[2], |
keir@20462 | 1534 nic->mac[3], nic->mac[4], nic->mac[5])); |
keir@20462 | 1535 if (0 /* protocol != native*/) { |
keir@20516 | 1536 flexarray_set(front, foffset++, "protocol"); |
keir@20516 | 1537 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */ |
keir@20462 | 1538 } |
keir@20462 | 1539 |
keir@20462 | 1540 libxl_device_generic_add(ctx, &device, |
keir@20462 | 1541 libxl_xs_kvs_of_flexarray(ctx, back, boffset), |
keir@20462 | 1542 libxl_xs_kvs_of_flexarray(ctx, front, foffset)); |
keir@20462 | 1543 |
keir@20462 | 1544 /* FIXME: wait for plug */ |
keir@20516 | 1545 flexarray_free(back); |
keir@20516 | 1546 flexarray_free(front); |
keir@20462 | 1547 return 0; |
keir@20462 | 1548 } |
keir@20462 | 1549 |
keir@20626 | 1550 int libxl_device_nic_del(struct libxl_ctx *ctx, |
keir@20626 | 1551 libxl_device_nic *nic, int wait) |
keir@20462 | 1552 { |
keir@20626 | 1553 libxl_device device; |
keir@20462 | 1554 |
keir@20626 | 1555 device.backend_devid = nic->devid; |
keir@20626 | 1556 device.backend_domid = nic->backend_domid; |
keir@20626 | 1557 device.backend_kind = DEVICE_VIF; |
keir@20626 | 1558 device.devid = nic->devid; |
keir@20626 | 1559 device.domid = nic->domid; |
keir@20626 | 1560 device.kind = DEVICE_VIF; |
keir@20626 | 1561 |
keir@20626 | 1562 return libxl_device_del(ctx, &device, wait); |
keir@20462 | 1563 } |
keir@20462 | 1564 |
keir@21408 | 1565 libxl_nicinfo *libxl_list_nics(struct libxl_ctx *ctx, uint32_t domid, unsigned int *nb) |
keir@21408 | 1566 { |
keir@21408 | 1567 char *dompath, *nic_path_fe; |
keir@21408 | 1568 char **l; |
keir@21408 | 1569 char *val, *tok; |
keir@21408 | 1570 unsigned int nb_nics, i; |
keir@21408 | 1571 libxl_nicinfo *res, *nics; |
keir@21408 | 1572 |
keir@21408 | 1573 dompath = libxl_xs_get_dompath(ctx, domid); |
keir@21408 | 1574 if (!dompath) { |
keir@21408 | 1575 return NULL; |
keir@21408 | 1576 } |
keir@21408 | 1577 l = libxl_xs_directory(ctx, XBT_NULL, |
keir@21408 | 1578 libxl_sprintf(ctx, "%s/device/vif", dompath), &nb_nics); |
keir@21408 | 1579 if (!l) { |
keir@21408 | 1580 return NULL; |
keir@21408 | 1581 } |
keir@21408 | 1582 res = libxl_calloc(ctx, nb_nics, sizeof (libxl_device_nic)); |
keir@21408 | 1583 if (!res) { |
keir@21408 | 1584 libxl_free(ctx, l); |
keir@21408 | 1585 return NULL; |
keir@21408 | 1586 } |
keir@21408 | 1587 nics = res; |
keir@21408 | 1588 for (*nb = nb_nics; nb_nics > 0; --nb_nics, ++l, ++nics) { |
keir@21408 | 1589 nic_path_fe = libxl_sprintf(ctx, "%s/device/vif/%s", dompath, *l); |
keir@21408 | 1590 |
keir@21408 | 1591 nics->backend = libxl_xs_read(ctx, XBT_NULL, |
keir@21408 | 1592 libxl_sprintf(ctx, "%s/backend", nic_path_fe)); |
keir@21408 | 1593 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", nic_path_fe)); |
keir@21408 | 1594 nics->backend_id = val ? strtoul(val, NULL, 10) : -1; |
keir@21408 | 1595 |
keir@21408 | 1596 nics->devid = strtoul(*l, NULL, 10); |
keir@21408 | 1597 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", nic_path_fe)); |
keir@21408 | 1598 nics->state = val ? strtoul(val, NULL, 10) : -1; |
keir@21408 | 1599 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", nic_path_fe)); |
keir@21408 | 1600 for (i = 0, tok = strtok(val, ":"); tok && (i < 6); |
keir@21408 | 1601 ++i, tok = strtok(NULL, ":")) { |
keir@21408 | 1602 nics->mac[i] = strtoul(tok, NULL, 16); |
keir@21408 | 1603 } |
keir@21408 | 1604 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/event-channel", nic_path_fe)); |
keir@21408 | 1605 nics->evtch = val ? strtol(val, NULL, 10) : -1; |
keir@21408 | 1606 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/tx-ring-ref", nic_path_fe)); |
keir@21408 | 1607 nics->rref_tx = val ? strtol(val, NULL, 10) : -1; |
keir@21408 | 1608 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/rx-ring-ref", nic_path_fe)); |
keir@21408 | 1609 nics->rref_rx = val ? strtol(val, NULL, 10) : -1; |
keir@21408 | 1610 nics->frontend = libxl_xs_read(ctx, XBT_NULL, |
keir@21408 | 1611 libxl_sprintf(ctx, "%s/frontend", nics->backend)); |
keir@21408 | 1612 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", nics->backend)); |
keir@21408 | 1613 nics->frontend_id = val ? strtoul(val, NULL, 10) : -1; |
keir@21408 | 1614 nics->script = libxl_xs_read(ctx, XBT_NULL, |
keir@21408 | 1615 libxl_sprintf(ctx, "%s/script", nics->backend)); |
keir@21408 | 1616 |
keir@21408 | 1617 libxl_free(ctx, nic_path_fe); |
keir@21408 | 1618 } |
keir@21408 | 1619 |
keir@21408 | 1620 libxl_free(ctx, l); |
keir@21408 | 1621 return res; |
keir@21408 | 1622 } |
keir@21408 | 1623 |
keir@21580 | 1624 /******************************************************************************/ |
keir@21580 | 1625 int libxl_device_net2_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2) |
keir@21580 | 1626 { |
keir@21580 | 1627 flexarray_t *front, *back; |
keir@21580 | 1628 unsigned int boffset = 0, foffset = 0; |
keir@21580 | 1629 libxl_device device; |
keir@21580 | 1630 char *dompath, *dom, **l; |
keir@21580 | 1631 unsigned int nb; |
keir@21580 | 1632 |
keir@21580 | 1633 front = flexarray_make(16, 1); |
keir@21580 | 1634 if (!front) |
keir@21580 | 1635 return ERROR_NOMEM; |
keir@21580 | 1636 back = flexarray_make(16, 1); |
keir@21580 | 1637 if (!back) |
keir@21580 | 1638 return ERROR_NOMEM; |
keir@21580 | 1639 |
keir@21580 | 1640 if (!(dompath = libxl_xs_get_dompath(ctx, domid))) { |
keir@21580 | 1641 return ERROR_FAIL; |
keir@21580 | 1642 } |
keir@21580 | 1643 dom = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/name", dompath)); |
keir@21580 | 1644 |
keir@21580 | 1645 if (net2->devid == -1) { |
keir@21580 | 1646 if (!(l = libxl_xs_directory(ctx, XBT_NULL, |
keir@21580 | 1647 libxl_sprintf(ctx, "%s/device/vif2", dompath), &nb))) { |
keir@21580 | 1648 net2->devid = 0; |
keir@21580 | 1649 } else { |
keir@21580 | 1650 net2->devid = strtoul(l[nb - 1], NULL, 10) + 1; |
keir@21580 | 1651 libxl_free(ctx, l); |
keir@21580 | 1652 } |
keir@21580 | 1653 } |
keir@21580 | 1654 |
keir@21580 | 1655 device.backend_devid = net2->devid; |
keir@21580 | 1656 device.backend_domid = net2->backend_domid; |
keir@21580 | 1657 device.backend_kind = DEVICE_VIF2; |
keir@21580 | 1658 device.devid = net2->devid; |
keir@21580 | 1659 device.domid = net2->domid; |
keir@21580 | 1660 device.kind = DEVICE_VIF2; |
keir@21580 | 1661 |
keir@21580 | 1662 flexarray_set(back, boffset++, "domain"); |
keir@21580 | 1663 flexarray_set(back, boffset++, dom); |
keir@21580 | 1664 flexarray_set(back, boffset++, "frontend-id"); |
keir@21580 | 1665 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->domid)); |
keir@21580 | 1666 |
keir@21580 | 1667 flexarray_set(back, boffset++, "local-trusted"); |
keir@21580 | 1668 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->back_trusted)); |
keir@21580 | 1669 flexarray_set(back, boffset++, "mac"); |
keir@21580 | 1670 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x", |
keir@21580 | 1671 net2->back_mac[0], net2->back_mac[1], |
keir@21580 | 1672 net2->back_mac[2], net2->back_mac[3], |
keir@21580 | 1673 net2->back_mac[4], net2->back_mac[5])); |
keir@21580 | 1674 |
keir@21580 | 1675 flexarray_set(back, boffset++, "remote-trusted"); |
keir@21580 | 1676 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->trusted)); |
keir@21580 | 1677 flexarray_set(back, boffset++, "remote-mac"); |
keir@21580 | 1678 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x", |
keir@21580 | 1679 net2->front_mac[0], net2->front_mac[1], |
keir@21580 | 1680 net2->front_mac[2], net2->front_mac[3], |
keir@21580 | 1681 net2->front_mac[4], net2->front_mac[5])); |
keir@21580 | 1682 |
keir@21580 | 1683 flexarray_set(back, boffset++, "max-bypasses"); |
keir@21580 | 1684 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->max_bypasses)); |
keir@21580 | 1685 flexarray_set(back, boffset++, "filter-mac"); |
keir@21580 | 1686 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", !!(net2->filter_mac))); |
keir@21580 | 1687 flexarray_set(back, boffset++, "handle"); |
keir@21580 | 1688 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", net2->devid)); |
keir@21580 | 1689 flexarray_set(back, boffset++, "online"); |
keir@21580 | 1690 flexarray_set(back, boffset++, "1"); |
keir@21580 | 1691 flexarray_set(back, boffset++, "state"); |
keir@21580 | 1692 flexarray_set(back, boffset++, "1"); |
keir@21580 | 1693 |
keir@21580 | 1694 flexarray_set(front, foffset++, "backend-id"); |
keir@21580 | 1695 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->backend_domid)); |
keir@21580 | 1696 |
keir@21580 | 1697 flexarray_set(front, foffset++, "local-trusted"); |
keir@21580 | 1698 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->trusted)); |
keir@21580 | 1699 flexarray_set(front, foffset++, "mac"); |
keir@21580 | 1700 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x", |
keir@21580 | 1701 net2->front_mac[0], net2->front_mac[1], |
keir@21580 | 1702 net2->front_mac[2], net2->front_mac[3], |
keir@21580 | 1703 net2->front_mac[4], net2->front_mac[5])); |
keir@21580 | 1704 |
keir@21580 | 1705 flexarray_set(front, foffset++, "remote-trusted"); |
keir@21580 | 1706 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", net2->back_trusted)); |
keir@21580 | 1707 flexarray_set(front, foffset++, "remote-mac"); |
keir@21580 | 1708 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x", |
keir@21580 | 1709 net2->back_mac[0], net2->back_mac[1], |
keir@21580 | 1710 net2->back_mac[2], net2->back_mac[3], |
keir@21580 | 1711 net2->back_mac[4], net2->back_mac[5])); |
keir@21580 | 1712 |
keir@21580 | 1713 flexarray_set(front, foffset++, "filter-mac"); |
keir@21580 | 1714 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", !!(net2->filter_mac))); |
keir@21580 | 1715 flexarray_set(front, foffset++, "state"); |
keir@21580 | 1716 flexarray_set(front, foffset++, "1"); |
keir@21580 | 1717 |
keir@21580 | 1718 libxl_device_generic_add(ctx, &device, |
keir@21580 | 1719 libxl_xs_kvs_of_flexarray(ctx, back, boffset), |
keir@21580 | 1720 libxl_xs_kvs_of_flexarray(ctx, front, foffset)); |
keir@21580 | 1721 |
keir@21580 | 1722 /* FIXME: wait for plug */ |
keir@21580 | 1723 flexarray_free(back); |
keir@21580 | 1724 flexarray_free(front); |
keir@21580 | 1725 return 0; |
keir@21580 | 1726 } |
keir@21408 | 1727 |
keir@21581 | 1728 libxl_net2info *libxl_device_net2_list(struct libxl_ctx *ctx, uint32_t domid, unsigned int *nb) |
keir@21581 | 1729 { |
keir@21581 | 1730 char *dompath, *net2_path_fe; |
keir@21581 | 1731 char **l; |
keir@21581 | 1732 char *val, *tok; |
keir@21581 | 1733 unsigned int nb_net2s, i; |
keir@21581 | 1734 libxl_net2info *res, *net2s; |
keir@21581 | 1735 |
keir@21581 | 1736 dompath = libxl_xs_get_dompath(ctx, domid); |
keir@21581 | 1737 if (!dompath) { |
keir@21581 | 1738 return NULL; |
keir@21581 | 1739 } |
keir@21581 | 1740 l = libxl_xs_directory(ctx, XBT_NULL, |
keir@21581 | 1741 libxl_sprintf(ctx, "%s/device/vif2", dompath), &nb_net2s); |
keir@21581 | 1742 if (!l) { |
keir@21581 | 1743 return NULL; |
keir@21581 | 1744 } |
keir@21581 | 1745 res = libxl_calloc(ctx, nb_net2s, sizeof (libxl_net2info)); |
keir@21581 | 1746 if (!res) { |
keir@21581 | 1747 libxl_free(ctx, l); |
keir@21581 | 1748 return NULL; |
keir@21581 | 1749 } |
keir@21581 | 1750 net2s = res; |
keir@21581 | 1751 for (*nb = nb_net2s; nb_net2s > 0; --nb_net2s, ++l, ++net2s) { |
keir@21581 | 1752 net2_path_fe = libxl_sprintf(ctx, "%s/device/vif2/%s", dompath, *l); |
keir@21581 | 1753 |
keir@21581 | 1754 net2s->backend = libxl_xs_read(ctx, XBT_NULL, |
keir@21581 | 1755 libxl_sprintf(ctx, "%s/backend", net2_path_fe)); |
keir@21581 | 1756 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", net2_path_fe)); |
keir@21581 | 1757 net2s->backend_id = val ? strtoul(val, NULL, 10) : -1; |
keir@21581 | 1758 |
keir@21581 | 1759 net2s->devid = strtoul(*l, NULL, 10); |
keir@21581 | 1760 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", net2_path_fe)); |
keir@21581 | 1761 net2s->state = val ? strtoul(val, NULL, 10) : -1; |
keir@21581 | 1762 |
keir@21581 | 1763 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/mac", net2_path_fe)); |
keir@21581 | 1764 for (i = 0, tok = strtok(val, ":"); tok && (i < 6); |
keir@21581 | 1765 ++i, tok = strtok(NULL, ":")) { |
keir@21581 | 1766 net2s->mac[i] = strtoul(tok, NULL, 16); |
keir@21581 | 1767 } |
keir@21581 | 1768 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/remote-trusted", net2_path_fe)); |
keir@21581 | 1769 net2s->trusted = val ? strtoul(val, NULL, 10) : -1; |
keir@21581 | 1770 |
keir@21581 | 1771 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/remote-mac", net2_path_fe)); |
keir@21581 | 1772 for (i = 0, tok = strtok(val, ":"); tok && (i < 6); |
keir@21581 | 1773 ++i, tok = strtok(NULL, ":")) { |
keir@21581 | 1774 net2s->back_mac[i] = strtoul(tok, NULL, 16); |
keir@21581 | 1775 } |
keir@21581 | 1776 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/filter-mac", net2_path_fe)); |
keir@21581 | 1777 net2s->filter_mac = val ? strtoul(val, NULL, 10) : -1; |
keir@21581 | 1778 |
keir@21581 | 1779 net2s->frontend = libxl_xs_read(ctx, XBT_NULL, |
keir@21581 | 1780 libxl_sprintf(ctx, "%s/frontend", net2s->backend)); |
keir@21581 | 1781 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", net2s->backend)); |
keir@21581 | 1782 net2s->frontend_id = val ? strtoul(val, NULL, 10) : -1; |
keir@21581 | 1783 libxl_free(ctx, net2_path_fe); |
keir@21581 | 1784 } |
keir@21581 | 1785 |
keir@21581 | 1786 libxl_free(ctx, l); |
keir@21581 | 1787 return res; |
keir@21581 | 1788 } |
keir@21581 | 1789 |
keir@21582 | 1790 int libxl_device_net2_del(struct libxl_ctx *ctx, libxl_device_net2 *net2, int wait) |
keir@21582 | 1791 { |
keir@21582 | 1792 libxl_device device; |
keir@21582 | 1793 |
keir@21582 | 1794 device.backend_devid = net2->devid; |
keir@21582 | 1795 device.backend_domid = net2->backend_domid; |
keir@21582 | 1796 device.backend_kind = DEVICE_VIF2; |
keir@21582 | 1797 device.devid = net2->devid; |
keir@21582 | 1798 device.domid = net2->domid; |
keir@21582 | 1799 device.kind = DEVICE_VIF2; |
keir@21582 | 1800 |
keir@21582 | 1801 return libxl_device_del(ctx, &device, wait); |
keir@21582 | 1802 } |
keir@21582 | 1803 |
keir@21581 | 1804 |
keir@20462 | 1805 /******************************************************************************/ |
keir@20509 | 1806 int libxl_device_console_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_console *console) |
keir@20462 | 1807 { |
keir@20509 | 1808 flexarray_t *front; |
keir@20509 | 1809 flexarray_t *back; |
keir@20509 | 1810 unsigned int boffset = 0; |
keir@20509 | 1811 unsigned int foffset = 0; |
keir@20509 | 1812 libxl_device device; |
keir@20509 | 1813 |
keir@20509 | 1814 if (console->build_state) { |
keir@20509 | 1815 xs_transaction_t t; |
keir@20509 | 1816 char **ents = (char **) libxl_calloc(ctx, 9, sizeof(char *)); |
keir@20516 | 1817 ents[0] = "console/port"; |
keir@20509 | 1818 ents[1] = libxl_sprintf(ctx, "%"PRIu32, console->build_state->console_port); |
keir@20516 | 1819 ents[2] = "console/ring-ref"; |
keir@20509 | 1820 ents[3] = libxl_sprintf(ctx, "%lu", console->build_state->console_mfn); |
keir@20516 | 1821 ents[4] = "console/limit"; |
keir@20509 | 1822 ents[5] = libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT); |
keir@20516 | 1823 ents[6] = "console/type"; |
keir@20509 | 1824 if (console->constype == CONSTYPE_XENCONSOLED) |
keir@20509 | 1825 ents[7] = "xenconsoled"; |
keir@20509 | 1826 else |
keir@20509 | 1827 ents[7] = "ioemu"; |
keir@20509 | 1828 retry_transaction: |
keir@20509 | 1829 t = xs_transaction_start(ctx->xsh); |
keir@20516 | 1830 libxl_xs_writev(ctx, t, libxl_xs_get_dompath(ctx, console->domid), ents); |
keir@20509 | 1831 if (!xs_transaction_end(ctx->xsh, t, 0)) |
keir@20509 | 1832 if (errno == EAGAIN) |
keir@20509 | 1833 goto retry_transaction; |
keir@20509 | 1834 } |
keir@20509 | 1835 |
keir@20509 | 1836 front = flexarray_make(16, 1); |
keir@20509 | 1837 if (!front) |
keir@20509 | 1838 return ERROR_NOMEM; |
keir@20509 | 1839 back = flexarray_make(16, 1); |
keir@20509 | 1840 if (!back) |
keir@20509 | 1841 return ERROR_NOMEM; |
keir@20509 | 1842 |
keir@20509 | 1843 device.backend_devid = console->devid; |
keir@20509 | 1844 device.backend_domid = console->backend_domid; |
keir@20509 | 1845 device.backend_kind = DEVICE_CONSOLE; |
keir@20509 | 1846 device.devid = console->devid; |
keir@20509 | 1847 device.domid = console->domid; |
keir@20509 | 1848 device.kind = DEVICE_CONSOLE; |
keir@20509 | 1849 |
keir@20516 | 1850 flexarray_set(back, boffset++, "frontend-id"); |
keir@20509 | 1851 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", console->domid)); |
keir@20516 | 1852 flexarray_set(back, boffset++, "online"); |
keir@20516 | 1853 flexarray_set(back, boffset++, "1"); |
keir@20516 | 1854 flexarray_set(back, boffset++, "state"); |
keir@20509 | 1855 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 1856 flexarray_set(back, boffset++, "domain"); |
keir@20516 | 1857 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid)); |
keir@20516 | 1858 flexarray_set(back, boffset++, "protocol"); |
keir@20516 | 1859 flexarray_set(back, boffset++, LIBXL_XENCONSOLE_PROTOCOL); |
keir@20509 | 1860 |
keir@20516 | 1861 flexarray_set(front, foffset++, "backend-id"); |
keir@20509 | 1862 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", console->backend_domid)); |
keir@20516 | 1863 flexarray_set(front, foffset++, "state"); |
keir@20509 | 1864 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 1865 flexarray_set(front, foffset++, "limit"); |
keir@20509 | 1866 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", LIBXL_XENCONSOLE_LIMIT)); |
keir@20516 | 1867 flexarray_set(front, foffset++, "protocol"); |
keir@20516 | 1868 flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL); |
keir@20516 | 1869 flexarray_set(front, foffset++, "type"); |
keir@20509 | 1870 if (console->constype == CONSTYPE_XENCONSOLED) |
keir@20516 | 1871 flexarray_set(front, foffset++, "xenconsoled"); |
keir@20509 | 1872 else |
keir@20516 | 1873 flexarray_set(front, foffset++, "ioemu"); |
keir@20509 | 1874 |
keir@20509 | 1875 libxl_device_generic_add(ctx, &device, |
keir@20509 | 1876 libxl_xs_kvs_of_flexarray(ctx, back, boffset), |
keir@20509 | 1877 libxl_xs_kvs_of_flexarray(ctx, front, foffset)); |
keir@20516 | 1878 flexarray_free(back); |
keir@20516 | 1879 flexarray_free(front); |
keir@20509 | 1880 |
keir@20509 | 1881 return 0; |
keir@20509 | 1882 } |
keir@20509 | 1883 |
keir@20509 | 1884 /******************************************************************************/ |
keir@20509 | 1885 int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb) |
keir@20509 | 1886 { |
keir@20509 | 1887 flexarray_t *front; |
keir@20509 | 1888 flexarray_t *back; |
keir@20509 | 1889 unsigned int boffset = 0; |
keir@20509 | 1890 unsigned int foffset = 0; |
keir@20509 | 1891 libxl_device device; |
keir@20509 | 1892 |
keir@20509 | 1893 front = flexarray_make(16, 1); |
keir@20509 | 1894 if (!front) |
keir@20509 | 1895 return ERROR_NOMEM; |
keir@20509 | 1896 back = flexarray_make(16, 1); |
keir@20509 | 1897 if (!back) |
keir@20509 | 1898 return ERROR_NOMEM; |
keir@20509 | 1899 |
keir@20509 | 1900 device.backend_devid = vkb->devid; |
keir@20509 | 1901 device.backend_domid = vkb->backend_domid; |
keir@20509 | 1902 device.backend_kind = DEVICE_VKBD; |
keir@20509 | 1903 device.devid = vkb->devid; |
keir@20509 | 1904 device.domid = vkb->domid; |
keir@20509 | 1905 device.kind = DEVICE_VKBD; |
keir@20509 | 1906 |
keir@20516 | 1907 flexarray_set(back, boffset++, "frontend-id"); |
keir@20509 | 1908 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vkb->domid)); |
keir@20516 | 1909 flexarray_set(back, boffset++, "online"); |
keir@20516 | 1910 flexarray_set(back, boffset++, "1"); |
keir@20516 | 1911 flexarray_set(back, boffset++, "state"); |
keir@20509 | 1912 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 1913 flexarray_set(back, boffset++, "domain"); |
keir@20516 | 1914 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid)); |
keir@20509 | 1915 |
keir@20516 | 1916 flexarray_set(front, foffset++, "backend-id"); |
keir@20509 | 1917 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vkb->backend_domid)); |
keir@20516 | 1918 flexarray_set(front, foffset++, "state"); |
keir@20509 | 1919 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20509 | 1920 |
keir@20509 | 1921 libxl_device_generic_add(ctx, &device, |
keir@20509 | 1922 libxl_xs_kvs_of_flexarray(ctx, back, boffset), |
keir@20509 | 1923 libxl_xs_kvs_of_flexarray(ctx, front, foffset)); |
keir@20516 | 1924 flexarray_free(back); |
keir@20516 | 1925 flexarray_free(front); |
keir@20509 | 1926 |
keir@20509 | 1927 return 0; |
keir@20462 | 1928 } |
keir@20462 | 1929 |
keir@20462 | 1930 int libxl_device_vkb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid) |
keir@20462 | 1931 { |
keir@20462 | 1932 return ERROR_NI; |
keir@20462 | 1933 } |
keir@20462 | 1934 |
keir@20462 | 1935 int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid) |
keir@20462 | 1936 { |
keir@20462 | 1937 return ERROR_NI; |
keir@20462 | 1938 } |
keir@20462 | 1939 |
keir@20637 | 1940 libxl_device_disk *libxl_device_disk_list(struct libxl_ctx *ctx, uint32_t domid, int *num) |
keir@20637 | 1941 { |
keir@20637 | 1942 char *be_path_tap, *be_path_vbd; |
keir@21411 | 1943 libxl_device_disk *dend, *disks, *ret = NULL; |
keir@21411 | 1944 char **b, **l = NULL; |
keir@20637 | 1945 unsigned int numl; |
keir@20637 | 1946 char *type; |
keir@20637 | 1947 |
keir@20637 | 1948 be_path_vbd = libxl_sprintf(ctx, "%s/backend/vbd/%d", libxl_xs_get_dompath(ctx, 0), domid); |
keir@20637 | 1949 be_path_tap = libxl_sprintf(ctx, "%s/backend/tap/%d", libxl_xs_get_dompath(ctx, 0), domid); |
keir@20637 | 1950 |
keir@21411 | 1951 b = l = libxl_xs_directory(ctx, XBT_NULL, be_path_vbd, &numl); |
keir@20637 | 1952 if (l) { |
keir@21411 | 1953 ret = realloc(ret, sizeof(libxl_device_disk) * numl); |
keir@21411 | 1954 disks = ret; |
keir@21411 | 1955 *num = numl; |
keir@21411 | 1956 dend = ret + *num; |
keir@21411 | 1957 for (; disks < dend; ++disks, ++l) { |
keir@21411 | 1958 disks->backend_domid = 0; |
keir@21411 | 1959 disks->domid = domid; |
keir@21411 | 1960 disks->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/params", be_path_vbd, *l)); |
keir@21411 | 1961 libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/type", be_path_vbd, *l)), &(disks->phystype)); |
keir@21411 | 1962 disks->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/dev", be_path_vbd, *l)); |
keir@21411 | 1963 disks->unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/removable", be_path_vbd, *l))); |
keir@21411 | 1964 if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/mode", be_path_vbd, *l)), "w")) |
keir@21411 | 1965 disks->readwrite = 1; |
keir@20637 | 1966 else |
keir@21411 | 1967 disks->readwrite = 0; |
keir@21411 | 1968 type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/frontend", be_path_vbd, *l)))); |
keir@21411 | 1969 disks->is_cdrom = !strcmp(type, "cdrom"); |
keir@20637 | 1970 } |
keir@21411 | 1971 libxl_free(ctx, b); |
keir@20637 | 1972 } |
keir@21411 | 1973 b = l = libxl_xs_directory(ctx, XBT_NULL, be_path_tap, &numl); |
keir@20637 | 1974 if (l) { |
keir@21411 | 1975 ret = realloc(ret, sizeof(libxl_device_disk) * (*num + numl)); |
keir@21411 | 1976 disks = ret + *num; |
keir@21411 | 1977 *num += numl; |
keir@21411 | 1978 for (dend = ret + *num; disks < dend; ++disks, ++l) { |
keir@21411 | 1979 disks->backend_domid = 0; |
keir@21411 | 1980 disks->domid = domid; |
keir@21411 | 1981 disks->physpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/params", be_path_tap, *l)); |
keir@21411 | 1982 libxl_string_to_phystype(ctx, libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/type", be_path_tap, *l)), &(disks->phystype)); |
keir@21411 | 1983 disks->virtpath = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/dev", be_path_tap, *l)); |
keir@21411 | 1984 disks->unpluggable = atoi(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/removable", be_path_tap, *l))); |
keir@21411 | 1985 if (!strcmp(libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/mode", be_path_tap, *l)), "w")) |
keir@21411 | 1986 disks->readwrite = 1; |
keir@20637 | 1987 else |
keir@21411 | 1988 disks->readwrite = 0; |
keir@21411 | 1989 type = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/device-type", libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/%s/frontend", be_path_tap, *l)))); |
keir@21411 | 1990 disks->is_cdrom = !strcmp(type, "cdrom"); |
keir@20637 | 1991 } |
keir@21411 | 1992 libxl_free(ctx, b); |
keir@20637 | 1993 } |
keir@21411 | 1994 return ret; |
keir@21411 | 1995 } |
keir@21411 | 1996 |
keir@21411 | 1997 int libxl_device_disk_getinfo(struct libxl_ctx *ctx, uint32_t domid, |
keir@21411 | 1998 libxl_device_disk *disk, libxl_diskinfo *diskinfo) |
keir@21411 | 1999 { |
keir@21411 | 2000 char *dompath, *diskpath; |
keir@21411 | 2001 char *val; |
keir@21411 | 2002 |
keir@21411 | 2003 dompath = libxl_xs_get_dompath(ctx, domid); |
keir@21411 | 2004 diskinfo->devid = device_disk_dev_number(disk->virtpath); |
keir@21411 | 2005 |
keir@21411 | 2006 /* tap devices entries in xenstore are written as vbd devices. */ |
keir@21411 | 2007 diskpath = libxl_sprintf(ctx, "%s/device/vbd/%d", dompath, diskinfo->devid); |
keir@21411 | 2008 diskinfo->backend = libxl_xs_read(ctx, XBT_NULL, |
keir@21411 | 2009 libxl_sprintf(ctx, "%s/backend", diskpath)); |
keir@21411 | 2010 if (!diskinfo->backend) { |
keir@21411 | 2011 return ERROR_FAIL; |
keir@21411 | 2012 } |
keir@21411 | 2013 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/backend-id", diskpath)); |
keir@21411 | 2014 diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1; |
keir@21411 | 2015 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/state", diskpath)); |
keir@21411 | 2016 diskinfo->state = val ? strtoul(val, NULL, 10) : -1; |
keir@21411 | 2017 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/event-channel", diskpath)); |
keir@21411 | 2018 diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1; |
keir@21411 | 2019 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/ring-ref", diskpath)); |
keir@21411 | 2020 diskinfo->rref = val ? strtoul(val, NULL, 10) : -1; |
keir@21411 | 2021 diskinfo->frontend = libxl_xs_read(ctx, XBT_NULL, |
keir@21411 | 2022 libxl_sprintf(ctx, "%s/frontend", diskinfo->backend)); |
keir@21411 | 2023 val = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend-id", diskinfo->backend)); |
keir@21411 | 2024 diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1; |
keir@21411 | 2025 |
keir@21411 | 2026 return 0; |
keir@20637 | 2027 } |
keir@20637 | 2028 |
keir@20637 | 2029 int libxl_cdrom_insert(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk) |
keir@20637 | 2030 { |
keir@20637 | 2031 int num, i; |
keir@20637 | 2032 uint32_t stubdomid; |
keir@20637 | 2033 libxl_device_disk *disks; |
keir@20637 | 2034 |
keir@20637 | 2035 if (!disk->physpath) { |
keir@20637 | 2036 disk->physpath = ""; |
keir@20637 | 2037 disk->phystype = PHYSTYPE_PHY; |
keir@20637 | 2038 } |
keir@20637 | 2039 disks = libxl_device_disk_list(ctx, domid, &num); |
keir@20637 | 2040 for (i = 0; i < num; i++) { |
keir@20637 | 2041 if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath)) |
keir@20637 | 2042 /* found */ |
keir@20637 | 2043 break; |
keir@20637 | 2044 } |
keir@20637 | 2045 if (i == num) { |
keir@20637 | 2046 XL_LOG(ctx, XL_LOG_ERROR, "Virtual device not found"); |
keir@20637 | 2047 return -1; |
keir@20637 | 2048 } |
keir@20637 | 2049 libxl_device_disk_del(ctx, disks + i, 1); |
keir@20637 | 2050 libxl_device_disk_add(ctx, domid, disk); |
keir@20637 | 2051 stubdomid = libxl_get_stubdom_id(ctx, domid); |
keir@20637 | 2052 if (stubdomid) { |
keir@20781 | 2053 disks[i].domid = stubdomid; |
keir@20637 | 2054 libxl_device_disk_del(ctx, disks + i, 1); |
keir@20781 | 2055 disk->domid = stubdomid; |
keir@20637 | 2056 libxl_device_disk_add(ctx, stubdomid, disk); |
keir@20781 | 2057 disk->domid = domid; |
keir@20637 | 2058 } |
keir@20637 | 2059 return 0; |
keir@20637 | 2060 } |
keir@20637 | 2061 |
keir@20462 | 2062 /******************************************************************************/ |
keir@20509 | 2063 static int libxl_build_xenpv_qemu_args(struct libxl_ctx *ctx, |
keir@20509 | 2064 libxl_device_vfb *vfb, |
keir@20509 | 2065 int num_console, |
keir@20509 | 2066 libxl_device_console *console, |
keir@20860 | 2067 libxl_device_model_info *info) |
keir@20860 | 2068 { |
keir@20509 | 2069 int i = 0, j = 0, num = 0; |
keir@20509 | 2070 memset(info, 0x00, sizeof(libxl_device_model_info)); |
keir@20509 | 2071 |
keir@20509 | 2072 info->vnc = vfb->vnc; |
keir@20509 | 2073 if (vfb->vnclisten) |
Ian@21845 | 2074 info->vnclisten = libxl_strdup(ctx, vfb->vnclisten); |
keir@20509 | 2075 info->vncdisplay = vfb->vncdisplay; |
keir@20509 | 2076 info->vncunused = vfb->vncunused; |
keir@21362 | 2077 if (vfb->vncpasswd) |
keir@21362 | 2078 info->vncpasswd = vfb->vncpasswd; |
keir@20509 | 2079 if (vfb->keymap) |
Ian@21845 | 2080 info->keymap = libxl_strdup(ctx, vfb->keymap); |
keir@20509 | 2081 info->sdl = vfb->sdl; |
keir@20509 | 2082 info->opengl = vfb->opengl; |
keir@20509 | 2083 for (i = 0; i < num_console; i++) { |
keir@20509 | 2084 if (console->constype == CONSTYPE_IOEMU) |
keir@20509 | 2085 num++; |
keir@20509 | 2086 } |
keir@20509 | 2087 if (num > 0) { |
keir@20860 | 2088 uint32_t guest_domid; |
keir@20860 | 2089 if (libxl_is_stubdom(ctx, vfb->domid, &guest_domid)) { |
keir@20599 | 2090 char *filename; |
keir@20599 | 2091 char *name = libxl_sprintf(ctx, "qemu-dm-%s", libxl_domid_to_name(ctx, guest_domid)); |
keir@20599 | 2092 libxl_create_logfile(ctx, name, &filename); |
keir@20599 | 2093 info->serial = libxl_sprintf(ctx, "file:%s", filename); |
keir@20599 | 2094 free(filename); |
keir@20599 | 2095 } else { |
keir@20599 | 2096 info->serial = "pty"; |
keir@20599 | 2097 } |
keir@20509 | 2098 num--; |
keir@20509 | 2099 } |
keir@20509 | 2100 if (num > 0) { |
keir@20509 | 2101 info->extra = (char **) libxl_calloc(ctx, num * 2 + 1, sizeof(char *)); |
keir@20509 | 2102 for (j = 0; j < num * 2; j = j + 2) { |
keir@20509 | 2103 info->extra[j] = "-serial"; |
keir@20509 | 2104 info->extra[j + 1] = "pty"; |
keir@20509 | 2105 } |
keir@20509 | 2106 info->extra[j] = NULL; |
keir@20509 | 2107 } |
keir@20509 | 2108 info->domid = vfb->domid; |
keir@20509 | 2109 info->dom_name = libxl_domid_to_name(ctx, vfb->domid); |
keir@21376 | 2110 info->device_model = libxl_abs_path(ctx, "qemu-dm", libxl_libexec_path()); |
keir@20509 | 2111 info->type = XENPV; |
keir@20509 | 2112 return 0; |
keir@20509 | 2113 } |
keir@20509 | 2114 |
keir@20509 | 2115 int libxl_create_xenpv_qemu(struct libxl_ctx *ctx, libxl_device_vfb *vfb, |
keir@20514 | 2116 int num_console, libxl_device_console *console, |
keir@20514 | 2117 struct libxl_device_model_starting **starting_r) |
keir@20509 | 2118 { |
keir@20509 | 2119 libxl_device_model_info info; |
keir@20509 | 2120 |
keir@20509 | 2121 libxl_build_xenpv_qemu_args(ctx, vfb, num_console, console, &info); |
keir@20542 | 2122 libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r); |
keir@20509 | 2123 return 0; |
keir@20509 | 2124 } |
keir@20509 | 2125 |
keir@20509 | 2126 int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb) |
keir@20462 | 2127 { |
keir@20509 | 2128 flexarray_t *front; |
keir@20509 | 2129 flexarray_t *back; |
keir@20509 | 2130 unsigned int boffset = 0; |
keir@20509 | 2131 unsigned int foffset = 0; |
keir@20509 | 2132 libxl_device device; |
keir@20509 | 2133 |
keir@20509 | 2134 front = flexarray_make(16, 1); |
keir@20509 | 2135 if (!front) |
keir@20509 | 2136 return ERROR_NOMEM; |
keir@20509 | 2137 back = flexarray_make(16, 1); |
keir@20509 | 2138 if (!back) |
keir@20509 | 2139 return ERROR_NOMEM; |
keir@20509 | 2140 |
keir@20509 | 2141 device.backend_devid = vfb->devid; |
keir@20509 | 2142 device.backend_domid = vfb->backend_domid; |
keir@20509 | 2143 device.backend_kind = DEVICE_VFB; |
keir@20509 | 2144 device.devid = vfb->devid; |
keir@20509 | 2145 device.domid = vfb->domid; |
keir@20509 | 2146 device.kind = DEVICE_VFB; |
keir@20509 | 2147 |
keir@20516 | 2148 flexarray_set(back, boffset++, "frontend-id"); |
keir@20509 | 2149 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->domid)); |
keir@20516 | 2150 flexarray_set(back, boffset++, "online"); |
keir@20516 | 2151 flexarray_set(back, boffset++, "1"); |
keir@20516 | 2152 flexarray_set(back, boffset++, "state"); |
keir@20509 | 2153 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 2154 flexarray_set(back, boffset++, "domain"); |
keir@20516 | 2155 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid)); |
keir@20516 | 2156 flexarray_set(back, boffset++, "vnc"); |
keir@20509 | 2157 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vnc)); |
keir@20516 | 2158 flexarray_set(back, boffset++, "vnclisten"); |
keir@20516 | 2159 flexarray_set(back, boffset++, vfb->vnclisten); |
keir@21362 | 2160 flexarray_set(back, boffset++, "vncpasswd"); |
keir@21362 | 2161 flexarray_set(back, boffset++, vfb->vncpasswd); |
keir@20516 | 2162 flexarray_set(back, boffset++, "vncdisplay"); |
keir@20509 | 2163 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncdisplay)); |
keir@20516 | 2164 flexarray_set(back, boffset++, "vncunused"); |
keir@20509 | 2165 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->vncunused)); |
keir@20516 | 2166 flexarray_set(back, boffset++, "sdl"); |
keir@20509 | 2167 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->sdl)); |
keir@20516 | 2168 flexarray_set(back, boffset++, "opengl"); |
keir@20509 | 2169 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", vfb->opengl)); |
keir@20509 | 2170 if (vfb->xauthority) { |
keir@20516 | 2171 flexarray_set(back, boffset++, "xauthority"); |
keir@20516 | 2172 flexarray_set(back, boffset++, vfb->xauthority); |
keir@20509 | 2173 } |
keir@20509 | 2174 if (vfb->display) { |
keir@20516 | 2175 flexarray_set(back, boffset++, "display"); |
keir@20516 | 2176 flexarray_set(back, boffset++, vfb->display); |
keir@20509 | 2177 } |
keir@20509 | 2178 |
keir@20516 | 2179 flexarray_set(front, foffset++, "backend-id"); |
keir@20509 | 2180 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", vfb->backend_domid)); |
keir@20516 | 2181 flexarray_set(front, foffset++, "state"); |
keir@20509 | 2182 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20509 | 2183 |
keir@20509 | 2184 libxl_device_generic_add(ctx, &device, |
keir@20509 | 2185 libxl_xs_kvs_of_flexarray(ctx, back, boffset), |
keir@20509 | 2186 libxl_xs_kvs_of_flexarray(ctx, front, foffset)); |
keir@20509 | 2187 flexarray_free(front); |
keir@20509 | 2188 flexarray_free(back); |
keir@20509 | 2189 |
keir@20509 | 2190 return 0; |
keir@20462 | 2191 } |
keir@20462 | 2192 |
keir@20462 | 2193 int libxl_device_vfb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid) |
keir@20462 | 2194 { |
keir@20462 | 2195 return ERROR_NI; |
keir@20462 | 2196 } |
keir@20462 | 2197 |
keir@20462 | 2198 int libxl_device_vfb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid) |
keir@20462 | 2199 { |
keir@20462 | 2200 return ERROR_NI; |
keir@20462 | 2201 } |
keir@20462 | 2202 |
keir@20462 | 2203 /******************************************************************************/ |
keir@20482 | 2204 |
keir@20482 | 2205 int libxl_device_pci_init(libxl_device_pci *pcidev, unsigned int domain, |
keir@20482 | 2206 unsigned int bus, unsigned int dev, |
keir@20482 | 2207 unsigned int func, unsigned int vdevfn) |
keir@20482 | 2208 { |
keir@20482 | 2209 pcidev->domain = domain; |
keir@20482 | 2210 pcidev->bus = bus; |
keir@20482 | 2211 pcidev->dev = dev; |
keir@20482 | 2212 pcidev->func = func; |
keir@20482 | 2213 pcidev->vdevfn = vdevfn; |
keir@20482 | 2214 return 0; |
keir@20482 | 2215 } |
keir@20482 | 2216 |
keir@20482 | 2217 static int libxl_create_pci_backend(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev, int num) |
keir@20482 | 2218 { |
keir@20482 | 2219 flexarray_t *front; |
keir@20482 | 2220 flexarray_t *back; |
keir@20482 | 2221 unsigned int boffset = 0; |
keir@20482 | 2222 unsigned int foffset = 0; |
keir@20482 | 2223 libxl_device device; |
keir@20482 | 2224 int i; |
keir@20482 | 2225 |
keir@20482 | 2226 front = flexarray_make(16, 1); |
keir@20482 | 2227 if (!front) |
keir@20482 | 2228 return ERROR_NOMEM; |
keir@20482 | 2229 back = flexarray_make(16, 1); |
keir@20482 | 2230 if (!back) |
keir@20482 | 2231 return ERROR_NOMEM; |
keir@20482 | 2232 |
keir@20512 | 2233 XL_LOG(ctx, XL_LOG_DEBUG, "Creating pci backend"); |
keir@20482 | 2234 |
keir@20482 | 2235 /* add pci device */ |
keir@20482 | 2236 device.backend_devid = 0; |
keir@20482 | 2237 device.backend_domid = 0; |
keir@20482 | 2238 device.backend_kind = DEVICE_PCI; |
keir@20482 | 2239 device.devid = 0; |
keir@20482 | 2240 device.domid = domid; |
keir@20482 | 2241 device.kind = DEVICE_PCI; |
keir@20482 | 2242 |
keir@20516 | 2243 flexarray_set(back, boffset++, "frontend-id"); |
keir@20482 | 2244 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", domid)); |
keir@20516 | 2245 flexarray_set(back, boffset++, "online"); |
keir@20516 | 2246 flexarray_set(back, boffset++, "1"); |
keir@20516 | 2247 flexarray_set(back, boffset++, "state"); |
keir@20482 | 2248 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 2249 flexarray_set(back, boffset++, "domain"); |
keir@20516 | 2250 flexarray_set(back, boffset++, libxl_domid_to_name(ctx, domid)); |
keir@20482 | 2251 for (i = 0; i < num; i++) { |
keir@20482 | 2252 flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", i)); |
keir@20482 | 2253 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func)); |
keir@20482 | 2254 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", i)); |
keir@20482 | 2255 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func)); |
keir@20482 | 2256 if (pcidev->vdevfn) { |
keir@20482 | 2257 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", i)); |
keir@20482 | 2258 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", pcidev->vdevfn)); |
keir@20482 | 2259 } |
keir@20482 | 2260 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", i)); |
keir@20482 | 2261 flexarray_set(back, boffset++, libxl_sprintf(ctx, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt)); |
keir@20482 | 2262 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", i)); |
keir@20482 | 2263 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20482 | 2264 } |
keir@20516 | 2265 flexarray_set(back, boffset++, "num_devs"); |
keir@20482 | 2266 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num)); |
keir@20482 | 2267 |
keir@20516 | 2268 flexarray_set(front, foffset++, "backend-id"); |
keir@20482 | 2269 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 0)); |
keir@20516 | 2270 flexarray_set(front, foffset++, "state"); |
keir@20482 | 2271 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20482 | 2272 |
keir@20482 | 2273 libxl_device_generic_add(ctx, &device, |
keir@20482 | 2274 libxl_xs_kvs_of_flexarray(ctx, back, boffset), |
keir@20482 | 2275 libxl_xs_kvs_of_flexarray(ctx, front, foffset)); |
keir@20482 | 2276 |
keir@20482 | 2277 flexarray_free(back); |
keir@20482 | 2278 flexarray_free(front); |
keir@20482 | 2279 return 0; |
keir@20482 | 2280 } |
keir@20482 | 2281 |
keir@20482 | 2282 static int libxl_device_pci_add_xenstore(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev) |
keir@20462 | 2283 { |
keir@20482 | 2284 flexarray_t *back; |
keir@20482 | 2285 char *num_devs, *be_path; |
keir@20482 | 2286 int num = 0; |
keir@20482 | 2287 unsigned int boffset = 0; |
keir@20482 | 2288 xs_transaction_t t; |
keir@20482 | 2289 |
keir@20516 | 2290 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid); |
keir@20482 | 2291 num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", be_path)); |
keir@20482 | 2292 if (!num_devs) |
keir@20482 | 2293 return libxl_create_pci_backend(ctx, domid, pcidev, 1); |
keir@20482 | 2294 |
keir@20482 | 2295 if (!is_hvm(ctx, domid)) { |
keir@20482 | 2296 if (libxl_wait_for_backend(ctx, be_path, "4") < 0) |
keir@20482 | 2297 return -1; |
keir@20482 | 2298 } |
keir@20482 | 2299 |
keir@20482 | 2300 back = flexarray_make(16, 1); |
keir@20482 | 2301 if (!back) |
keir@20482 | 2302 return ERROR_NOMEM; |
keir@20482 | 2303 |
keir@20512 | 2304 XL_LOG(ctx, XL_LOG_DEBUG, "Adding new pci device to xenstore"); |
keir@20482 | 2305 num = atoi(num_devs); |
keir@20482 | 2306 flexarray_set(back, boffset++, libxl_sprintf(ctx, "key-%d", num)); |
keir@20482 | 2307 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func)); |
keir@20482 | 2308 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev-%d", num)); |
keir@20482 | 2309 flexarray_set(back, boffset++, libxl_sprintf(ctx, PCI_BDF, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func)); |
keir@20482 | 2310 if (pcidev->vdevfn) { |
keir@20482 | 2311 flexarray_set(back, boffset++, libxl_sprintf(ctx, "vdevfn-%d", num)); |
keir@20482 | 2312 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x", pcidev->vdevfn)); |
keir@20482 | 2313 } |
keir@20482 | 2314 flexarray_set(back, boffset++, libxl_sprintf(ctx, "opts-%d", num)); |
keir@20482 | 2315 flexarray_set(back, boffset++, libxl_sprintf(ctx, "msitranslate=%d,power_mgmt=%d", pcidev->msitranslate, pcidev->power_mgmt)); |
keir@20482 | 2316 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state-%d", num)); |
keir@20482 | 2317 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1)); |
keir@20516 | 2318 flexarray_set(back, boffset++, "num_devs"); |
keir@20482 | 2319 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", num + 1)); |
keir@20516 | 2320 flexarray_set(back, boffset++, "state"); |
keir@20482 | 2321 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 7)); |
keir@20482 | 2322 |
keir@20482 | 2323 retry_transaction: |
keir@20482 | 2324 t = xs_transaction_start(ctx->xsh); |
keir@20482 | 2325 libxl_xs_writev(ctx, t, be_path, |
keir@20482 | 2326 libxl_xs_kvs_of_flexarray(ctx, back, boffset)); |
keir@20482 | 2327 if (!xs_transaction_end(ctx->xsh, t, 0)) |
keir@20482 | 2328 if (errno == EAGAIN) |
keir@20482 | 2329 goto retry_transaction; |
keir@20482 | 2330 |
keir@20482 | 2331 flexarray_free(back); |
keir@20482 | 2332 return 0; |
keir@20482 | 2333 } |
keir@20482 | 2334 |
keir@20482 | 2335 static int libxl_device_pci_remove_xenstore(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev) |
keir@20482 | 2336 { |
keir@20542 | 2337 char *be_path, *num_devs_path, *num_devs, *xsdev, *tmp, *tmppath; |
keir@20542 | 2338 int num, i, j; |
keir@20482 | 2339 xs_transaction_t t; |
keir@20482 | 2340 unsigned int domain = 0, bus = 0, dev = 0, func = 0; |
keir@20482 | 2341 |
keir@20516 | 2342 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid); |
keir@20482 | 2343 num_devs_path = libxl_sprintf(ctx, "%s/num_devs", be_path); |
keir@20482 | 2344 num_devs = libxl_xs_read(ctx, XBT_NULL, num_devs_path); |
keir@20482 | 2345 if (!num_devs) |
keir@20482 | 2346 return -1; |
keir@20482 | 2347 num = atoi(num_devs); |
keir@20482 | 2348 |
keir@20482 | 2349 if (!is_hvm(ctx, domid)) { |
keir@20482 | 2350 if (libxl_wait_for_backend(ctx, be_path, "4") < 0) { |
keir@20542 | 2351 XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", be_path); |
keir@20482 | 2352 return -1; |
keir@20482 | 2353 } |
keir@20482 | 2354 } |
keir@20482 | 2355 |
keir@20482 | 2356 for (i = 0; i < num; i++) { |
keir@20482 | 2357 xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", be_path, i)); |
keir@20482 | 2358 sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func); |
keir@20482 | 2359 if (domain == pcidev->domain && bus == pcidev->bus && |
keir@20482 | 2360 pcidev->dev == dev && pcidev->func == func) { |
keir@20482 | 2361 break; |
keir@20482 | 2362 } |
keir@20482 | 2363 } |
keir@20482 | 2364 if (i == num) { |
keir@20512 | 2365 XL_LOG(ctx, XL_LOG_ERROR, "Couldn't find the device on xenstore"); |
keir@20482 | 2366 return -1; |
keir@20482 | 2367 } |
keir@20482 | 2368 |
keir@20482 | 2369 retry_transaction: |
keir@20482 | 2370 t = xs_transaction_start(ctx->xsh); |
keir@20542 | 2371 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i), "5", strlen("5")); |
keir@20482 | 2372 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state", be_path), "7", strlen("7")); |
keir@20482 | 2373 if (!xs_transaction_end(ctx->xsh, t, 0)) |
keir@20482 | 2374 if (errno == EAGAIN) |
keir@20482 | 2375 goto retry_transaction; |
keir@20542 | 2376 |
keir@20542 | 2377 if (!is_hvm(ctx, domid)) { |
keir@20542 | 2378 if (libxl_wait_for_backend(ctx, be_path, "4") < 0) { |
keir@20542 | 2379 XL_LOG(ctx, XL_LOG_DEBUG, "pci backend at %s is not ready", be_path); |
keir@20542 | 2380 return -1; |
keir@20542 | 2381 } |
keir@20542 | 2382 } |
keir@20542 | 2383 |
keir@20542 | 2384 retry_transaction2: |
keir@20542 | 2385 t = xs_transaction_start(ctx->xsh); |
keir@20542 | 2386 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, i)); |
keir@20542 | 2387 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, i)); |
keir@20542 | 2388 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, i)); |
keir@20542 | 2389 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, i)); |
keir@20542 | 2390 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, i)); |
keir@20542 | 2391 xs_rm(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i)); |
keir@20542 | 2392 libxl_xs_write(ctx, t, num_devs_path, "%d", num - 1); |
keir@20542 | 2393 for (j = i + 1; j < num; j++) { |
keir@20542 | 2394 tmppath = libxl_sprintf(ctx, "%s/state-%d", be_path, j); |
keir@20542 | 2395 tmp = libxl_xs_read(ctx, t, tmppath); |
keir@20542 | 2396 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/state-%d", be_path, j - 1), tmp, strlen(tmp)); |
keir@20542 | 2397 xs_rm(ctx->xsh, t, tmppath); |
keir@20542 | 2398 tmppath = libxl_sprintf(ctx, "%s/dev-%d", be_path, j); |
keir@20542 | 2399 tmp = libxl_xs_read(ctx, t, tmppath); |
keir@20542 | 2400 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/dev-%d", be_path, j - 1), tmp, strlen(tmp)); |
keir@20542 | 2401 xs_rm(ctx->xsh, t, tmppath); |
keir@20542 | 2402 tmppath = libxl_sprintf(ctx, "%s/key-%d", be_path, j); |
keir@20542 | 2403 tmp = libxl_xs_read(ctx, t, tmppath); |
keir@20542 | 2404 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/key-%d", be_path, j - 1), tmp, strlen(tmp)); |
keir@20542 | 2405 xs_rm(ctx->xsh, t, tmppath); |
keir@20542 | 2406 tmppath = libxl_sprintf(ctx, "%s/vdev-%d", be_path, j); |
keir@20542 | 2407 tmp = libxl_xs_read(ctx, t, tmppath); |
keir@20542 | 2408 if (tmp) { |
keir@20542 | 2409 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdev-%d", be_path, j - 1), tmp, strlen(tmp)); |
keir@20542 | 2410 xs_rm(ctx->xsh, t, tmppath); |
keir@20542 | 2411 } |
keir@20542 | 2412 tmppath = libxl_sprintf(ctx, "%s/opts-%d", be_path, j); |
keir@20542 | 2413 tmp = libxl_xs_read(ctx, t, tmppath); |
keir@20542 | 2414 if (tmp) { |
keir@20542 | 2415 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/opts-%d", be_path, j - 1), tmp, strlen(tmp)); |
keir@20542 | 2416 xs_rm(ctx->xsh, t, tmppath); |
keir@20542 | 2417 } |
keir@20542 | 2418 tmppath = libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j); |
keir@20542 | 2419 tmp = libxl_xs_read(ctx, t, tmppath); |
keir@20542 | 2420 if (tmp) { |
keir@20542 | 2421 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, j - 1), tmp, strlen(tmp)); |
keir@20542 | 2422 xs_rm(ctx->xsh, t, tmppath); |
keir@20542 | 2423 } |
keir@20542 | 2424 } |
keir@20542 | 2425 if (!xs_transaction_end(ctx->xsh, t, 0)) |
keir@20542 | 2426 if (errno == EAGAIN) |
keir@20542 | 2427 goto retry_transaction2; |
keir@20542 | 2428 |
keir@20542 | 2429 if (num == 1) { |
keir@20542 | 2430 char *fe_path = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/frontend", be_path)); |
keir@20542 | 2431 libxl_device_destroy(ctx, be_path, 1); |
keir@20542 | 2432 xs_rm(ctx->xsh, XBT_NULL, be_path); |
keir@20542 | 2433 xs_rm(ctx->xsh, XBT_NULL, fe_path); |
keir@20542 | 2434 return 0; |
keir@20542 | 2435 } |
keir@20542 | 2436 |
keir@20482 | 2437 return 0; |
keir@20462 | 2438 } |
keir@20462 | 2439 |
keir@20482 | 2440 int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev) |
keir@20462 | 2441 { |
keir@20779 | 2442 char *path; |
keir@20482 | 2443 char *state, *vdevfn; |
keir@20482 | 2444 int rc, hvm; |
keir@20542 | 2445 int stubdomid = 0; |
keir@20482 | 2446 |
keir@20482 | 2447 /* TODO: check if the device can be assigned */ |
keir@20482 | 2448 |
Ian@21711 | 2449 libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func); |
keir@20482 | 2450 |
keir@20779 | 2451 stubdomid = libxl_get_stubdom_id(ctx, domid); |
keir@20779 | 2452 if (stubdomid != 0) { |
keir@20542 | 2453 libxl_device_pci pcidev_s = *pcidev; |
keir@20542 | 2454 libxl_device_pci_add(ctx, stubdomid, &pcidev_s); |
keir@20542 | 2455 } |
keir@20542 | 2456 |
keir@20482 | 2457 hvm = is_hvm(ctx, domid); |
keir@20482 | 2458 if (hvm) { |
keir@20831 | 2459 if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 0) { |
keir@20482 | 2460 return -1; |
keir@20482 | 2461 } |
keir@20779 | 2462 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid); |
keir@20482 | 2463 state = libxl_xs_read(ctx, XBT_NULL, path); |
keir@20779 | 2464 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid); |
keir@20482 | 2465 if (pcidev->vdevfn) |
keir@20482 | 2466 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF_VDEVFN, pcidev->domain, |
keir@20482 | 2467 pcidev->bus, pcidev->dev, pcidev->func, pcidev->vdevfn); |
keir@20482 | 2468 else |
keir@20482 | 2469 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain, |
keir@20482 | 2470 pcidev->bus, pcidev->dev, pcidev->func); |
keir@20779 | 2471 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid); |
keir@20482 | 2472 xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins")); |
keir@20831 | 2473 if (libxl_wait_for_device_model(ctx, domid, "pci-inserted", NULL, NULL) < 0) |
keir@20512 | 2474 XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time"); |
keir@20779 | 2475 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid); |
keir@20482 | 2476 vdevfn = libxl_xs_read(ctx, XBT_NULL, path); |
keir@20482 | 2477 sscanf(vdevfn + 2, "%x", &pcidev->vdevfn); |
keir@20779 | 2478 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid); |
keir@20482 | 2479 xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state)); |
keir@20482 | 2480 } else { |
keir@20542 | 2481 char *sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain, |
keir@20482 | 2482 pcidev->bus, pcidev->dev, pcidev->func); |
keir@20482 | 2483 FILE *f = fopen(sysfs_path, "r"); |
keir@21517 | 2484 unsigned long long start = 0, end = 0, flags = 0, size = 0; |
keir@20482 | 2485 int irq = 0; |
keir@20482 | 2486 int i; |
keir@20482 | 2487 |
keir@20482 | 2488 if (f == NULL) { |
keir@20512 | 2489 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path); |
keir@20482 | 2490 return -1; |
keir@20482 | 2491 } |
keir@20482 | 2492 for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) { |
keir@21517 | 2493 if (fscanf(f, "0x%llx 0x%llx 0x%llx\n", &start, &end, &flags) != 3) |
keir@21466 | 2494 continue; |
keir@20482 | 2495 size = end - start + 1; |
keir@20482 | 2496 if (start) { |
keir@20482 | 2497 if (flags & PCI_BAR_IO) { |
keir@20482 | 2498 rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 1); |
keir@20482 | 2499 if (rc < 0) |
keir@21517 | 2500 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_ioport_permission error 0x%llx/0x%llx", start, size); |
keir@20482 | 2501 } else { |
keir@20482 | 2502 rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT, |
keir@20482 | 2503 (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 1); |
keir@20482 | 2504 if (rc < 0) |
keir@21537 | 2505 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_iomem_permission error 0x%llx/0x%llx", start, size); |
keir@20482 | 2506 } |
keir@20482 | 2507 } |
keir@20482 | 2508 } |
keir@20482 | 2509 fclose(f); |
keir@20542 | 2510 sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", pcidev->domain, |
keir@20482 | 2511 pcidev->bus, pcidev->dev, pcidev->func); |
keir@20482 | 2512 f = fopen(sysfs_path, "r"); |
keir@20482 | 2513 if (f == NULL) { |
keir@20512 | 2514 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path); |
keir@20482 | 2515 goto out; |
keir@20482 | 2516 } |
keir@21466 | 2517 if ((fscanf(f, "%u", &irq) == 1) && irq) { |
keir@20482 | 2518 rc = xc_physdev_map_pirq(ctx->xch, domid, irq, &irq); |
keir@20482 | 2519 if (rc < 0) { |
keir@20512 | 2520 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_physdev_map_pirq irq=%d", irq); |
keir@20482 | 2521 } |
keir@20482 | 2522 rc = xc_domain_irq_permission(ctx->xch, domid, irq, 1); |
keir@20482 | 2523 if (rc < 0) { |
keir@20512 | 2524 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "Error: xc_domain_irq_permission irq=%d", irq); |
keir@20482 | 2525 } |
keir@20482 | 2526 } |
keir@20482 | 2527 fclose(f); |
keir@20482 | 2528 } |
keir@20482 | 2529 out: |
keir@20860 | 2530 if (!libxl_is_stubdom(ctx, domid, NULL)) { |
keir@20779 | 2531 rc = xc_assign_device(ctx->xch, domid, pcidev->value); |
keir@20779 | 2532 if (rc < 0) |
keir@20542 | 2533 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_assign_device failed"); |
keir@20542 | 2534 } |
keir@20482 | 2535 |
keir@20482 | 2536 libxl_device_pci_add_xenstore(ctx, domid, pcidev); |
keir@20482 | 2537 return 0; |
keir@20462 | 2538 } |
keir@20462 | 2539 |
keir@20482 | 2540 int libxl_device_pci_remove(struct libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev) |
keir@20462 | 2541 { |
keir@20779 | 2542 char *path; |
keir@20482 | 2543 char *state; |
keir@20482 | 2544 int hvm, rc; |
keir@20542 | 2545 int stubdomid = 0; |
keir@20482 | 2546 |
keir@20482 | 2547 /* TODO: check if the device can be detached */ |
keir@20542 | 2548 libxl_device_pci_remove_xenstore(ctx, domid, pcidev); |
keir@20482 | 2549 |
keir@20482 | 2550 hvm = is_hvm(ctx, domid); |
keir@20482 | 2551 if (hvm) { |
keir@20831 | 2552 if (libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL) < 0) { |
keir@20482 | 2553 return -1; |
keir@20482 | 2554 } |
keir@20779 | 2555 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid); |
keir@20482 | 2556 state = libxl_xs_read(ctx, XBT_NULL, path); |
keir@20779 | 2557 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/parameter", domid); |
keir@20482 | 2558 libxl_xs_write(ctx, XBT_NULL, path, PCI_BDF, pcidev->domain, |
keir@20482 | 2559 pcidev->bus, pcidev->dev, pcidev->func); |
keir@20779 | 2560 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid); |
keir@20482 | 2561 xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem")); |
keir@20831 | 2562 if (libxl_wait_for_device_model(ctx, domid, "pci-removed", NULL, NULL) < 0) { |
keir@20512 | 2563 XL_LOG(ctx, XL_LOG_ERROR, "Device Model didn't respond in time"); |
keir@20482 | 2564 return -1; |
keir@20482 | 2565 } |
keir@20779 | 2566 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d/state", domid); |
keir@20482 | 2567 xs_write(ctx->xsh, XBT_NULL, path, state, strlen(state)); |
keir@20482 | 2568 } else { |
keir@20542 | 2569 char *sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain, |
keir@20482 | 2570 pcidev->bus, pcidev->dev, pcidev->func); |
keir@20482 | 2571 FILE *f = fopen(sysfs_path, "r"); |
keir@20482 | 2572 unsigned int start = 0, end = 0, flags = 0, size = 0; |
keir@20482 | 2573 int irq = 0; |
keir@20482 | 2574 int i; |
keir@20482 | 2575 |
keir@20482 | 2576 if (f == NULL) { |
keir@20512 | 2577 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path); |
keir@20482 | 2578 goto skip1; |
keir@20482 | 2579 } |
keir@20482 | 2580 for (i = 0; i < PROC_PCI_NUM_RESOURCES; i++) { |
keir@21466 | 2581 if (fscanf(f, "0x%x 0x%x 0x%x\n", &start, &end, &flags) != 3) |
keir@21466 | 2582 continue; |
keir@20482 | 2583 size = end - start + 1; |
keir@20482 | 2584 if (start) { |
keir@20482 | 2585 if (flags & PCI_BAR_IO) { |
keir@20482 | 2586 rc = xc_domain_ioport_permission(ctx->xch, domid, start, size, 0); |
keir@20482 | 2587 if (rc < 0) |
keir@20512 | 2588 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_ioport_permission error 0x%x/0x%x", start, size); |
keir@20482 | 2589 } else { |
keir@20482 | 2590 rc = xc_domain_iomem_permission(ctx->xch, domid, start>>XC_PAGE_SHIFT, |
keir@20482 | 2591 (size+(XC_PAGE_SIZE-1))>>XC_PAGE_SHIFT, 0); |
keir@20482 | 2592 if (rc < 0) |
keir@20512 | 2593 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_iomem_permission error 0x%x/0x%x", start, size); |
keir@20482 | 2594 } |
keir@20482 | 2595 } |
keir@20482 | 2596 } |
keir@20482 | 2597 fclose(f); |
keir@20482 | 2598 skip1: |
keir@20542 | 2599 sysfs_path = libxl_sprintf(ctx, SYSFS_PCI_DEV"/"PCI_BDF"/irq", pcidev->domain, |
keir@20482 | 2600 pcidev->bus, pcidev->dev, pcidev->func); |
keir@20482 | 2601 f = fopen(sysfs_path, "r"); |
keir@20482 | 2602 if (f == NULL) { |
keir@20512 | 2603 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't open %s", sysfs_path); |
keir@20482 | 2604 goto out; |
keir@20482 | 2605 } |
keir@21466 | 2606 if ((fscanf(f, "%u", &irq) == 1) && irq) { |
keir@20482 | 2607 rc = xc_physdev_unmap_pirq(ctx->xch, domid, irq); |
keir@20482 | 2608 if (rc < 0) { |
keir@20512 | 2609 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_physdev_map_pirq irq=%d", irq); |
keir@20482 | 2610 } |
keir@20482 | 2611 rc = xc_domain_irq_permission(ctx->xch, domid, irq, 0); |
keir@20482 | 2612 if (rc < 0) { |
keir@20512 | 2613 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_irq_permission irq=%d", irq); |
keir@20482 | 2614 } |
keir@20482 | 2615 } |
keir@20482 | 2616 fclose(f); |
keir@20482 | 2617 } |
keir@20482 | 2618 out: |
Ian@21711 | 2619 libxl_device_pci_reset(ctx, pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func); |
keir@20482 | 2620 |
keir@20860 | 2621 if (!libxl_is_stubdom(ctx, domid, NULL)) { |
keir@20779 | 2622 rc = xc_deassign_device(ctx->xch, domid, pcidev->value); |
keir@20779 | 2623 if (rc < 0) |
keir@20542 | 2624 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_deassign_device failed"); |
keir@20542 | 2625 } |
keir@20542 | 2626 |
keir@20779 | 2627 stubdomid = libxl_get_stubdom_id(ctx, domid); |
keir@20779 | 2628 if (stubdomid != 0) { |
keir@20542 | 2629 libxl_device_pci pcidev_s = *pcidev; |
keir@20542 | 2630 libxl_device_pci_remove(ctx, stubdomid, &pcidev_s); |
keir@20542 | 2631 } |
keir@20542 | 2632 |
keir@20482 | 2633 return 0; |
keir@20462 | 2634 } |
keir@20482 | 2635 |
keir@20482 | 2636 libxl_device_pci *libxl_device_pci_list(struct libxl_ctx *ctx, uint32_t domid, int *num) |
keir@20482 | 2637 { |
keir@20482 | 2638 char *be_path, *num_devs, *xsdev, *xsvdevfn, *xsopts; |
keir@20482 | 2639 int n, i; |
keir@20482 | 2640 unsigned int domain = 0, bus = 0, dev = 0, func = 0, vdevfn = 0; |
keir@20482 | 2641 libxl_device_pci *pcidevs; |
keir@20482 | 2642 |
keir@20516 | 2643 be_path = libxl_sprintf(ctx, "%s/backend/pci/%d/0", libxl_xs_get_dompath(ctx, 0), domid); |
keir@20482 | 2644 num_devs = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/num_devs", be_path)); |
keir@20482 | 2645 if (!num_devs) { |
keir@20482 | 2646 *num = 0; |
keir@20482 | 2647 return NULL; |
keir@20482 | 2648 } |
keir@20482 | 2649 n = atoi(num_devs); |
keir@20779 | 2650 pcidevs = calloc(n, sizeof(libxl_device_pci)); |
keir@20482 | 2651 *num = n; |
keir@20482 | 2652 |
keir@20482 | 2653 for (i = 0; i < n; i++) { |
keir@20482 | 2654 xsdev = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/dev-%d", be_path, i)); |
keir@20482 | 2655 sscanf(xsdev, PCI_BDF, &domain, &bus, &dev, &func); |
keir@20482 | 2656 xsvdevfn = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vdevfn-%d", be_path, i)); |
keir@20482 | 2657 if (xsvdevfn) |
keir@20482 | 2658 vdevfn = strtol(xsvdevfn, (char **) NULL, 16); |
keir@20482 | 2659 libxl_device_pci_init(pcidevs + i, domain, bus, dev, func, vdevfn); |
keir@20482 | 2660 xsopts = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/opts-%d", be_path, i)); |
keir@20482 | 2661 if (xsopts) { |
keir@20482 | 2662 char *saveptr; |
keir@20482 | 2663 char *p = strtok_r(xsopts, ",=", &saveptr); |
keir@20482 | 2664 do { |
keir@20482 | 2665 while (*p == ' ') |
keir@20482 | 2666 p++; |
keir@20482 | 2667 if (!strcmp(p, "msitranslate")) { |
keir@20482 | 2668 p = strtok_r(NULL, ",=", &saveptr); |
keir@20482 | 2669 pcidevs[i].msitranslate = atoi(p); |
keir@20482 | 2670 } else if (!strcmp(p, "power_mgmt")) { |
keir@20482 | 2671 p = strtok_r(NULL, ",=", &saveptr); |
keir@20482 | 2672 pcidevs[i].power_mgmt = atoi(p); |
keir@20482 | 2673 } |
keir@20482 | 2674 } while ((p = strtok_r(NULL, ",=", &saveptr)) != NULL); |
keir@20482 | 2675 } |
keir@20482 | 2676 } |
keir@20482 | 2677 return pcidevs; |
keir@20482 | 2678 } |
keir@20482 | 2679 |
keir@20482 | 2680 int libxl_device_pci_shutdown(struct libxl_ctx *ctx, uint32_t domid) |
keir@20482 | 2681 { |
keir@20482 | 2682 libxl_device_pci *pcidevs; |
keir@20482 | 2683 int num, i; |
keir@20482 | 2684 |
keir@20482 | 2685 pcidevs = libxl_device_pci_list(ctx, domid, &num); |
keir@20482 | 2686 for (i = 0; i < num; i++) { |
keir@20482 | 2687 if (libxl_device_pci_remove(ctx, domid, pcidevs + i) < 0) |
keir@20482 | 2688 return -1; |
keir@20482 | 2689 } |
keir@20516 | 2690 free(pcidevs); |
keir@20482 | 2691 return 0; |
keir@20482 | 2692 } |
keir@20482 | 2693 |
keir@21404 | 2694 int libxl_domain_setmaxmem(struct libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb) |
keir@21404 | 2695 { |
keir@21404 | 2696 char *mem, *endptr; |
keir@21404 | 2697 uint32_t memorykb; |
keir@21404 | 2698 char *dompath = libxl_xs_get_dompath(ctx, domid); |
keir@21404 | 2699 |
keir@21404 | 2700 mem = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", dompath)); |
keir@21404 | 2701 if (!mem) { |
keir@21404 | 2702 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot get memory info from %s/memory/target\n", dompath); |
keir@21404 | 2703 return 1; |
keir@21404 | 2704 } |
keir@21404 | 2705 memorykb = strtoul(mem, &endptr, 10); |
keir@21404 | 2706 if (*endptr != '\0') { |
keir@21404 | 2707 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "invalid memory %s from %s/memory/target\n", mem, dompath); |
keir@21404 | 2708 return 1; |
keir@21404 | 2709 } |
keir@21404 | 2710 |
keir@21404 | 2711 if (max_memkb < memorykb) { |
keir@21404 | 2712 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "memory_static_max must be greater than or or equal to memory_dynamic_max\n"); |
keir@21404 | 2713 return 1; |
keir@21404 | 2714 } |
keir@21404 | 2715 |
keir@21404 | 2716 if (domid != 0) |
Ian@21844 | 2717 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/static-max", dompath), "%"PRIu32, max_memkb); |
keir@21404 | 2718 |
keir@21422 | 2719 return 0; |
keir@21404 | 2720 } |
keir@21404 | 2721 |
keir@21422 | 2722 int libxl_set_memory_target(struct libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb, int enforce) |
keir@20647 | 2723 { |
keir@20647 | 2724 int rc = 0; |
keir@21422 | 2725 uint32_t memorykb = 0, videoram = 0; |
keir@21405 | 2726 char *memmax, *endptr, *videoram_s = NULL; |
keir@20647 | 2727 char *dompath = libxl_xs_get_dompath(ctx, domid); |
keir@21374 | 2728 xc_domaininfo_t info; |
keir@21374 | 2729 struct libxl_dominfo ptr; |
keir@21374 | 2730 char *uuid; |
keir@20542 | 2731 |
keir@21405 | 2732 if (domid) { |
keir@21405 | 2733 memmax = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/static-max", dompath)); |
keir@21405 | 2734 if (!memmax) { |
keir@21405 | 2735 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, |
keir@21405 | 2736 "cannot get memory info from %s/memory/static-max\n", dompath); |
keir@21405 | 2737 return 1; |
keir@21405 | 2738 } |
keir@21405 | 2739 memorykb = strtoul(memmax, &endptr, 10); |
keir@21405 | 2740 if (*endptr != '\0') { |
keir@21405 | 2741 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, |
keir@21405 | 2742 "invalid max memory %s from %s/memory/static-max\n", memmax, dompath); |
keir@21405 | 2743 return 1; |
keir@21405 | 2744 } |
keir@21405 | 2745 |
keir@21405 | 2746 if (target_memkb > memorykb) { |
keir@21504 | 2747 XL_LOG(ctx, XL_LOG_ERROR, |
keir@21405 | 2748 "memory_dynamic_max must be less than or equal to memory_static_max\n"); |
keir@21405 | 2749 return 1; |
keir@21405 | 2750 } |
keir@21405 | 2751 } |
keir@21405 | 2752 |
keir@20647 | 2753 videoram_s = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/videoram", dompath)); |
keir@21314 | 2754 videoram = videoram_s ? atoi(videoram_s) : 0; |
keir@20647 | 2755 |
Ian@21844 | 2756 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/memory/target", dompath), "%"PRIu32, target_memkb); |
keir@21374 | 2757 |
keir@21374 | 2758 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info); |
keir@21374 | 2759 if (rc != 1 || info.domain != domid) |
keir@21374 | 2760 return rc; |
keir@21374 | 2761 xcinfo2xlinfo(&info, &ptr); |
keir@21374 | 2762 uuid = libxl_uuid2string(ctx, ptr.uuid); |
Ian@21844 | 2763 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "/vm/%s/memory", uuid), "%"PRIu32, target_memkb / 1024); |
keir@21374 | 2764 |
keir@21422 | 2765 if (enforce || !domid) |
keir@21422 | 2766 memorykb = target_memkb; |
keir@21422 | 2767 rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb + LIBXL_MAXMEM_CONSTANT); |
keir@21422 | 2768 if (rc != 0) |
keir@21422 | 2769 return rc; |
keir@20647 | 2770 rc = xc_domain_memory_set_pod_target(ctx->xch, domid, (target_memkb - videoram) / 4, NULL, NULL, NULL); |
keir@20647 | 2771 return rc; |
keir@20647 | 2772 } |
keir@20875 | 2773 |
keir@20875 | 2774 int libxl_button_press(struct libxl_ctx *ctx, uint32_t domid, libxl_button button) |
keir@20875 | 2775 { |
keir@20875 | 2776 int rc = -1; |
keir@20875 | 2777 |
keir@20875 | 2778 switch (button) { |
keir@20875 | 2779 case POWER_BUTTON: |
keir@20875 | 2780 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_POWER, 0); |
keir@20875 | 2781 break; |
keir@20875 | 2782 case SLEEP_BUTTON: |
keir@20875 | 2783 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_SLEEP, 0); |
keir@20875 | 2784 break; |
keir@20875 | 2785 default: |
keir@20875 | 2786 break; |
keir@20875 | 2787 } |
keir@20875 | 2788 |
keir@20875 | 2789 return rc; |
keir@20875 | 2790 } |
keir@21141 | 2791 |
keir@21141 | 2792 int libxl_get_physinfo(struct libxl_ctx *ctx, struct libxl_physinfo *physinfo) |
keir@21141 | 2793 { |
keir@21141 | 2794 xc_physinfo_t xcphysinfo = { 0 }; |
keir@21141 | 2795 int rc; |
keir@21141 | 2796 |
keir@21141 | 2797 rc = xc_physinfo(ctx->xch, &xcphysinfo); |
keir@21141 | 2798 if (rc != 0) { |
keir@21141 | 2799 return rc; |
keir@21141 | 2800 } |
keir@21141 | 2801 physinfo->threads_per_core = xcphysinfo.threads_per_core; |
keir@21141 | 2802 physinfo->cores_per_socket = xcphysinfo.cores_per_socket; |
keir@21142 | 2803 physinfo->max_cpu_id = xcphysinfo.max_cpu_id; |
keir@21141 | 2804 physinfo->nr_cpus = xcphysinfo.nr_cpus; |
keir@21141 | 2805 physinfo->cpu_khz = xcphysinfo.cpu_khz; |
keir@21141 | 2806 physinfo->total_pages = xcphysinfo.total_pages; |
keir@21141 | 2807 physinfo->free_pages = xcphysinfo.free_pages; |
keir@21141 | 2808 physinfo->scrub_pages = xcphysinfo.scrub_pages; |
keir@21264 | 2809 physinfo->nr_nodes = xcphysinfo.nr_nodes; |
keir@21264 | 2810 memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap)); |
keir@21264 | 2811 physinfo->phys_cap = xcphysinfo.capabilities; |
keir@21264 | 2812 |
keir@21141 | 2813 return 0; |
keir@21141 | 2814 } |
keir@21141 | 2815 |
keir@21266 | 2816 const libxl_version_info* libxl_get_version_info(struct libxl_ctx *ctx) |
keir@21266 | 2817 { |
keir@21266 | 2818 union { |
keir@21266 | 2819 xen_extraversion_t xen_extra; |
keir@21266 | 2820 xen_compile_info_t xen_cc; |
keir@21266 | 2821 xen_changeset_info_t xen_chgset; |
keir@21266 | 2822 xen_capabilities_info_t xen_caps; |
keir@21266 | 2823 xen_platform_parameters_t p_parms; |
keir@21266 | 2824 xen_commandline_t xen_commandline; |
keir@21266 | 2825 } u; |
keir@21266 | 2826 long xen_version; |
keir@21266 | 2827 libxl_version_info *info = &ctx->version_info; |
keir@21266 | 2828 |
keir@21266 | 2829 if (info->xen_version_extra != NULL) |
keir@21266 | 2830 return info; |
keir@21266 | 2831 |
keir@21266 | 2832 xen_version = xc_version(ctx->xch, XENVER_version, NULL); |
keir@21266 | 2833 info->xen_version_major = xen_version >> 16; |
keir@21266 | 2834 info->xen_version_minor = xen_version & 0xFF; |
keir@21266 | 2835 xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra); |
Ian@21845 | 2836 info->xen_version_extra = libxl_strdup(ctx, u.xen_extra); |
keir@21266 | 2837 |
keir@21266 | 2838 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc); |
Ian@21845 | 2839 info->compiler = libxl_strdup(ctx, u.xen_cc.compiler); |
Ian@21845 | 2840 info->compile_by = libxl_strdup(ctx, u.xen_cc.compile_by); |
Ian@21845 | 2841 info->compile_domain = libxl_strdup(ctx, u.xen_cc.compile_domain); |
Ian@21845 | 2842 info->compile_date = libxl_strdup(ctx, u.xen_cc.compile_date); |
keir@21266 | 2843 |
keir@21266 | 2844 xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps); |
Ian@21845 | 2845 info->capabilities = libxl_strdup(ctx, u.xen_caps); |
keir@21266 | 2846 |
keir@21266 | 2847 xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset); |
Ian@21845 | 2848 info->changeset = libxl_strdup(ctx, u.xen_chgset); |
keir@21266 | 2849 |
keir@21266 | 2850 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms); |
keir@21266 | 2851 info->virt_start = u.p_parms.virt_start; |
keir@21266 | 2852 |
keir@21266 | 2853 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL); |
keir@21266 | 2854 |
keir@21266 | 2855 xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline); |
Ian@21845 | 2856 info->commandline = libxl_strdup(ctx, u.xen_commandline); |
keir@21266 | 2857 |
keir@21266 | 2858 return info; |
keir@21266 | 2859 } |
keir@21266 | 2860 |
keir@21141 | 2861 struct libxl_vcpuinfo *libxl_list_vcpu(struct libxl_ctx *ctx, uint32_t domid, |
keir@21141 | 2862 int *nb_vcpu, int *cpusize) |
keir@21141 | 2863 { |
keir@21141 | 2864 struct libxl_vcpuinfo *ptr, *ret; |
keir@21141 | 2865 xc_domaininfo_t domaininfo; |
keir@21141 | 2866 xc_vcpuinfo_t vcpuinfo; |
keir@21141 | 2867 xc_physinfo_t physinfo = { 0 }; |
keir@21141 | 2868 |
keir@21141 | 2869 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) { |
keir@21141 | 2870 return NULL; |
keir@21141 | 2871 } |
keir@21141 | 2872 if (xc_physinfo(ctx->xch, &physinfo) == -1) { |
keir@21141 | 2873 return NULL; |
keir@21141 | 2874 } |
keir@21141 | 2875 *cpusize = physinfo.max_cpu_id + 1; |
keir@21141 | 2876 ptr = libxl_calloc(ctx, domaininfo.max_vcpu_id + 1, sizeof (struct libxl_vcpuinfo)); |
keir@21141 | 2877 if (!ptr) { |
keir@21141 | 2878 return NULL; |
keir@21141 | 2879 } |
keir@21141 | 2880 |
keir@21141 | 2881 ret = ptr; |
keir@21141 | 2882 for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) { |
keir@21141 | 2883 ptr->cpumap = libxl_calloc(ctx, (*cpusize + 63) / 64, sizeof (uint64_t)); |
keir@21141 | 2884 if (!ptr->cpumap) { |
keir@21141 | 2885 return NULL; |
keir@21141 | 2886 } |
keir@21141 | 2887 if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) { |
keir@21141 | 2888 return NULL; |
keir@21141 | 2889 } |
keir@21141 | 2890 if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu, ptr->cpumap, *cpusize) == -1) { |
keir@21141 | 2891 return NULL; |
keir@21141 | 2892 } |
keir@21141 | 2893 ptr->vcpuid = *nb_vcpu; |
keir@21141 | 2894 ptr->cpu = vcpuinfo.cpu; |
keir@21141 | 2895 ptr->online = !!vcpuinfo.online; |
keir@21141 | 2896 ptr->blocked = !!vcpuinfo.blocked; |
keir@21141 | 2897 ptr->running = !!vcpuinfo.running; |
keir@21141 | 2898 ptr->vcpu_time = vcpuinfo.cpu_time; |
keir@21141 | 2899 } |
keir@21141 | 2900 return ret; |
keir@21141 | 2901 } |
keir@21142 | 2902 |
keir@21142 | 2903 int libxl_set_vcpuaffinity(struct libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid, |
keir@21142 | 2904 uint64_t *cpumap, int cpusize) |
keir@21142 | 2905 { |
keir@21142 | 2906 return (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap, cpusize)); |
keir@21142 | 2907 } |
keir@21143 | 2908 |
keir@21143 | 2909 int libxl_set_vcpucount(struct libxl_ctx *ctx, uint32_t domid, uint32_t count) |
keir@21143 | 2910 { |
keir@21143 | 2911 xc_domaininfo_t domaininfo; |
keir@21143 | 2912 char *dompath; |
keir@21143 | 2913 int i; |
keir@21143 | 2914 |
keir@21143 | 2915 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) { |
keir@21143 | 2916 return ERROR_FAIL; |
keir@21143 | 2917 } |
keir@21143 | 2918 if (!count || ((domaininfo.max_vcpu_id + 1) < count)) { |
keir@21143 | 2919 return ERROR_INVAL; |
keir@21143 | 2920 } |
keir@21143 | 2921 if (!(dompath = libxl_xs_get_dompath(ctx, domid))) |
keir@21143 | 2922 return ERROR_FAIL; |
keir@21143 | 2923 |
keir@21143 | 2924 for (i = 0; i <= domaininfo.max_vcpu_id; ++i) { |
keir@21143 | 2925 libxl_xs_write(ctx, XBT_NULL, |
keir@21143 | 2926 libxl_sprintf(ctx, "%s/cpu/%u/availability", dompath, i), |
keir@21143 | 2927 "%s", ((1 << i) & ((1 << count) - 1)) ? "online" : "offline"); |
keir@21143 | 2928 } |
keir@21143 | 2929 return 0; |
keir@21143 | 2930 } |
keir@21265 | 2931 |
keir@21265 | 2932 /* |
keir@21265 | 2933 * returns one of the XEN_SCHEDULER_* constants from public/domctl.h |
keir@21265 | 2934 * or -1 if an error occured. |
keir@21265 | 2935 */ |
keir@21265 | 2936 int libxl_get_sched_id(struct libxl_ctx *ctx) |
keir@21265 | 2937 { |
keir@21265 | 2938 int sched, ret; |
keir@21265 | 2939 |
keir@21265 | 2940 if ((ret = xc_sched_id(ctx->xch, &sched)) != 0) |
keir@21265 | 2941 return ret; |
keir@21265 | 2942 return sched; |
keir@21265 | 2943 } |
keir@21292 | 2944 |
keir@21292 | 2945 int libxl_sched_credit_domain_get(struct libxl_ctx *ctx, uint32_t domid, struct libxl_sched_credit *scinfo) |
keir@21292 | 2946 { |
keir@21292 | 2947 struct xen_domctl_sched_credit sdom; |
keir@21292 | 2948 int rc; |
keir@21292 | 2949 |
keir@21292 | 2950 rc = xc_sched_credit_domain_get(ctx->xch, domid, &sdom); |
keir@21292 | 2951 if (rc != 0) |
keir@21292 | 2952 return rc; |
keir@21292 | 2953 |
keir@21292 | 2954 scinfo->weight = sdom.weight; |
keir@21292 | 2955 scinfo->cap = sdom.cap; |
keir@21292 | 2956 |
keir@21292 | 2957 return 0; |
keir@21292 | 2958 } |
keir@21292 | 2959 |
keir@21292 | 2960 int libxl_sched_credit_domain_set(struct libxl_ctx *ctx, uint32_t domid, struct libxl_sched_credit *scinfo) |
keir@21292 | 2961 { |
keir@21292 | 2962 struct xen_domctl_sched_credit sdom; |
keir@21292 | 2963 xc_domaininfo_t domaininfo; |
keir@21292 | 2964 int rc; |
keir@21292 | 2965 |
keir@21292 | 2966 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo); |
keir@21292 | 2967 if (rc != 1 || domaininfo.domain != domid) |
keir@21292 | 2968 return rc; |
keir@21292 | 2969 |
keir@21292 | 2970 |
keir@21292 | 2971 if (scinfo->weight < 1 || scinfo->weight > 65535) { |
keir@21292 | 2972 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, |
keir@21292 | 2973 "Cpu weight out of range, valid values are within range from 1 to 65535"); |
keir@21292 | 2974 return -1; |
keir@21292 | 2975 } |
keir@21292 | 2976 |
keir@21292 | 2977 if (scinfo->cap < 0 || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) { |
keir@21292 | 2978 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, |
keir@21292 | 2979 "Cpu cap out of range, valid range is from 0 to %d for specified number of vcpus", |
keir@21292 | 2980 ((domaininfo.max_vcpu_id + 1) * 100)); |
keir@21292 | 2981 return -1; |
keir@21292 | 2982 } |
keir@21292 | 2983 |
keir@21292 | 2984 sdom.weight = scinfo->weight; |
keir@21292 | 2985 sdom.cap = scinfo->cap; |
keir@21292 | 2986 |
keir@21292 | 2987 rc = xc_sched_credit_domain_set(ctx->xch, domid, &sdom); |
keir@21292 | 2988 if (rc != 0) |
keir@21292 | 2989 return rc; |
keir@21292 | 2990 |
keir@21292 | 2991 return 0; |
keir@21292 | 2992 } |
keir@21292 | 2993 |
keir@21393 | 2994 static int trigger_type_from_string(char *trigger_name) |
keir@21393 | 2995 { |
keir@21393 | 2996 if (!strcmp(trigger_name, "nmi")) |
keir@21393 | 2997 return XEN_DOMCTL_SENDTRIGGER_NMI; |
keir@21393 | 2998 else if (!strcmp(trigger_name, "reset")) |
keir@21393 | 2999 return XEN_DOMCTL_SENDTRIGGER_RESET; |
keir@21393 | 3000 else if (!strcmp(trigger_name, "init")) |
keir@21393 | 3001 return XEN_DOMCTL_SENDTRIGGER_INIT; |
keir@21393 | 3002 else if (!strcmp(trigger_name, "power")) |
keir@21393 | 3003 return XEN_DOMCTL_SENDTRIGGER_POWER; |
keir@21393 | 3004 else if (!strcmp(trigger_name, "sleep")) |
keir@21393 | 3005 return XEN_DOMCTL_SENDTRIGGER_SLEEP; |
keir@21393 | 3006 else |
keir@21393 | 3007 return -1; |
keir@21393 | 3008 } |
keir@21393 | 3009 |
keir@21393 | 3010 int libxl_send_trigger(struct libxl_ctx *ctx, uint32_t domid, char *trigger_name, uint32_t vcpuid) |
keir@21393 | 3011 { |
keir@21393 | 3012 int rc = -1; |
keir@21393 | 3013 int trigger_type = trigger_type_from_string(trigger_name); |
keir@21393 | 3014 |
keir@21393 | 3015 if (trigger_type == -1) { |
keir@21393 | 3016 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1, |
keir@21393 | 3017 "Invalid trigger, valid triggers are <nmi|reset|init|power|sleep>"); |
keir@21393 | 3018 return -1; |
keir@21393 | 3019 } |
keir@21393 | 3020 |
keir@21393 | 3021 rc = xc_domain_send_trigger(ctx->xch, domid, trigger_type, vcpuid); |
keir@21393 | 3022 if (rc != 0) |
keir@21393 | 3023 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, |
keir@21393 | 3024 "Send trigger '%s' failed", trigger_name); |
keir@21393 | 3025 |
keir@21393 | 3026 return rc; |
keir@21393 | 3027 } |
keir@21402 | 3028 |
keir@21402 | 3029 int libxl_send_sysrq(struct libxl_ctx *ctx, uint32_t domid, char sysrq) |
keir@21402 | 3030 { |
keir@21402 | 3031 char *dompath = libxl_xs_get_dompath(ctx, domid); |
keir@21402 | 3032 |
keir@21402 | 3033 libxl_xs_write(ctx, XBT_NULL, libxl_sprintf(ctx, "%s/control/sysrq", dompath), "%c", sysrq); |
keir@21402 | 3034 |
keir@21402 | 3035 return 0; |
keir@21402 | 3036 } |
keir@21402 | 3037 |
keir@21472 | 3038 int libxl_send_debug_keys(struct libxl_ctx *ctx, char *keys) |
keir@21472 | 3039 { |
keir@21472 | 3040 return xc_send_debug_keys(ctx->xch, keys); |
keir@21472 | 3041 } |
keir@21472 | 3042 |
keir@21496 | 3043 struct libxl_xen_console_reader * |
keir@21496 | 3044 libxl_xen_console_read_start(struct libxl_ctx *ctx, int clear) |
keir@21496 | 3045 { |
keir@21496 | 3046 struct libxl_xen_console_reader *cr; |
keir@21496 | 3047 unsigned int size = 16384; |
keir@21496 | 3048 char *buf = malloc(size); |
keir@21496 | 3049 |
keir@21496 | 3050 if (!buf) { |
keir@21496 | 3051 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc buffer for libxl_xen_console_reader," |
keir@21496 | 3052 " size is %u", size); |
keir@21496 | 3053 return NULL; |
keir@21496 | 3054 } |
keir@21496 | 3055 |
keir@21496 | 3056 cr = malloc(sizeof(struct libxl_xen_console_reader)); |
keir@21496 | 3057 if (!cr) { |
keir@21496 | 3058 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc libxl_xen_console_reader"); |
keir@21496 | 3059 return NULL; |
keir@21496 | 3060 } |
keir@21496 | 3061 |
keir@21496 | 3062 memset(cr, 0, sizeof(struct libxl_xen_console_reader)); |
keir@21496 | 3063 cr->buffer = buf; |
keir@21496 | 3064 cr->size = size; |
keir@21496 | 3065 cr->count = size; |
keir@21496 | 3066 cr->clear = clear; |
keir@21496 | 3067 cr->incremental = 1; |
keir@21496 | 3068 |
keir@21496 | 3069 return cr; |
keir@21496 | 3070 } |
keir@21496 | 3071 |
keir@21496 | 3072 /* return values: *line_r |
keir@21496 | 3073 * 1 success, whole line obtained from buffer non-0 |
keir@21496 | 3074 * 0 no more lines available right now 0 |
keir@21496 | 3075 * negative error code ERROR_* 0 |
keir@21496 | 3076 * On success *line_r is updated to point to a nul-terminated |
keir@21496 | 3077 * string which is valid until the next call on the same console |
keir@21496 | 3078 * reader. The libxl caller may overwrite parts of the string |
keir@21496 | 3079 * if it wishes. */ |
keir@21496 | 3080 int libxl_xen_console_read_line(struct libxl_ctx *ctx, |
keir@21496 | 3081 struct libxl_xen_console_reader *cr, |
keir@21496 | 3082 char **line_r) |
keir@21496 | 3083 { |
keir@21496 | 3084 int ret; |
keir@21496 | 3085 |
keir@21496 | 3086 memset(cr->buffer, 0, cr->size); |
keir@21496 | 3087 ret = xc_readconsolering(ctx->xch, &cr->buffer, &cr->count, |
keir@21496 | 3088 cr->clear, cr->incremental, &cr->index); |
keir@21496 | 3089 if (!ret) { |
keir@21496 | 3090 if (cr->count) { |
keir@21496 | 3091 *line_r = cr->buffer; |
keir@21496 | 3092 ret = 1; |
keir@21496 | 3093 } else { |
keir@21496 | 3094 *line_r = NULL; |
keir@21496 | 3095 ret = 0; |
keir@21496 | 3096 } |
keir@21496 | 3097 } |
keir@21496 | 3098 |
keir@21496 | 3099 return ret; |
keir@21496 | 3100 } |
keir@21496 | 3101 |
keir@21496 | 3102 void libxl_xen_console_read_finish(struct libxl_ctx *ctx, |
keir@21496 | 3103 struct libxl_xen_console_reader *cr) |
keir@21496 | 3104 { |
keir@21496 | 3105 free(cr->buffer); |
keir@21496 | 3106 free(cr); |
keir@21496 | 3107 } |
keir@21496 | 3108 |
keir@21425 | 3109 uint32_t libxl_vm_get_start_time(struct libxl_ctx *ctx, uint32_t domid) |
keir@21425 | 3110 { |
keir@21425 | 3111 char *dompath = libxl_xs_get_dompath(ctx, domid); |
keir@21425 | 3112 char *vm_path, *start_time; |
keir@21425 | 3113 |
keir@21425 | 3114 vm_path = libxl_xs_read( |
keir@21425 | 3115 ctx, XBT_NULL, libxl_sprintf(ctx, "%s/vm", dompath)); |
keir@21425 | 3116 start_time = libxl_xs_read( |
keir@21425 | 3117 ctx, XBT_NULL, libxl_sprintf(ctx, "%s/start_time", vm_path)); |
keir@21425 | 3118 if (start_time == NULL) { |
keir@21425 | 3119 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1, |
keir@21425 | 3120 "Can't get start time of domain '%d'", domid); |
keir@21425 | 3121 return -1; |
keir@21425 | 3122 } |
keir@21425 | 3123 |
keir@21425 | 3124 return strtoul(start_time, NULL, 10); |
keir@21425 | 3125 } |
keir@21425 | 3126 |
keir@21471 | 3127 char *libxl_tmem_list(struct libxl_ctx *ctx, uint32_t domid, int use_long) |
keir@21471 | 3128 { |
keir@21471 | 3129 int rc; |
keir@21471 | 3130 char _buf[32768]; |
keir@21471 | 3131 |
keir@21471 | 3132 rc = xc_tmem_control(ctx->xch, -1, TMEMC_LIST, domid, 32768, use_long, |
keir@21471 | 3133 0, _buf); |
keir@21471 | 3134 if (rc < 0) { |
keir@21471 | 3135 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, |
keir@21471 | 3136 "Can not get tmem list"); |
keir@21471 | 3137 return NULL; |
keir@21471 | 3138 } |
keir@21471 | 3139 |
keir@21471 | 3140 return strdup(_buf); |
keir@21471 | 3141 } |
keir@21471 | 3142 |
keir@21471 | 3143 int libxl_tmem_freeze(struct libxl_ctx *ctx, uint32_t domid) |
keir@21471 | 3144 { |
keir@21471 | 3145 int rc; |
keir@21471 | 3146 |
keir@21471 | 3147 rc = xc_tmem_control(ctx->xch, -1, TMEMC_FREEZE, domid, 0, 0, |
keir@21471 | 3148 0, NULL); |
keir@21471 | 3149 if (rc < 0) { |
keir@21471 | 3150 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, |
keir@21471 | 3151 "Can not freeze tmem pools"); |
keir@21471 | 3152 return -1; |
keir@21471 | 3153 } |
keir@21471 | 3154 |
keir@21471 | 3155 return rc; |
keir@21471 | 3156 } |
keir@21471 | 3157 |
keir@21471 | 3158 int libxl_tmem_destroy(struct libxl_ctx *ctx, uint32_t domid) |
keir@21471 | 3159 { |
keir@21471 | 3160 int rc; |
keir@21471 | 3161 |
keir@21471 | 3162 rc = xc_tmem_control(ctx->xch, -1, TMEMC_DESTROY, domid, 0, 0, |
keir@21471 | 3163 0, NULL); |
keir@21471 | 3164 if (rc < 0) { |
keir@21471 | 3165 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, |
keir@21471 | 3166 "Can not destroy tmem pools"); |
keir@21471 | 3167 return -1; |
keir@21471 | 3168 } |
keir@21471 | 3169 |
keir@21471 | 3170 return rc; |
keir@21471 | 3171 } |
keir@21471 | 3172 |
keir@21471 | 3173 int libxl_tmem_thaw(struct libxl_ctx *ctx, uint32_t domid) |
keir@21471 | 3174 { |
keir@21471 | 3175 int rc; |
keir@21471 | 3176 |
keir@21471 | 3177 rc = xc_tmem_control(ctx->xch, -1, TMEMC_THAW, domid, 0, 0, |
keir@21471 | 3178 0, NULL); |
keir@21471 | 3179 if (rc < 0) { |
keir@21471 | 3180 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, |
keir@21471 | 3181 "Can not thaw tmem pools"); |
keir@21471 | 3182 return -1; |
keir@21471 | 3183 } |
keir@21471 | 3184 |
keir@21471 | 3185 return rc; |
keir@21471 | 3186 } |
keir@21471 | 3187 |
keir@21471 | 3188 static int32_t tmem_setop_from_string(char *set_name) |
keir@21471 | 3189 { |
keir@21471 | 3190 if (!strcmp(set_name, "weight")) |
keir@21471 | 3191 return TMEMC_SET_WEIGHT; |
keir@21471 | 3192 else if (!strcmp(set_name, "cap")) |
keir@21471 | 3193 return TMEMC_SET_CAP; |
keir@21471 | 3194 else if (!strcmp(set_name, "compress")) |
keir@21471 | 3195 return TMEMC_SET_COMPRESS; |
keir@21471 | 3196 else |
keir@21471 | 3197 return -1; |
keir@21471 | 3198 } |
keir@21471 | 3199 |
keir@21471 | 3200 int libxl_tmem_set(struct libxl_ctx *ctx, uint32_t domid, char* name, uint32_t set) |
keir@21471 | 3201 { |
keir@21471 | 3202 int rc; |
keir@21471 | 3203 int32_t subop = tmem_setop_from_string(name); |
keir@21471 | 3204 |
keir@21471 | 3205 if (subop == -1) { |
keir@21471 | 3206 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1, |
keir@21471 | 3207 "Invalid set, valid sets are <weight|cap|compress>"); |
keir@21471 | 3208 return -1; |
keir@21471 | 3209 } |
keir@21471 | 3210 rc = xc_tmem_control(ctx->xch, -1, subop, domid, set, 0, 0, NULL); |
keir@21471 | 3211 if (rc < 0) { |
keir@21471 | 3212 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, |
keir@21471 | 3213 "Can not set tmem %s", name); |
keir@21471 | 3214 return -1; |
keir@21471 | 3215 } |
keir@21471 | 3216 |
keir@21471 | 3217 return rc; |
keir@21471 | 3218 } |
keir@21471 | 3219 |
keir@21471 | 3220 int libxl_tmem_shared_auth(struct libxl_ctx *ctx, uint32_t domid, |
keir@21471 | 3221 char* uuid, int auth) |
keir@21471 | 3222 { |
keir@21471 | 3223 int rc; |
keir@21471 | 3224 |
keir@21471 | 3225 rc = xc_tmem_auth(ctx->xch, domid, uuid, auth); |
keir@21471 | 3226 if (rc < 0) { |
keir@21471 | 3227 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, |
keir@21471 | 3228 "Can not set tmem shared auth"); |
keir@21471 | 3229 return -1; |
keir@21471 | 3230 } |
keir@21471 | 3231 |
keir@21471 | 3232 return rc; |
keir@21471 | 3233 } |
keir@21471 | 3234 |
Ian@21848 | 3235 int libxl_file_reference_map(struct libxl_ctx *ctx, libxl_file_reference *f) |
Ian@21848 | 3236 { |
Ian@21848 | 3237 struct stat st_buf; |
Ian@21848 | 3238 int ret, fd; |
Ian@21848 | 3239 void *data; |
Ian@21848 | 3240 |
Ian@21848 | 3241 if (f->mapped) |
Ian@21848 | 3242 return 0; |
Ian@21848 | 3243 |
Ian@21848 | 3244 fd = open(f->path, O_RDONLY); |
Ian@21848 | 3245 if (f < 0) |
Ian@21848 | 3246 return ERROR_FAIL; |
Ian@21848 | 3247 |
Ian@21848 | 3248 ret = fstat(fd, &st_buf); |
Ian@21848 | 3249 if (ret < 0) |
Ian@21848 | 3250 goto out; |
Ian@21848 | 3251 |
Ian@21848 | 3252 ret = -1; |
Ian@21848 | 3253 data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); |
Ian@21848 | 3254 if (data == NULL) |
Ian@21848 | 3255 goto out; |
Ian@21848 | 3256 |
Ian@21848 | 3257 f->mapped = 1; |
Ian@21848 | 3258 f->data = data; |
Ian@21848 | 3259 f->size = st_buf.st_size; |
Ian@21848 | 3260 |
Ian@21848 | 3261 ret = 0; |
Ian@21848 | 3262 out: |
Ian@21848 | 3263 close(fd); |
Ian@21848 | 3264 |
Ian@21848 | 3265 return ret == 0 ? 0 : ERROR_FAIL; |
Ian@21848 | 3266 } |
Ian@21848 | 3267 |
Ian@21848 | 3268 int libxl_file_reference_unmap(struct libxl_ctx *ctx, libxl_file_reference *f) |
Ian@21848 | 3269 { |
Ian@21848 | 3270 int ret; |
Ian@21848 | 3271 |
Ian@21848 | 3272 if (!f->mapped) |
Ian@21848 | 3273 return 0; |
Ian@21848 | 3274 |
Ian@21848 | 3275 ret = munmap(f->data, f->size); |
Ian@21848 | 3276 |
Ian@21848 | 3277 return ret == 0 ? 0 : ERROR_FAIL; |
Ian@21848 | 3278 } |