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_fds_changed);
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_fds_changed));
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_hvm_directio =
400 !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_hvm_directio);
401
402 GC_FREE;
403 return 0;
404 }
405
libxl_get_cpu_topology(libxl_ctx * ctx,int * nb_cpu_out)406 libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out)
407 {
408 GC_INIT(ctx);
409 xc_cputopo_t *cputopo;
410 libxl_cputopology *ret = NULL;
411 int i;
412 unsigned num_cpus = 0;
413
414 /* Setting buffer to NULL makes the call return number of CPUs */
415 if (xc_cputopoinfo(ctx->xch, &num_cpus, NULL))
416 {
417 LOGE(ERROR, "Unable to determine number of CPUS");
418 goto out;
419 }
420
421 cputopo = libxl__zalloc(gc, sizeof(*cputopo) * num_cpus);
422
423 if (xc_cputopoinfo(ctx->xch, &num_cpus, cputopo)) {
424 LOGE(ERROR, "CPU topology info hypercall failed");
425 goto out;
426 }
427
428 ret = libxl__zalloc(NOGC, sizeof(libxl_cputopology) * num_cpus);
429
430 for (i = 0; i < num_cpus; i++) {
431 #define V(map, i, invalid) ( cputopo[i].map == invalid) ? \
432 LIBXL_CPUTOPOLOGY_INVALID_ENTRY : cputopo[i].map
433 ret[i].core = V(core, i, XEN_INVALID_CORE_ID);
434 ret[i].socket = V(socket, i, XEN_INVALID_SOCKET_ID);
435 ret[i].node = V(node, i, XEN_INVALID_NODE_ID);
436 #undef V
437 }
438
439 *nb_cpu_out = num_cpus;
440
441 out:
442 GC_FREE;
443 return ret;
444 }
445
libxl_get_pci_topology(libxl_ctx * ctx,int * num_devs)446 libxl_pcitopology *libxl_get_pci_topology(libxl_ctx *ctx, int *num_devs)
447 {
448 GC_INIT(ctx);
449 physdev_pci_device_t *devs;
450 uint32_t *nodes;
451 libxl_pcitopology *ret = NULL;
452 int i, rc;
453
454 *num_devs = libxl__pci_numdevs(gc);
455 if (*num_devs < 0) {
456 LOG(ERROR, "Unable to determine number of PCI devices, rc %d",
457 *num_devs);
458 goto out;
459 }
460
461 devs = libxl__zalloc(gc, sizeof(*devs) * *num_devs);
462 nodes = libxl__zalloc(gc, sizeof(*nodes) * *num_devs);
463
464 rc = libxl__pci_topology_init(gc, devs, *num_devs);
465 if (rc) {
466 LOG(ERROR, "Cannot initialize PCI hypercall structure, rc %d", rc);
467 goto out;
468 }
469
470 if (xc_pcitopoinfo(ctx->xch, *num_devs, devs, nodes) != 0) {
471 LOGE(ERROR, "PCI topology info hypercall failed");
472 goto out;
473 }
474
475 ret = libxl__zalloc(NOGC, sizeof(libxl_pcitopology) * *num_devs);
476
477 for (i = 0; i < *num_devs; i++) {
478 ret[i].seg = devs[i].seg;
479 ret[i].bus = devs[i].bus;
480 ret[i].devfn = devs[i].devfn;
481 ret[i].node = ((nodes[i] == XEN_INVALID_NODE_ID) ||
482 (nodes[i] == XEN_INVALID_DEV)) ?
483 LIBXL_PCITOPOLOGY_INVALID_ENTRY : nodes[i];
484 }
485
486 out:
487 GC_FREE;
488 return ret;
489 }
490
libxl_get_numainfo(libxl_ctx * ctx,int * nr)491 libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr)
492 {
493 GC_INIT(ctx);
494 xc_meminfo_t *meminfo;
495 uint32_t *distance;
496 libxl_numainfo *ret = NULL;
497 int i, j;
498 unsigned num_nodes = 0;
499
500 if (xc_numainfo(ctx->xch, &num_nodes, NULL, NULL)) {
501 LOGE(ERROR, "Unable to determine number of nodes");
502 goto out;
503 }
504
505 meminfo = libxl__zalloc(gc, sizeof(*meminfo) * num_nodes);
506 distance = libxl__zalloc(gc, sizeof(*distance) * num_nodes * num_nodes);
507
508 if (xc_numainfo(ctx->xch, &num_nodes, meminfo, distance)) {
509 LOGE(ERROR, "getting numainfo");
510 goto out;
511 }
512
513 *nr = num_nodes;
514
515 ret = libxl__zalloc(NOGC, sizeof(libxl_numainfo) * num_nodes);
516 for (i = 0; i < num_nodes; i++)
517 ret[i].dists = libxl__calloc(NOGC, num_nodes, sizeof(*distance));
518
519 for (i = 0; i < num_nodes; i++) {
520 #define V(val, invalid) (val == invalid) ? \
521 LIBXL_NUMAINFO_INVALID_ENTRY : val
522 ret[i].size = V(meminfo[i].memsize, XEN_INVALID_MEM_SZ);
523 ret[i].free = V(meminfo[i].memfree, XEN_INVALID_MEM_SZ);
524 ret[i].num_dists = num_nodes;
525 for (j = 0; j < ret[i].num_dists; j++) {
526 unsigned idx = i * num_nodes + j;
527 ret[i].dists[j] = V(distance[idx], XEN_INVALID_NODE_DIST);
528 }
529 #undef V
530 }
531
532 out:
533 GC_FREE;
534 return ret;
535 }
536
libxl__xc_version_wrap(libxl__gc * gc,libxl_version_info * info,xen_build_id_t * build)537 static int libxl__xc_version_wrap(libxl__gc *gc, libxl_version_info *info,
538 xen_build_id_t *build)
539 {
540 int r;
541
542 r = xc_version(CTX->xch, XENVER_build_id, build);
543 switch (r) {
544 case -EPERM:
545 case -ENODATA:
546 case 0:
547 info->build_id = libxl__strdup(NOGC, "");
548 break;
549
550 case -ENOBUFS:
551 break;
552
553 default:
554 if (r > 0) {
555 unsigned int i;
556
557 info->build_id = libxl__zalloc(NOGC, (r * 2) + 1);
558
559 for (i = 0; i < r ; i++)
560 snprintf(&info->build_id[i * 2], 3, "%02hhx", build->buf[i]);
561
562 r = 0;
563 }
564 break;
565 }
566 return r;
567 }
568
libxl_get_version_info(libxl_ctx * ctx)569 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx)
570 {
571 GC_INIT(ctx);
572 union {
573 xen_extraversion_t xen_extra;
574 xen_compile_info_t xen_cc;
575 xen_changeset_info_t xen_chgset;
576 xen_capabilities_info_t xen_caps;
577 xen_platform_parameters_t p_parms;
578 xen_commandline_t xen_commandline;
579 xen_build_id_t build_id;
580 } u;
581 long xen_version;
582 int r;
583 libxl_version_info *info = &ctx->version_info;
584
585 if (info->xen_version_extra != NULL)
586 goto out;
587
588 xen_version = xc_version(ctx->xch, XENVER_version, NULL);
589 info->xen_version_major = xen_version >> 16;
590 info->xen_version_minor = xen_version & 0xFF;
591
592 xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra);
593 info->xen_version_extra = libxl__strdup(NOGC, u.xen_extra);
594
595 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
596 info->compiler = libxl__strdup(NOGC, u.xen_cc.compiler);
597 info->compile_by = libxl__strdup(NOGC, u.xen_cc.compile_by);
598 info->compile_domain = libxl__strdup(NOGC, u.xen_cc.compile_domain);
599 info->compile_date = libxl__strdup(NOGC, u.xen_cc.compile_date);
600
601 xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps);
602 info->capabilities = libxl__strdup(NOGC, u.xen_caps);
603
604 xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset);
605 info->changeset = libxl__strdup(NOGC, u.xen_chgset);
606
607 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
608 info->virt_start = u.p_parms.virt_start;
609
610 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
611
612 xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline);
613 info->commandline = libxl__strdup(NOGC, u.xen_commandline);
614
615 u.build_id.len = sizeof(u) - sizeof(u.build_id);
616 r = libxl__xc_version_wrap(gc, info, &u.build_id);
617 if (r == -ENOBUFS) {
618 xen_build_id_t *build_id;
619
620 build_id = libxl__zalloc(gc, info->pagesize);
621 build_id->len = info->pagesize - sizeof(*build_id);
622 r = libxl__xc_version_wrap(gc, info, build_id);
623 if (r) LOGEV(ERROR, r, "getting build_id");
624 }
625 out:
626 GC_FREE;
627 return info;
628 }
629
libxl_send_sysrq(libxl_ctx * ctx,uint32_t domid,char sysrq)630 int libxl_send_sysrq(libxl_ctx *ctx, uint32_t domid, char sysrq)
631 {
632 GC_INIT(ctx);
633 char *dompath = libxl__xs_get_dompath(gc, domid);
634
635 libxl__xs_printf(gc, XBT_NULL, GCSPRINTF("%s/control/sysrq", dompath),
636 "%c", sysrq);
637
638 GC_FREE;
639 return 0;
640 }
641
libxl_send_debug_keys(libxl_ctx * ctx,char * keys)642 int libxl_send_debug_keys(libxl_ctx *ctx, char *keys)
643 {
644 int ret;
645 GC_INIT(ctx);
646 ret = xc_send_debug_keys(ctx->xch, keys);
647 if ( ret < 0 ) {
648 LOGE(ERROR, "sending debug keys");
649 GC_FREE;
650 return ERROR_FAIL;
651 }
652 GC_FREE;
653 return 0;
654 }
655
libxl_set_parameters(libxl_ctx * ctx,char * params)656 int libxl_set_parameters(libxl_ctx *ctx, char *params)
657 {
658 int ret;
659 GC_INIT(ctx);
660
661 ret = xc_set_parameters(ctx->xch, params);
662 if (ret < 0) {
663 LOGEV(ERROR, ret, "setting parameters");
664 GC_FREE;
665 return ERROR_FAIL;
666 }
667 GC_FREE;
668 return 0;
669 }
670
fd_set_flags(libxl_ctx * ctx,int fd,int fcntlgetop,int fcntlsetop,const char * fl,int flagmask,int set_p)671 static int fd_set_flags(libxl_ctx *ctx, int fd,
672 int fcntlgetop, int fcntlsetop, const char *fl,
673 int flagmask, int set_p)
674 {
675 int flags, r;
676 GC_INIT(ctx);
677
678 flags = fcntl(fd, fcntlgetop);
679 if (flags == -1) {
680 LOGE(ERROR, "fcntl(,F_GET%s) failed", fl);
681 GC_FREE;
682 return ERROR_FAIL;
683 }
684
685 if (set_p)
686 flags |= flagmask;
687 else
688 flags &= ~flagmask;
689
690 r = fcntl(fd, fcntlsetop, flags);
691 if (r == -1) {
692 LOGE(ERROR, "fcntl(,F_SET%s) failed", fl);
693 GC_FREE;
694 return ERROR_FAIL;
695 }
696
697 GC_FREE;
698 return 0;
699 }
700
libxl_fd_set_cloexec(libxl_ctx * ctx,int fd,int cloexec)701 int libxl_fd_set_cloexec(libxl_ctx *ctx, int fd, int cloexec)
702 { return fd_set_flags(ctx,fd, F_GETFD,F_SETFD,"FD", FD_CLOEXEC, cloexec); }
703
libxl_fd_set_nonblock(libxl_ctx * ctx,int fd,int nonblock)704 int libxl_fd_set_nonblock(libxl_ctx *ctx, int fd, int nonblock)
705 { return fd_set_flags(ctx,fd, F_GETFL,F_SETFL,"FL", O_NONBLOCK, nonblock); }
706
libxl__fd_flags_modify_save(libxl__gc * gc,int fd,int mask,int val,int * r_oldflags)707 int libxl__fd_flags_modify_save(libxl__gc *gc, int fd,
708 int mask, int val, int *r_oldflags)
709 {
710 int rc, ret, fdfl;
711
712 fdfl = fcntl(fd, F_GETFL);
713 if (fdfl < 0) {
714 LOGE(ERROR, "failed to fcntl.F_GETFL for fd %d", fd);
715 rc = ERROR_FAIL;
716 goto out_err;
717 }
718
719 LOG(DEBUG, "fnctl F_GETFL flags for fd %d are 0x%x", fd, fdfl);
720
721 if (r_oldflags)
722 *r_oldflags = fdfl;
723
724 fdfl &= mask;
725 fdfl |= val;
726
727 LOG(DEBUG, "fnctl F_SETFL of fd %d to 0x%x", fd, fdfl);
728
729 ret = fcntl(fd, F_SETFL, fdfl);
730 if (ret < 0) {
731 LOGE(ERROR, "failed to fcntl.F_SETFL for fd %d", fd);
732 rc = ERROR_FAIL;
733 goto out_err;
734 }
735
736 rc = 0;
737
738 out_err:
739 return rc;
740 }
741
libxl__fd_flags_restore(libxl__gc * gc,int fd,int fdfl)742 int libxl__fd_flags_restore(libxl__gc *gc, int fd, int fdfl)
743 {
744 int ret, rc;
745
746 LOG(DEBUG, "fnctl F_SETFL of fd %d to 0x%x", fd, fdfl);
747
748 ret = fcntl(fd, F_SETFL, fdfl);
749 if (ret < 0) {
750 LOGE(ERROR, "failed to fcntl.F_SETFL for fd %d", fd);
751 rc = ERROR_FAIL;
752 goto out_err;
753 }
754
755 rc = 0;
756
757 out_err:
758 return rc;
759
760 }
761
libxl_hwcap_copy(libxl_ctx * ctx,libxl_hwcap * dst,const libxl_hwcap * src)762 void libxl_hwcap_copy(libxl_ctx *ctx,libxl_hwcap *dst, const libxl_hwcap *src)
763 {
764 int i;
765
766 for (i = 0; i < 8; i++)
767 (*dst)[i] = (*src)[i];
768 }
769
libxl_mac_copy(libxl_ctx * ctx,libxl_mac * dst,const libxl_mac * src)770 void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const libxl_mac *src)
771 {
772 int i;
773
774 for (i = 0; i < 6; i++)
775 (*dst)[i] = (*src)[i];
776 }
777
778 /*
779 * Local variables:
780 * mode: C
781 * c-basic-offset: 4
782 * indent-tabs-mode: nil
783 * End:
784 */
785