1 /*
2 * Copyright 2009-2017 Citrix Ltd and other contributors
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; version 2.1 only. with the special
7 * exception on linking described in file LICENSE.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 */
14
15 #include "libxl_osdeps.h"
16
17 #include "libxl_internal.h"
18
libxl_ctx_alloc(libxl_ctx ** pctx,int version,unsigned flags,xentoollog_logger * lg)19 int libxl_ctx_alloc(libxl_ctx **pctx, int version,
20 unsigned flags, xentoollog_logger * lg)
21 {
22 libxl_ctx *ctx = NULL;
23 libxl__gc gc_buf, *gc = NULL;
24 int rc;
25
26 if (version != LIBXL_VERSION) { rc = ERROR_VERSION; goto out; }
27
28 ctx = malloc(sizeof(*ctx));
29 if (!ctx) {
30 xtl_log(lg, XTL_ERROR, errno, "libxl",
31 "%s:%d:%s: Failed to allocate context\n",
32 __FILE__, __LINE__, __func__);
33 rc = ERROR_NOMEM; goto out;
34 }
35
36 memset(ctx, 0, sizeof(libxl_ctx));
37 ctx->lg = lg;
38
39 /* First initialise pointers etc. (cannot fail) */
40
41 ctx->nogc_gc.alloc_maxsize = -1;
42 ctx->nogc_gc.owner = ctx;
43
44 LIBXL_TAILQ_INIT(&ctx->occurred);
45
46 ctx->osevent_hooks = 0;
47
48 ctx->poller_app = 0;
49 LIBXL_LIST_INIT(&ctx->pollers_event);
50 LIBXL_LIST_INIT(&ctx->pollers_idle);
51 LIBXL_LIST_INIT(&ctx->pollers_active);
52
53 LIBXL_LIST_INIT(&ctx->efds);
54 LIBXL_TAILQ_INIT(&ctx->etimes);
55
56 ctx->watch_slots = 0;
57 LIBXL_SLIST_INIT(&ctx->watch_freeslots);
58 libxl__ev_fd_init(&ctx->watch_efd);
59
60 ctx->xce = 0;
61 LIBXL_LIST_INIT(&ctx->evtchns_waiting);
62 libxl__ev_fd_init(&ctx->evtchn_efd);
63
64 LIBXL_LIST_INIT(&ctx->aos_inprogress);
65
66 LIBXL_TAILQ_INIT(&ctx->death_list);
67 libxl__ev_xswatch_init(&ctx->death_watch);
68
69 ctx->childproc_hooks = &libxl__childproc_default_hooks;
70 ctx->childproc_user = 0;
71
72 ctx->sigchld_selfpipe[0] = -1;
73 ctx->sigchld_selfpipe[1] = -1;
74 libxl__ev_fd_init(&ctx->sigchld_selfpipe_efd);
75
76 /* The mutex is special because we can't idempotently destroy it */
77
78 if (libxl__init_recursive_mutex(ctx, &ctx->lock) < 0) {
79 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Failed to initialize mutex");
80 free(ctx);
81 ctx = 0;
82 rc = ERROR_FAIL;
83 goto out;
84 }
85
86 /* Now ctx is safe for ctx_free; failures simply set rc and "goto out" */
87 LIBXL_INIT_GC(gc_buf,ctx);
88 gc = &gc_buf;
89 /* Now gc is useable */
90
91 rc = libxl__atfork_init(ctx);
92 if (rc) goto out;
93
94 ctx->poller_app = libxl__poller_get(gc);
95 if (!ctx->poller_app) {
96 rc = ERROR_FAIL;
97 goto out;
98 }
99
100 ctx->xch = xc_interface_open(lg,lg,0);
101 if (!ctx->xch) {
102 LOGEV(ERROR, errno, "cannot open libxc handle");
103 rc = ERROR_FAIL; goto out;
104 }
105
106 ctx->xsh = xs_daemon_open();
107 if (!ctx->xsh)
108 ctx->xsh = xs_domain_open();
109 if (!ctx->xsh) {
110 LOGEV(ERROR, errno, "cannot connect to xenstore");
111 rc = ERROR_FAIL; goto out;
112 }
113
114 *pctx = ctx;
115 return 0;
116
117 out:
118 if (gc) libxl__free_all(gc);
119 libxl_ctx_free(ctx);
120 *pctx = NULL;
121 return rc;
122 }
123
free_disable_deaths(libxl__gc * gc,struct libxl__evgen_domain_death_list * l)124 static void free_disable_deaths(libxl__gc *gc,
125 struct libxl__evgen_domain_death_list *l) {
126 libxl_evgen_domain_death *death;
127 while ((death = LIBXL_TAILQ_FIRST(l)))
128 libxl__evdisable_domain_death(gc, death);
129 }
130
discard_events(struct libxl__event_list * l)131 static void discard_events(struct libxl__event_list *l) {
132 /* doesn't bother unlinking from the list, so l is corrupt on return */
133 libxl_event *ev, *next;
134 LIBXL_TAILQ_FOREACH_SAFE(ev, l, link, next)
135 libxl_event_free(0, ev);
136 }
137
libxl_ctx_free(libxl_ctx * ctx)138 int libxl_ctx_free(libxl_ctx *ctx)
139 {
140 if (!ctx) return 0;
141
142 int i;
143 GC_INIT(ctx);
144
145 CTX_LOCK;
146 assert(!ctx->osevent_in_hook);
147 CTX->osevent_in_hook += 1000; /* make violations easier to debug */
148
149 /* Deregister all libxl__ev_KINDs: */
150
151 free_disable_deaths(gc, &CTX->death_list);
152 free_disable_deaths(gc, &CTX->death_reported);
153
154 libxl_evgen_disk_eject *eject;
155 while ((eject = LIBXL_LIST_FIRST(&CTX->disk_eject_evgens)))
156 libxl__evdisable_disk_eject(gc, eject);
157
158 libxl_childproc_setmode(CTX,0,0);
159 for (i = 0; i < ctx->watch_nslots; i++)
160 assert(!libxl__watch_slot_contents(gc, i));
161 assert(!libxl__ev_fd_isregistered(&ctx->watch_efd));
162 assert(!libxl__ev_fd_isregistered(&ctx->evtchn_efd));
163 assert(!libxl__ev_fd_isregistered(&ctx->sigchld_selfpipe_efd));
164
165 /* Now there should be no more events requested from the application: */
166
167 assert(LIBXL_LIST_EMPTY(&ctx->efds));
168 assert(LIBXL_TAILQ_EMPTY(&ctx->etimes));
169 assert(LIBXL_LIST_EMPTY(&ctx->evtchns_waiting));
170 assert(LIBXL_LIST_EMPTY(&ctx->aos_inprogress));
171
172 if (ctx->xch) xc_interface_close(ctx->xch);
173 libxl_version_info_dispose(&ctx->version_info);
174 if (ctx->xsh) xs_daemon_close(ctx->xsh);
175 if (ctx->xce) xenevtchn_close(ctx->xce);
176
177 libxl__poller_put(ctx, ctx->poller_app);
178 ctx->poller_app = NULL;
179 assert(LIBXL_LIST_EMPTY(&ctx->pollers_event));
180 assert(LIBXL_LIST_EMPTY(&ctx->pollers_active));
181 libxl__poller *poller, *poller_tmp;
182 LIBXL_LIST_FOREACH_SAFE(poller, &ctx->pollers_idle, entry, poller_tmp) {
183 libxl__poller_dispose(poller);
184 free(poller);
185 }
186
187 free(ctx->watch_slots);
188
189 discard_events(&ctx->occurred);
190
191 /* If we have outstanding children, then the application inherits
192 * them; we wish the application good luck with understanding
193 * this if and when it reaps them. */
194 libxl__sigchld_notneeded(gc);
195 libxl__pipe_close(ctx->sigchld_selfpipe);
196
197 CTX_UNLOCK;
198 pthread_mutex_destroy(&ctx->lock);
199
200 GC_FREE;
201 free(ctx);
202 return 0;
203 }
204
libxl_string_list_dispose(libxl_string_list * psl)205 void libxl_string_list_dispose(libxl_string_list *psl)
206 {
207 int i;
208 libxl_string_list sl = *psl;
209
210 if (!sl)
211 return;
212
213 for (i = 0; sl[i] != NULL; i++) {
214 free(sl[i]);
215 sl[i] = NULL;
216 }
217 free(sl);
218 *psl = NULL;
219 }
220
libxl_string_list_copy(libxl_ctx * ctx,libxl_string_list * dst,const libxl_string_list * src)221 void libxl_string_list_copy(libxl_ctx *ctx,
222 libxl_string_list *dst,
223 const libxl_string_list *src)
224 {
225 GC_INIT(ctx);
226 int i, len;
227
228 if (!*src) {
229 *dst = NULL;
230 goto out;
231 }
232
233 len = libxl_string_list_length(src);
234 /* one extra slot for sentinel */
235 *dst = libxl__calloc(NOGC, len + 1, sizeof(char *));
236
237 for (i = 0; i < len; i++)
238 (*dst)[i] = libxl__strdup(NOGC, (*src)[i]);
239
240 out:
241 GC_FREE;
242 }
243
libxl_string_list_length(const libxl_string_list * psl)244 int libxl_string_list_length(const libxl_string_list *psl)
245 {
246 int i = 0;
247
248 if (*psl)
249 while ((*psl)[i])
250 i++;
251
252 return i;
253 }
254
libxl_key_value_list_length(const libxl_key_value_list * pkvl)255 int libxl_key_value_list_length(const libxl_key_value_list *pkvl)
256 {
257 int i = 0;
258 libxl_key_value_list kvl = *pkvl;
259
260 if (kvl) {
261 while (kvl[2 * i]) /* Only checks keys */
262 i++;
263 }
264
265 return i;
266 }
267
libxl_key_value_list_dispose(libxl_key_value_list * pkvl)268 void libxl_key_value_list_dispose(libxl_key_value_list *pkvl)
269 {
270 int i;
271 libxl_key_value_list kvl = *pkvl;
272
273 if (!kvl)
274 return;
275
276 for (i = 0; kvl[i] != NULL; i += 2) {
277 free(kvl[i]);
278 kvl[i] = NULL;
279 if (kvl[i + 1]) {
280 free(kvl[i + 1]);
281 kvl[i+1] = NULL;
282 }
283 }
284 free(kvl);
285 *pkvl = NULL;
286 }
287
libxl_key_value_list_copy(libxl_ctx * ctx,libxl_key_value_list * dst,const libxl_key_value_list * src)288 void libxl_key_value_list_copy(libxl_ctx *ctx,
289 libxl_key_value_list *dst,
290 const libxl_key_value_list *src)
291 {
292 GC_INIT(ctx);
293 int i, len;
294
295 if (*src == NULL) {
296 *dst = NULL;
297 goto out;
298 }
299
300 len = libxl_key_value_list_length(src);
301 /* one extra slot for sentinel */
302 *dst = libxl__calloc(NOGC, len * 2 + 1, sizeof(char *));
303
304 for (i = 0; i < len * 2; i += 2) {
305 (*dst)[i] = libxl__strdup(NOGC, (*src)[i]);
306 if ((*src)[i+1])
307 (*dst)[i+1] = libxl__strdup(NOGC, (*src)[i+1]);
308 else
309 (*dst)[i+1] = NULL;
310 }
311
312 out:
313 GC_FREE;
314 }
315
libxl_defbool_set(libxl_defbool * db,bool b)316 void libxl_defbool_set(libxl_defbool *db, bool b)
317 {
318 db->val = b ? LIBXL__DEFBOOL_TRUE : LIBXL__DEFBOOL_FALSE;
319 }
320
libxl_defbool_unset(libxl_defbool * db)321 void libxl_defbool_unset(libxl_defbool *db)
322 {
323 db->val = LIBXL__DEFBOOL_DEFAULT;
324 }
325
libxl_defbool_is_default(libxl_defbool db)326 bool libxl_defbool_is_default(libxl_defbool db)
327 {
328 return !db.val;
329 }
330
libxl_defbool_setdefault(libxl_defbool * db,bool b)331 void libxl_defbool_setdefault(libxl_defbool *db, bool b)
332 {
333 if (libxl_defbool_is_default(*db))
334 libxl_defbool_set(db, b);
335 }
336
libxl_defbool_val(libxl_defbool db)337 bool libxl_defbool_val(libxl_defbool db)
338 {
339 assert(!libxl_defbool_is_default(db));
340 return db.val > 0;
341 }
342
libxl_defbool_to_string(libxl_defbool b)343 const char *libxl_defbool_to_string(libxl_defbool b)
344 {
345 if (b.val < 0)
346 return LIBXL__DEFBOOL_STR_FALSE;
347 else if (b.val > 0)
348 return LIBXL__DEFBOOL_STR_TRUE;
349 else
350 return LIBXL__DEFBOOL_STR_DEFAULT;
351 }
352
353 /******************************************************************************/
libxl_get_physinfo(libxl_ctx * ctx,libxl_physinfo * physinfo)354 int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
355 {
356 xc_physinfo_t xcphysinfo = { 0 };
357 int rc;
358 long l;
359 GC_INIT(ctx);
360
361 rc = xc_physinfo(ctx->xch, &xcphysinfo);
362 if (rc != 0) {
363 LOGE(ERROR, "getting physinfo");
364 GC_FREE;
365 return ERROR_FAIL;
366 }
367 physinfo->threads_per_core = xcphysinfo.threads_per_core;
368 physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
369 physinfo->max_cpu_id = xcphysinfo.max_cpu_id;
370 physinfo->nr_cpus = xcphysinfo.nr_cpus;
371 physinfo->cpu_khz = xcphysinfo.cpu_khz;
372 physinfo->total_pages = xcphysinfo.total_pages;
373 physinfo->free_pages = xcphysinfo.free_pages;
374 physinfo->scrub_pages = xcphysinfo.scrub_pages;
375 physinfo->outstanding_pages = xcphysinfo.outstanding_pages;
376 physinfo->max_possible_mfn = xcphysinfo.max_mfn;
377 l = xc_sharing_freed_pages(ctx->xch);
378 if (l < 0 && errno == ENOSYS) {
379 l = 0;
380 } else if (l < 0) {
381 LOGEV(ERROR, l, "getting sharing freed pages");
382 GC_FREE;
383 return ERROR_FAIL;
384 }
385 physinfo->sharing_freed_pages = l;
386 l = xc_sharing_used_frames(ctx->xch);
387 if (l < 0 && errno == ENOSYS) {
388 l = 0;
389 } else if (l < 0) {
390 LOGEV(ERROR, l, "getting sharing used frames");
391 GC_FREE;
392 return ERROR_FAIL;
393 }
394 physinfo->sharing_used_frames = l;
395 physinfo->nr_nodes = xcphysinfo.nr_nodes;
396 memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap));
397
398 physinfo->cap_hvm = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_hvm);
399 physinfo->cap_pv = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_pv);
400 physinfo->cap_hvm_directio =
401 !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_directio);
402 physinfo->cap_hap = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_hap);
403 physinfo->cap_shadow =
404 !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_shadow);
405 physinfo->cap_iommu_hap_pt_share =
406 !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share);
407
408 GC_FREE;
409 return 0;
410 }
411
libxl_get_cpu_topology(libxl_ctx * ctx,int * nb_cpu_out)412 libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out)
413 {
414 GC_INIT(ctx);
415 xc_cputopo_t *cputopo;
416 libxl_cputopology *ret = NULL;
417 int i;
418 unsigned num_cpus = 0;
419
420 /* Setting buffer to NULL makes the call return number of CPUs */
421 if (xc_cputopoinfo(ctx->xch, &num_cpus, NULL))
422 {
423 LOGE(ERROR, "Unable to determine number of CPUS");
424 goto out;
425 }
426
427 cputopo = libxl__zalloc(gc, sizeof(*cputopo) * num_cpus);
428
429 if (xc_cputopoinfo(ctx->xch, &num_cpus, cputopo)) {
430 LOGE(ERROR, "CPU topology info hypercall failed");
431 goto out;
432 }
433
434 ret = libxl__zalloc(NOGC, sizeof(libxl_cputopology) * num_cpus);
435
436 for (i = 0; i < num_cpus; i++) {
437 #define V(map, i, invalid) ( cputopo[i].map == invalid) ? \
438 LIBXL_CPUTOPOLOGY_INVALID_ENTRY : cputopo[i].map
439 ret[i].core = V(core, i, XEN_INVALID_CORE_ID);
440 ret[i].socket = V(socket, i, XEN_INVALID_SOCKET_ID);
441 ret[i].node = V(node, i, XEN_INVALID_NODE_ID);
442 #undef V
443 }
444
445 *nb_cpu_out = num_cpus;
446
447 out:
448 GC_FREE;
449 return ret;
450 }
451
libxl_get_pci_topology(libxl_ctx * ctx,int * num_devs)452 libxl_pcitopology *libxl_get_pci_topology(libxl_ctx *ctx, int *num_devs)
453 {
454 GC_INIT(ctx);
455 physdev_pci_device_t *devs;
456 uint32_t *nodes;
457 libxl_pcitopology *ret = NULL;
458 int i, rc;
459
460 *num_devs = libxl__pci_numdevs(gc);
461 if (*num_devs < 0) {
462 LOG(ERROR, "Unable to determine number of PCI devices, rc %d",
463 *num_devs);
464 goto out;
465 }
466
467 devs = libxl__zalloc(gc, sizeof(*devs) * *num_devs);
468 nodes = libxl__zalloc(gc, sizeof(*nodes) * *num_devs);
469
470 rc = libxl__pci_topology_init(gc, devs, *num_devs);
471 if (rc) {
472 LOG(ERROR, "Cannot initialize PCI hypercall structure, rc %d", rc);
473 goto out;
474 }
475
476 if (xc_pcitopoinfo(ctx->xch, *num_devs, devs, nodes) != 0) {
477 LOGE(ERROR, "PCI topology info hypercall failed");
478 goto out;
479 }
480
481 ret = libxl__zalloc(NOGC, sizeof(libxl_pcitopology) * *num_devs);
482
483 for (i = 0; i < *num_devs; i++) {
484 ret[i].seg = devs[i].seg;
485 ret[i].bus = devs[i].bus;
486 ret[i].devfn = devs[i].devfn;
487 ret[i].node = ((nodes[i] == XEN_INVALID_NODE_ID) ||
488 (nodes[i] == XEN_INVALID_DEV)) ?
489 LIBXL_PCITOPOLOGY_INVALID_ENTRY : nodes[i];
490 }
491
492 out:
493 GC_FREE;
494 return ret;
495 }
496
libxl_get_numainfo(libxl_ctx * ctx,int * nr)497 libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr)
498 {
499 GC_INIT(ctx);
500 xc_meminfo_t *meminfo;
501 uint32_t *distance;
502 libxl_numainfo *ret = NULL;
503 int i, j;
504 unsigned num_nodes = 0;
505
506 if (xc_numainfo(ctx->xch, &num_nodes, NULL, NULL)) {
507 LOGE(ERROR, "Unable to determine number of nodes");
508 goto out;
509 }
510
511 meminfo = libxl__zalloc(gc, sizeof(*meminfo) * num_nodes);
512 distance = libxl__zalloc(gc, sizeof(*distance) * num_nodes * num_nodes);
513
514 if (xc_numainfo(ctx->xch, &num_nodes, meminfo, distance)) {
515 LOGE(ERROR, "getting numainfo");
516 goto out;
517 }
518
519 *nr = num_nodes;
520
521 ret = libxl__zalloc(NOGC, sizeof(libxl_numainfo) * num_nodes);
522 for (i = 0; i < num_nodes; i++)
523 ret[i].dists = libxl__calloc(NOGC, num_nodes, sizeof(*distance));
524
525 for (i = 0; i < num_nodes; i++) {
526 #define V(val, invalid) (val == invalid) ? \
527 LIBXL_NUMAINFO_INVALID_ENTRY : val
528 ret[i].size = V(meminfo[i].memsize, XEN_INVALID_MEM_SZ);
529 ret[i].free = V(meminfo[i].memfree, XEN_INVALID_MEM_SZ);
530 ret[i].num_dists = num_nodes;
531 for (j = 0; j < ret[i].num_dists; j++) {
532 unsigned idx = i * num_nodes + j;
533 ret[i].dists[j] = V(distance[idx], XEN_INVALID_NODE_DIST);
534 }
535 #undef V
536 }
537
538 out:
539 GC_FREE;
540 return ret;
541 }
542
libxl__xc_version_wrap(libxl__gc * gc,libxl_version_info * info,xen_build_id_t * build)543 static int libxl__xc_version_wrap(libxl__gc *gc, libxl_version_info *info,
544 xen_build_id_t *build)
545 {
546 int r;
547
548 r = xc_version(CTX->xch, XENVER_build_id, build);
549 switch (r) {
550 case -EPERM:
551 case -ENODATA:
552 case 0:
553 info->build_id = libxl__strdup(NOGC, "");
554 break;
555
556 case -ENOBUFS:
557 break;
558
559 default:
560 if (r > 0) {
561 unsigned int i;
562
563 info->build_id = libxl__zalloc(NOGC, (r * 2) + 1);
564
565 for (i = 0; i < r ; i++)
566 snprintf(&info->build_id[i * 2], 3, "%02hhx", build->buf[i]);
567
568 r = 0;
569 }
570 break;
571 }
572 return r;
573 }
574
libxl_get_version_info(libxl_ctx * ctx)575 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx)
576 {
577 GC_INIT(ctx);
578 union {
579 xen_extraversion_t xen_extra;
580 xen_compile_info_t xen_cc;
581 xen_changeset_info_t xen_chgset;
582 xen_capabilities_info_t xen_caps;
583 xen_platform_parameters_t p_parms;
584 xen_commandline_t xen_commandline;
585 xen_build_id_t build_id;
586 } u;
587 long xen_version;
588 int r;
589 libxl_version_info *info = &ctx->version_info;
590
591 if (info->xen_version_extra != NULL)
592 goto out;
593
594 xen_version = xc_version(ctx->xch, XENVER_version, NULL);
595 info->xen_version_major = xen_version >> 16;
596 info->xen_version_minor = xen_version & 0xFF;
597
598 xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra);
599 info->xen_version_extra = libxl__strdup(NOGC, u.xen_extra);
600
601 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
602 info->compiler = libxl__strdup(NOGC, u.xen_cc.compiler);
603 info->compile_by = libxl__strdup(NOGC, u.xen_cc.compile_by);
604 info->compile_domain = libxl__strdup(NOGC, u.xen_cc.compile_domain);
605 info->compile_date = libxl__strdup(NOGC, u.xen_cc.compile_date);
606
607 xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps);
608 info->capabilities = libxl__strdup(NOGC, u.xen_caps);
609
610 xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset);
611 info->changeset = libxl__strdup(NOGC, u.xen_chgset);
612
613 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
614 info->virt_start = u.p_parms.virt_start;
615
616 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
617
618 xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline);
619 info->commandline = libxl__strdup(NOGC, u.xen_commandline);
620
621 u.build_id.len = sizeof(u) - sizeof(u.build_id);
622 r = libxl__xc_version_wrap(gc, info, &u.build_id);
623 if (r == -ENOBUFS) {
624 xen_build_id_t *build_id;
625
626 build_id = libxl__zalloc(gc, info->pagesize);
627 build_id->len = info->pagesize - sizeof(*build_id);
628 r = libxl__xc_version_wrap(gc, info, build_id);
629 if (r) LOGEV(ERROR, r, "getting build_id");
630 }
631 out:
632 GC_FREE;
633 return info;
634 }
635
libxl_send_sysrq(libxl_ctx * ctx,uint32_t domid,char sysrq)636 int libxl_send_sysrq(libxl_ctx *ctx, uint32_t domid, char sysrq)
637 {
638 GC_INIT(ctx);
639 char *dompath = libxl__xs_get_dompath(gc, domid);
640
641 libxl__xs_printf(gc, XBT_NULL, GCSPRINTF("%s/control/sysrq", dompath),
642 "%c", sysrq);
643
644 GC_FREE;
645 return 0;
646 }
647
libxl_send_debug_keys(libxl_ctx * ctx,char * keys)648 int libxl_send_debug_keys(libxl_ctx *ctx, char *keys)
649 {
650 int ret;
651 GC_INIT(ctx);
652 ret = xc_send_debug_keys(ctx->xch, keys);
653 if ( ret < 0 ) {
654 LOGE(ERROR, "sending debug keys");
655 GC_FREE;
656 return ERROR_FAIL;
657 }
658 GC_FREE;
659 return 0;
660 }
661
libxl_set_parameters(libxl_ctx * ctx,char * params)662 int libxl_set_parameters(libxl_ctx *ctx, char *params)
663 {
664 int ret;
665 GC_INIT(ctx);
666 char *par, *val, *end, *path;
667 xenhypfs_handle *hypfs;
668
669 hypfs = xenhypfs_open(ctx->lg, 0);
670 if (!hypfs) {
671 LOGE(ERROR, "opening Xen hypfs");
672 ret = ERROR_FAIL;
673 goto out;
674 }
675
676 while (isblank(*params))
677 params++;
678
679 for (par = params; *par; par = end) {
680 end = strchr(par, ' ');
681 if (!end)
682 end = par + strlen(par);
683
684 val = strchr(par, '=');
685 if (val > end)
686 val = NULL;
687 if (!val && !strncmp(par, "no", 2)) {
688 path = libxl__sprintf(gc, "/params/%s", par + 2);
689 path[end - par - 2 + 8] = 0;
690 val = "no";
691 par += 2;
692 } else {
693 path = libxl__sprintf(gc, "/params/%s", par);
694 path[val - par + 8] = 0;
695 val = libxl__strndup(gc, val + 1, end - val - 1);
696 }
697
698 LOG(DEBUG, "setting node \"%s\" to value \"%s\"", path, val);
699 ret = xenhypfs_write(hypfs, path, val);
700 if (ret < 0) {
701 LOGE(ERROR, "setting parameters");
702 ret = ERROR_FAIL;
703 goto out;
704 }
705
706 while (isblank(*end))
707 end++;
708 }
709
710 ret = 0;
711
712 out:
713 xenhypfs_close(hypfs);
714 GC_FREE;
715 return ret;
716 }
717
fd_set_flags(libxl_ctx * ctx,int fd,int fcntlgetop,int fcntlsetop,const char * fl,int flagmask,int set_p)718 static int fd_set_flags(libxl_ctx *ctx, int fd,
719 int fcntlgetop, int fcntlsetop, const char *fl,
720 int flagmask, int set_p)
721 {
722 int flags, r;
723 GC_INIT(ctx);
724
725 flags = fcntl(fd, fcntlgetop);
726 if (flags == -1) {
727 LOGE(ERROR, "fcntl(,F_GET%s) failed", fl);
728 GC_FREE;
729 return ERROR_FAIL;
730 }
731
732 if (set_p)
733 flags |= flagmask;
734 else
735 flags &= ~flagmask;
736
737 r = fcntl(fd, fcntlsetop, flags);
738 if (r == -1) {
739 LOGE(ERROR, "fcntl(,F_SET%s) failed", fl);
740 GC_FREE;
741 return ERROR_FAIL;
742 }
743
744 GC_FREE;
745 return 0;
746 }
747
libxl_fd_set_cloexec(libxl_ctx * ctx,int fd,int cloexec)748 int libxl_fd_set_cloexec(libxl_ctx *ctx, int fd, int cloexec)
749 { return fd_set_flags(ctx,fd, F_GETFD,F_SETFD,"FD", FD_CLOEXEC, cloexec); }
750
libxl_fd_set_nonblock(libxl_ctx * ctx,int fd,int nonblock)751 int libxl_fd_set_nonblock(libxl_ctx *ctx, int fd, int nonblock)
752 { return fd_set_flags(ctx,fd, F_GETFL,F_SETFL,"FL", O_NONBLOCK, nonblock); }
753
libxl__fd_flags_modify_save(libxl__gc * gc,int fd,int mask,int val,int * r_oldflags)754 int libxl__fd_flags_modify_save(libxl__gc *gc, int fd,
755 int mask, int val, int *r_oldflags)
756 {
757 int rc, ret, fdfl;
758
759 fdfl = fcntl(fd, F_GETFL);
760 if (fdfl < 0) {
761 LOGE(ERROR, "failed to fcntl.F_GETFL for fd %d", fd);
762 rc = ERROR_FAIL;
763 goto out_err;
764 }
765
766 LOG(DEBUG, "fnctl F_GETFL flags for fd %d are 0x%x", fd, fdfl);
767
768 if (r_oldflags)
769 *r_oldflags = fdfl;
770
771 fdfl &= mask;
772 fdfl |= val;
773
774 LOG(DEBUG, "fnctl F_SETFL of fd %d to 0x%x", fd, fdfl);
775
776 ret = fcntl(fd, F_SETFL, fdfl);
777 if (ret < 0) {
778 LOGE(ERROR, "failed to fcntl.F_SETFL for fd %d", fd);
779 rc = ERROR_FAIL;
780 goto out_err;
781 }
782
783 rc = 0;
784
785 out_err:
786 return rc;
787 }
788
libxl__fd_flags_restore(libxl__gc * gc,int fd,int fdfl)789 int libxl__fd_flags_restore(libxl__gc *gc, int fd, int fdfl)
790 {
791 int ret, rc;
792
793 LOG(DEBUG, "fnctl F_SETFL of fd %d to 0x%x", fd, fdfl);
794
795 ret = fcntl(fd, F_SETFL, fdfl);
796 if (ret < 0) {
797 LOGE(ERROR, "failed to fcntl.F_SETFL for fd %d", fd);
798 rc = ERROR_FAIL;
799 goto out_err;
800 }
801
802 rc = 0;
803
804 out_err:
805 return rc;
806
807 }
808
libxl_hwcap_copy(libxl_ctx * ctx,libxl_hwcap * dst,const libxl_hwcap * src)809 void libxl_hwcap_copy(libxl_ctx *ctx,libxl_hwcap *dst, const libxl_hwcap *src)
810 {
811 int i;
812
813 for (i = 0; i < 8; i++)
814 (*dst)[i] = (*src)[i];
815 }
816
libxl_mac_copy(libxl_ctx * ctx,libxl_mac * dst,const libxl_mac * src)817 void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const libxl_mac *src)
818 {
819 int i;
820
821 for (i = 0; i < 6; i++)
822 (*dst)[i] = (*src)[i];
823 }
824
825 /*
826 * Local variables:
827 * mode: C
828 * c-basic-offset: 4
829 * indent-tabs-mode: nil
830 * End:
831 */
832