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