/* * Copyright (c) 2024 SUSE Software Solutions Germany GmbH * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; If not, see . */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include struct xenmanage_handle { xentoollog_logger *logger, *logger_tofree; unsigned int flags; xencall_handle *xcall; }; xenmanage_handle *xenmanage_open(xentoollog_logger *logger, unsigned int open_flags) { xenmanage_handle *hdl = calloc(1, sizeof(*hdl)); int saved_errno; if ( !hdl ) return NULL; if ( open_flags ) { errno = EINVAL; goto err; } hdl->flags = open_flags; hdl->logger = logger; hdl->logger_tofree = NULL; if ( !hdl->logger ) { hdl->logger = hdl->logger_tofree = (xentoollog_logger *) xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0); if ( !hdl->logger ) goto err; } hdl->xcall = xencall_open(hdl->logger, 0); if ( !hdl->xcall ) goto err; return hdl; err: saved_errno = errno; xenmanage_close(hdl); errno = saved_errno; return NULL; } int xenmanage_close(xenmanage_handle *hdl) { if ( !hdl ) return 0; xencall_close(hdl->xcall); xtl_logger_destroy(hdl->logger_tofree); free(hdl); return 0; } static int xenmanage_do_domctl_get_domain_state(xenmanage_handle *hdl, unsigned int domid_in, unsigned int *domid_out, unsigned int *state, unsigned int *caps, uint64_t *unique_id) { struct xen_domctl *buf; int saved_errno; int ret; buf = xencall_alloc_buffer(hdl->xcall, sizeof(*buf)); if ( !buf ) { errno = ENOMEM; return -1; } memset(buf, 0, sizeof(*buf)); buf->cmd = XEN_DOMCTL_get_domain_state; buf->domain = domid_in; ret = xencall1(hdl->xcall, __HYPERVISOR_domctl, (unsigned long)buf); saved_errno = errno; if ( !ret ) { struct xen_domctl_get_domain_state *st = &buf->u.get_domain_state; if ( domid_out ) *domid_out = buf->domain; if ( state ) { *state = 0; if ( st->state & XEN_DOMCTL_GETDOMSTATE_STATE_EXIST ) *state |= XENMANAGE_GETDOMSTATE_STATE_EXIST; if ( st->state & XEN_DOMCTL_GETDOMSTATE_STATE_SHUTDOWN ) *state |= XENMANAGE_GETDOMSTATE_STATE_SHUTDOWN; if ( st->state & XEN_DOMCTL_GETDOMSTATE_STATE_DYING ) *state |= XENMANAGE_GETDOMSTATE_STATE_DYING; if ( st->state & XEN_DOMCTL_GETDOMSTATE_STATE_DEAD ) *state |= XENMANAGE_GETDOMSTATE_STATE_DEAD; } if ( caps ) { *caps = 0; if ( st->caps & XEN_DOMCTL_GETDOMSTATE_CAP_CONTROL ) *caps |= XENMANAGE_GETDOMSTATE_CAP_CONTROL; if ( st->caps & XEN_DOMCTL_GETDOMSTATE_CAP_HARDWARE ) *caps |= XENMANAGE_GETDOMSTATE_CAP_HARDWARE; if ( st->caps & XEN_DOMCTL_GETDOMSTATE_CAP_XENSTORE ) *caps |= XENMANAGE_GETDOMSTATE_CAP_XENSTORE; } if ( unique_id ) *unique_id = st->unique_id; } xencall_free_buffer(hdl->xcall, buf); errno = saved_errno; return ret; } int xenmanage_get_domain_info(xenmanage_handle *hdl, unsigned int domid, unsigned int *state, unsigned int *caps, uint64_t *unique_id) { if ( !hdl || domid >= DOMID_FIRST_RESERVED ) { errno = EINVAL; return -1; } return xenmanage_do_domctl_get_domain_state(hdl, domid, NULL, state, caps, unique_id); } int xenmanage_poll_changed_domain(xenmanage_handle *hdl, unsigned int *domid, unsigned int *state, unsigned int *caps, uint64_t *unique_id) { if ( !hdl || !domid ) { errno = EINVAL; return -1; } return xenmanage_do_domctl_get_domain_state(hdl, DOMID_INVALID, domid, state, caps, unique_id); }