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 XEN_TAILQ_INIT(&ctx->occurred);
45
46 ctx->osevent_hooks = 0;
47
48 ctx->poller_app = 0;
49 XEN_LIST_INIT(&ctx->pollers_event);
50 XEN_LIST_INIT(&ctx->pollers_idle);
51 XEN_LIST_INIT(&ctx->pollers_active);
52
53 XEN_LIST_INIT(&ctx->efds);
54 XEN_TAILQ_INIT(&ctx->etimes);
55
56 ctx->watch_slots = 0;
57 XEN_SLIST_INIT(&ctx->watch_freeslots);
58 libxl__ev_fd_init(&ctx->watch_efd);
59
60 ctx->xce = 0;
61 XEN_LIST_INIT(&ctx->evtchns_waiting);
62 libxl__ev_fd_init(&ctx->evtchn_efd);
63
64 XEN_LIST_INIT(&ctx->aos_inprogress);
65
66 XEN_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_open(0);
107 if (!ctx->xsh) {
108 LOGEV(ERROR, errno, "cannot connect to xenstore");
109 rc = ERROR_FAIL; goto out;
110 }
111
112 *pctx = ctx;
113 return 0;
114
115 out:
116 if (gc) libxl__free_all(gc);
117 libxl_ctx_free(ctx);
118 *pctx = NULL;
119 return rc;
120 }
121
free_disable_deaths(libxl__gc * gc,struct libxl__evgen_domain_death_list * l)122 static void free_disable_deaths(libxl__gc *gc,
123 struct libxl__evgen_domain_death_list *l) {
124 libxl_evgen_domain_death *death;
125 while ((death = XEN_TAILQ_FIRST(l)))
126 libxl__evdisable_domain_death(gc, death);
127 }
128
discard_events(struct libxl__event_list * l)129 static void discard_events(struct libxl__event_list *l) {
130 /* doesn't bother unlinking from the list, so l is corrupt on return */
131 libxl_event *ev, *next;
132 XEN_TAILQ_FOREACH_SAFE(ev, l, link, next)
133 libxl_event_free(0, ev);
134 }
135
libxl_ctx_free(libxl_ctx * ctx)136 int libxl_ctx_free(libxl_ctx *ctx)
137 {
138 if (!ctx) return 0;
139
140 int i;
141 GC_INIT(ctx);
142
143 CTX_LOCK;
144 assert(!ctx->osevent_in_hook);
145 CTX->osevent_in_hook += 1000; /* make violations easier to debug */
146
147 /* Deregister all libxl__ev_KINDs: */
148
149 free_disable_deaths(gc, &CTX->death_list);
150 free_disable_deaths(gc, &CTX->death_reported);
151
152 libxl_evgen_disk_eject *eject;
153 while ((eject = XEN_LIST_FIRST(&CTX->disk_eject_evgens)))
154 libxl__evdisable_disk_eject(gc, eject);
155
156 libxl_childproc_setmode(CTX,0,0);
157 for (i = 0; i < ctx->watch_nslots; i++)
158 assert(!libxl__watch_slot_contents(gc, i));
159 assert(!libxl__ev_fd_isregistered(&ctx->watch_efd));
160 assert(!libxl__ev_fd_isregistered(&ctx->evtchn_efd));
161 assert(!libxl__ev_fd_isregistered(&ctx->sigchld_selfpipe_efd));
162
163 /* Now there should be no more events requested from the application: */
164
165 assert(XEN_LIST_EMPTY(&ctx->efds));
166 assert(XEN_TAILQ_EMPTY(&ctx->etimes));
167 assert(XEN_LIST_EMPTY(&ctx->evtchns_waiting));
168 assert(XEN_LIST_EMPTY(&ctx->aos_inprogress));
169
170 if (ctx->xch) xc_interface_close(ctx->xch);
171 libxl_version_info_dispose(&ctx->version_info);
172 if (ctx->xsh) xs_close(ctx->xsh);
173 if (ctx->xce) xenevtchn_close(ctx->xce);
174
175 libxl__poller_put(ctx, ctx->poller_app);
176 ctx->poller_app = NULL;
177 assert(XEN_LIST_EMPTY(&ctx->pollers_event));
178 assert(XEN_LIST_EMPTY(&ctx->pollers_active));
179 libxl__poller *poller, *poller_tmp;
180 XEN_LIST_FOREACH_SAFE(poller, &ctx->pollers_idle, entry, poller_tmp) {
181 libxl__poller_dispose(poller);
182 free(poller);
183 }
184
185 free(ctx->watch_slots);
186
187 discard_events(&ctx->occurred);
188
189 /* If we have outstanding children, then the application inherits
190 * them; we wish the application good luck with understanding
191 * this if and when it reaps them. */
192 libxl__sigchld_notneeded(gc);
193 libxl__pipe_close(ctx->sigchld_selfpipe);
194
195 CTX_UNLOCK;
196 pthread_mutex_destroy(&ctx->lock);
197
198 GC_FREE;
199 free(ctx);
200 return 0;
201 }
202
libxl_string_list_dispose(libxl_string_list * psl)203 void libxl_string_list_dispose(libxl_string_list *psl)
204 {
205 int i;
206 libxl_string_list sl = *psl;
207
208 if (!sl)
209 return;
210
211 for (i = 0; sl[i] != NULL; i++) {
212 free(sl[i]);
213 sl[i] = NULL;
214 }
215 free(sl);
216 *psl = NULL;
217 }
218
libxl_string_list_copy(libxl_ctx * ctx,libxl_string_list * dst,const libxl_string_list * src)219 void libxl_string_list_copy(libxl_ctx *ctx,
220 libxl_string_list *dst,
221 const libxl_string_list *src)
222 {
223 GC_INIT(ctx);
224 int i, len;
225
226 if (!*src) {
227 *dst = NULL;
228 goto out;
229 }
230
231 len = libxl_string_list_length(src);
232 /* one extra slot for sentinel */
233 *dst = libxl__calloc(NOGC, len + 1, sizeof(char *));
234
235 for (i = 0; i < len; i++)
236 (*dst)[i] = libxl__strdup(NOGC, (*src)[i]);
237
238 out:
239 GC_FREE;
240 }
241
libxl_string_list_length(const libxl_string_list * psl)242 int libxl_string_list_length(const libxl_string_list *psl)
243 {
244 int i = 0;
245
246 if (*psl)
247 while ((*psl)[i])
248 i++;
249
250 return i;
251 }
252
libxl_key_value_list_length(const libxl_key_value_list * pkvl)253 int libxl_key_value_list_length(const libxl_key_value_list *pkvl)
254 {
255 int i = 0;
256 libxl_key_value_list kvl = *pkvl;
257
258 if (kvl) {
259 while (kvl[2 * i]) /* Only checks keys */
260 i++;
261 }
262
263 return i;
264 }
265
libxl_key_value_list_dispose(libxl_key_value_list * pkvl)266 void libxl_key_value_list_dispose(libxl_key_value_list *pkvl)
267 {
268 int i;
269 libxl_key_value_list kvl = *pkvl;
270
271 if (!kvl)
272 return;
273
274 for (i = 0; kvl[i] != NULL; i += 2) {
275 free(kvl[i]);
276 kvl[i] = NULL;
277 if (kvl[i + 1]) {
278 free(kvl[i + 1]);
279 kvl[i+1] = NULL;
280 }
281 }
282 free(kvl);
283 *pkvl = NULL;
284 }
285
libxl_key_value_list_copy(libxl_ctx * ctx,libxl_key_value_list * dst,const libxl_key_value_list * src)286 void libxl_key_value_list_copy(libxl_ctx *ctx,
287 libxl_key_value_list *dst,
288 const libxl_key_value_list *src)
289 {
290 GC_INIT(ctx);
291 int i, len;
292
293 if (*src == NULL) {
294 *dst = NULL;
295 goto out;
296 }
297
298 len = libxl_key_value_list_length(src);
299 /* one extra slot for sentinel */
300 *dst = libxl__calloc(NOGC, len * 2 + 1, sizeof(char *));
301
302 for (i = 0; i < len * 2; i += 2) {
303 (*dst)[i] = libxl__strdup(NOGC, (*src)[i]);
304 if ((*src)[i+1])
305 (*dst)[i+1] = libxl__strdup(NOGC, (*src)[i+1]);
306 else
307 (*dst)[i+1] = NULL;
308 }
309
310 out:
311 GC_FREE;
312 }
313
libxl_defbool_set(libxl_defbool * db,bool b)314 void libxl_defbool_set(libxl_defbool *db, bool b)
315 {
316 db->val = b ? LIBXL__DEFBOOL_TRUE : LIBXL__DEFBOOL_FALSE;
317 }
318
libxl_defbool_unset(libxl_defbool * db)319 void libxl_defbool_unset(libxl_defbool *db)
320 {
321 db->val = LIBXL__DEFBOOL_DEFAULT;
322 }
323
libxl_defbool_is_default(libxl_defbool db)324 bool libxl_defbool_is_default(libxl_defbool db)
325 {
326 return !db.val;
327 }
328
libxl_defbool_setdefault(libxl_defbool * db,bool b)329 void libxl_defbool_setdefault(libxl_defbool *db, bool b)
330 {
331 if (libxl_defbool_is_default(*db))
332 libxl_defbool_set(db, b);
333 }
334
libxl_defbool_val(libxl_defbool db)335 bool libxl_defbool_val(libxl_defbool db)
336 {
337 assert(!libxl_defbool_is_default(db));
338 return db.val > 0;
339 }
340
libxl_defbool_to_string(libxl_defbool b)341 const char *libxl_defbool_to_string(libxl_defbool b)
342 {
343 if (b.val < 0)
344 return LIBXL__DEFBOOL_STR_FALSE;
345 else if (b.val > 0)
346 return LIBXL__DEFBOOL_STR_TRUE;
347 else
348 return LIBXL__DEFBOOL_STR_DEFAULT;
349 }
350
351 /******************************************************************************/
libxl_get_physinfo(libxl_ctx * ctx,libxl_physinfo * physinfo)352 int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
353 {
354 xc_physinfo_t xcphysinfo;
355 int rc;
356 long l;
357 GC_INIT(ctx);
358
359 rc = xc_physinfo(ctx->xch, &xcphysinfo);
360 if (rc != 0) {
361 LOGE(ERROR, "getting physinfo");
362 GC_FREE;
363 return ERROR_FAIL;
364 }
365 physinfo->threads_per_core = xcphysinfo.threads_per_core;
366 physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
367 physinfo->max_cpu_id = xcphysinfo.max_cpu_id;
368 physinfo->nr_cpus = xcphysinfo.nr_cpus;
369 physinfo->cpu_khz = xcphysinfo.cpu_khz;
370 physinfo->total_pages = xcphysinfo.total_pages;
371 physinfo->free_pages = xcphysinfo.free_pages;
372 physinfo->scrub_pages = xcphysinfo.scrub_pages;
373 physinfo->outstanding_pages = xcphysinfo.outstanding_pages;
374 physinfo->max_possible_mfn = xcphysinfo.max_mfn;
375 l = xc_sharing_freed_pages(ctx->xch);
376 if (l < 0 && errno == ENOSYS) {
377 l = 0;
378 } else if (l < 0) {
379 LOGEV(ERROR, l, "getting sharing freed pages");
380 GC_FREE;
381 return ERROR_FAIL;
382 }
383 physinfo->sharing_freed_pages = l;
384 l = xc_sharing_used_frames(ctx->xch);
385 if (l < 0 && errno == ENOSYS) {
386 l = 0;
387 } else if (l < 0) {
388 LOGEV(ERROR, l, "getting sharing used frames");
389 GC_FREE;
390 return ERROR_FAIL;
391 }
392 physinfo->sharing_used_frames = l;
393 physinfo->nr_nodes = xcphysinfo.nr_nodes;
394 memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap));
395
396 physinfo->cap_hvm = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_hvm);
397 physinfo->cap_pv = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_pv);
398 physinfo->cap_hvm_directio =
399 !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_directio);
400 physinfo->cap_hap = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_hap);
401 physinfo->cap_shadow =
402 !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_shadow);
403 physinfo->cap_iommu_hap_pt_share =
404 !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_iommu_hap_pt_share);
405 physinfo->cap_vmtrace =
406 !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_vmtrace);
407 physinfo->cap_vpmu = !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_vpmu);
408 physinfo->cap_gnttab_v1 =
409 !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_gnttab_v1);
410 physinfo->cap_gnttab_v2 =
411 !!(xcphysinfo.capabilities & XEN_SYSCTL_PHYSCAP_gnttab_v2);
412 physinfo->arch_capabilities = xcphysinfo.arch_capabilities;
413
414 GC_FREE;
415 return 0;
416 }
417
libxl_get_cpu_topology(libxl_ctx * ctx,int * nb_cpu_out)418 libxl_cputopology *libxl_get_cpu_topology(libxl_ctx *ctx, int *nb_cpu_out)
419 {
420 GC_INIT(ctx);
421 xc_cputopo_t *cputopo;
422 libxl_cputopology *ret = NULL;
423 int i;
424 unsigned num_cpus = 0;
425
426 /* Setting buffer to NULL makes the call return number of CPUs */
427 if (xc_cputopoinfo(ctx->xch, &num_cpus, NULL))
428 {
429 LOGE(ERROR, "Unable to determine number of CPUS");
430 goto out;
431 }
432
433 cputopo = libxl__zalloc(gc, sizeof(*cputopo) * num_cpus);
434
435 if (xc_cputopoinfo(ctx->xch, &num_cpus, cputopo)) {
436 LOGE(ERROR, "CPU topology info hypercall failed");
437 goto out;
438 }
439
440 ret = libxl__zalloc(NOGC, sizeof(libxl_cputopology) * num_cpus);
441
442 for (i = 0; i < num_cpus; i++) {
443 #define V(map, i, invalid) ( cputopo[i].map == invalid) ? \
444 LIBXL_CPUTOPOLOGY_INVALID_ENTRY : cputopo[i].map
445 ret[i].core = V(core, i, XEN_INVALID_CORE_ID);
446 ret[i].socket = V(socket, i, XEN_INVALID_SOCKET_ID);
447 ret[i].node = V(node, i, XEN_INVALID_NODE_ID);
448 #undef V
449 }
450
451 *nb_cpu_out = num_cpus;
452
453 out:
454 GC_FREE;
455 return ret;
456 }
457
libxl_get_pci_topology(libxl_ctx * ctx,int * num_devs)458 libxl_pcitopology *libxl_get_pci_topology(libxl_ctx *ctx, int *num_devs)
459 {
460 GC_INIT(ctx);
461 physdev_pci_device_t *devs;
462 uint32_t *nodes;
463 libxl_pcitopology *ret = NULL;
464 int i, rc;
465
466 *num_devs = libxl__pci_numdevs(gc);
467 if (*num_devs < 0) {
468 LOG(ERROR, "Unable to determine number of PCI devices, rc %d",
469 *num_devs);
470 goto out;
471 }
472
473 devs = libxl__zalloc(gc, sizeof(*devs) * *num_devs);
474 nodes = libxl__zalloc(gc, sizeof(*nodes) * *num_devs);
475
476 rc = libxl__pci_topology_init(gc, devs, *num_devs);
477 if (rc) {
478 LOG(ERROR, "Cannot initialize PCI hypercall structure, rc %d", rc);
479 goto out;
480 }
481
482 if (xc_pcitopoinfo(ctx->xch, *num_devs, devs, nodes) != 0) {
483 LOGE(ERROR, "PCI topology info hypercall failed");
484 goto out;
485 }
486
487 ret = libxl__zalloc(NOGC, sizeof(libxl_pcitopology) * *num_devs);
488
489 for (i = 0; i < *num_devs; i++) {
490 ret[i].seg = devs[i].seg;
491 ret[i].bus = devs[i].bus;
492 ret[i].devfn = devs[i].devfn;
493 ret[i].node = ((nodes[i] == XEN_INVALID_NODE_ID) ||
494 (nodes[i] == XEN_INVALID_DEV)) ?
495 LIBXL_PCITOPOLOGY_INVALID_ENTRY : nodes[i];
496 }
497
498 out:
499 GC_FREE;
500 return ret;
501 }
502
libxl_get_numainfo(libxl_ctx * ctx,int * nr)503 libxl_numainfo *libxl_get_numainfo(libxl_ctx *ctx, int *nr)
504 {
505 GC_INIT(ctx);
506 xc_meminfo_t *meminfo;
507 uint32_t *distance;
508 libxl_numainfo *ret = NULL;
509 int i, j;
510 unsigned num_nodes = 0;
511
512 if (xc_numainfo(ctx->xch, &num_nodes, NULL, NULL)) {
513 LOGE(ERROR, "Unable to determine number of nodes");
514 goto out;
515 }
516
517 meminfo = libxl__zalloc(gc, sizeof(*meminfo) * num_nodes);
518 distance = libxl__zalloc(gc, sizeof(*distance) * num_nodes * num_nodes);
519
520 if (xc_numainfo(ctx->xch, &num_nodes, meminfo, distance)) {
521 LOGE(ERROR, "getting numainfo");
522 goto out;
523 }
524
525 *nr = num_nodes;
526
527 ret = libxl__zalloc(NOGC, sizeof(libxl_numainfo) * num_nodes);
528 for (i = 0; i < num_nodes; i++)
529 ret[i].dists = libxl__calloc(NOGC, num_nodes, sizeof(*distance));
530
531 for (i = 0; i < num_nodes; i++) {
532 #define V(val, invalid) (val == invalid) ? \
533 LIBXL_NUMAINFO_INVALID_ENTRY : val
534 ret[i].size = V(meminfo[i].memsize, XEN_INVALID_MEM_SZ);
535 ret[i].free = V(meminfo[i].memfree, XEN_INVALID_MEM_SZ);
536 ret[i].num_dists = num_nodes;
537 for (j = 0; j < ret[i].num_dists; j++) {
538 unsigned idx = i * num_nodes + j;
539 ret[i].dists[j] = V(distance[idx], XEN_INVALID_NODE_DIST);
540 }
541 #undef V
542 }
543
544 out:
545 GC_FREE;
546 return ret;
547 }
548
libxl_get_version_info(libxl_ctx * ctx)549 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx)
550 {
551 GC_INIT(ctx);
552 union {
553 xen_compile_info_t xen_cc;
554 xen_platform_parameters_t p_parms;
555 xen_build_id_t build_id;
556 } u;
557 long xen_version;
558 libxl_version_info *info = &ctx->version_info;
559
560 if (info->xen_version_extra != NULL)
561 goto out;
562
563 xen_version = xc_version(ctx->xch, XENVER_version, NULL);
564 info->xen_version_major = xen_version >> 16;
565 info->xen_version_minor = xen_version & 0xFF;
566
567 info->xen_version_extra = xc_xenver_extraversion(ctx->xch);
568
569 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
570 info->compiler = libxl__strdup(NOGC, u.xen_cc.compiler);
571 info->compile_by = libxl__strdup(NOGC, u.xen_cc.compile_by);
572 info->compile_domain = libxl__strdup(NOGC, u.xen_cc.compile_domain);
573 info->compile_date = libxl__strdup(NOGC, u.xen_cc.compile_date);
574
575 info->capabilities = xc_xenver_capabilities(ctx->xch);
576 info->changeset = xc_xenver_changeset(ctx->xch);
577
578 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
579 info->virt_start = u.p_parms.virt_start;
580
581 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
582
583 info->commandline = xc_xenver_commandline(ctx->xch);
584 info->build_id = xc_xenver_buildid(ctx->xch);
585
586 out:
587 GC_FREE;
588 return info;
589 }
590
libxl_send_sysrq(libxl_ctx * ctx,uint32_t domid,char sysrq)591 int libxl_send_sysrq(libxl_ctx *ctx, uint32_t domid, char sysrq)
592 {
593 GC_INIT(ctx);
594 char *dompath = libxl__xs_get_dompath(gc, domid);
595
596 libxl__xs_printf(gc, XBT_NULL, GCSPRINTF("%s/control/sysrq", dompath),
597 "%c", sysrq);
598
599 GC_FREE;
600 return 0;
601 }
602
libxl_send_debug_keys(libxl_ctx * ctx,char * keys)603 int libxl_send_debug_keys(libxl_ctx *ctx, char *keys)
604 {
605 int ret;
606 GC_INIT(ctx);
607 ret = xc_send_debug_keys(ctx->xch, keys);
608 if ( ret < 0 ) {
609 LOGE(ERROR, "sending debug keys");
610 GC_FREE;
611 return ERROR_FAIL;
612 }
613 GC_FREE;
614 return 0;
615 }
616
libxl_set_parameters(libxl_ctx * ctx,char * params)617 int libxl_set_parameters(libxl_ctx *ctx, char *params)
618 {
619 int ret;
620 GC_INIT(ctx);
621 char *par, *val, *end, *path;
622 xenhypfs_handle *hypfs;
623
624 hypfs = xenhypfs_open(ctx->lg, 0);
625 if (!hypfs) {
626 LOGE(ERROR, "opening Xen hypfs");
627 ret = ERROR_FAIL;
628 goto out;
629 }
630
631 while (isblank(*params))
632 params++;
633
634 for (par = params; *par; par = end) {
635 end = strchr(par, ' ');
636 if (!end)
637 end = par + strlen(par);
638
639 val = strchr(par, '=');
640 if (val > end)
641 val = NULL;
642 if (!val && !strncmp(par, "no", 2)) {
643 path = libxl__sprintf(gc, "/params/%s", par + 2);
644 path[end - par - 2 + 8] = 0;
645 val = "no";
646 par += 2;
647 } else {
648 path = libxl__sprintf(gc, "/params/%s", par);
649 path[val - par + 8] = 0;
650 val = libxl__strndup(gc, val + 1, end - val - 1);
651 }
652
653 LOG(DEBUG, "setting node \"%s\" to value \"%s\"", path, val);
654 ret = xenhypfs_write(hypfs, path, val);
655 if (ret < 0) {
656 LOGE(ERROR, "setting parameters");
657 ret = ERROR_FAIL;
658 goto out;
659 }
660
661 while (isblank(*end))
662 end++;
663 }
664
665 ret = 0;
666
667 out:
668 xenhypfs_close(hypfs);
669 GC_FREE;
670 return ret;
671 }
672
fd_set_flags(libxl_ctx * ctx,int fd,int fcntlgetop,int fcntlsetop,const char * fl,int flagmask,int set_p)673 static int fd_set_flags(libxl_ctx *ctx, int fd,
674 int fcntlgetop, int fcntlsetop, const char *fl,
675 int flagmask, int set_p)
676 {
677 int flags, r;
678 GC_INIT(ctx);
679
680 flags = fcntl(fd, fcntlgetop);
681 if (flags == -1) {
682 LOGE(ERROR, "fcntl(,F_GET%s) failed", fl);
683 GC_FREE;
684 return ERROR_FAIL;
685 }
686
687 if (set_p)
688 flags |= flagmask;
689 else
690 flags &= ~flagmask;
691
692 r = fcntl(fd, fcntlsetop, flags);
693 if (r == -1) {
694 LOGE(ERROR, "fcntl(,F_SET%s) failed", fl);
695 GC_FREE;
696 return ERROR_FAIL;
697 }
698
699 GC_FREE;
700 return 0;
701 }
702
libxl_fd_set_cloexec(libxl_ctx * ctx,int fd,int cloexec)703 int libxl_fd_set_cloexec(libxl_ctx *ctx, int fd, int cloexec)
704 { return fd_set_flags(ctx,fd, F_GETFD,F_SETFD,"FD", FD_CLOEXEC, cloexec); }
705
libxl_fd_set_nonblock(libxl_ctx * ctx,int fd,int nonblock)706 int libxl_fd_set_nonblock(libxl_ctx *ctx, int fd, int nonblock)
707 { return fd_set_flags(ctx,fd, F_GETFL,F_SETFL,"FL", O_NONBLOCK, nonblock); }
708
libxl__fd_flags_modify_save(libxl__gc * gc,int fd,int mask,int val,int * r_oldflags)709 int libxl__fd_flags_modify_save(libxl__gc *gc, int fd,
710 int mask, int val, int *r_oldflags)
711 {
712 int rc, ret, fdfl;
713
714 fdfl = fcntl(fd, F_GETFL);
715 if (fdfl < 0) {
716 LOGE(ERROR, "failed to fcntl.F_GETFL for fd %d", fd);
717 rc = ERROR_FAIL;
718 goto out_err;
719 }
720
721 LOG(DEBUG, "fnctl F_GETFL flags for fd %d are 0x%x", fd, fdfl);
722
723 if (r_oldflags)
724 *r_oldflags = fdfl;
725
726 fdfl &= mask;
727 fdfl |= val;
728
729 LOG(DEBUG, "fnctl F_SETFL of fd %d to 0x%x", fd, fdfl);
730
731 ret = fcntl(fd, F_SETFL, fdfl);
732 if (ret < 0) {
733 LOGE(ERROR, "failed to fcntl.F_SETFL for fd %d", fd);
734 rc = ERROR_FAIL;
735 goto out_err;
736 }
737
738 rc = 0;
739
740 out_err:
741 return rc;
742 }
743
libxl__fd_flags_restore(libxl__gc * gc,int fd,int fdfl)744 int libxl__fd_flags_restore(libxl__gc *gc, int fd, int fdfl)
745 {
746 int ret, rc;
747
748 LOG(DEBUG, "fnctl F_SETFL of fd %d to 0x%x", fd, fdfl);
749
750 ret = fcntl(fd, F_SETFL, fdfl);
751 if (ret < 0) {
752 LOGE(ERROR, "failed to fcntl.F_SETFL for fd %d", fd);
753 rc = ERROR_FAIL;
754 goto out_err;
755 }
756
757 rc = 0;
758
759 out_err:
760 return rc;
761
762 }
763
libxl_hwcap_copy(libxl_ctx * ctx,libxl_hwcap * dst,const libxl_hwcap * src)764 void libxl_hwcap_copy(libxl_ctx *ctx,libxl_hwcap *dst, const libxl_hwcap *src)
765 {
766 int i;
767
768 for (i = 0; i < 8; i++)
769 (*dst)[i] = (*src)[i];
770 }
771
libxl_mac_copy(libxl_ctx * ctx,libxl_mac * dst,const libxl_mac * src)772 void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const libxl_mac *src)
773 {
774 int i;
775
776 for (i = 0; i < 6; i++)
777 (*dst)[i] = (*src)[i];
778 }
779
780 /*
781 * Local variables:
782 * mode: C
783 * c-basic-offset: 4
784 * indent-tabs-mode: nil
785 * End:
786 */
787