1 /*
2 * Copyright (c) 2024 SUSE Software Solutions Germany GmbH
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation;
7 * version 2.1 of the License.
8 *
9 * This library 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 GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #define _GNU_SOURCE
19
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <xentoollog.h>
25 #include <xenmanage.h>
26 #include <xencall.h>
27 #include <xentoolcore_internal.h>
28
29 #include <xen/xen.h>
30 #include <xen/domctl.h>
31
32 struct xenmanage_handle {
33 xentoollog_logger *logger, *logger_tofree;
34 unsigned int flags;
35 xencall_handle *xcall;
36 };
37
xenmanage_open(xentoollog_logger * logger,unsigned int open_flags)38 xenmanage_handle *xenmanage_open(xentoollog_logger *logger,
39 unsigned int open_flags)
40 {
41 xenmanage_handle *hdl = calloc(1, sizeof(*hdl));
42 int saved_errno;
43
44 if ( !hdl )
45 return NULL;
46
47 if ( open_flags )
48 {
49 errno = EINVAL;
50 goto err;
51 }
52
53 hdl->flags = open_flags;
54 hdl->logger = logger;
55 hdl->logger_tofree = NULL;
56
57 if ( !hdl->logger )
58 {
59 hdl->logger = hdl->logger_tofree =
60 (xentoollog_logger *)
61 xtl_createlogger_stdiostream(stderr, XTL_PROGRESS, 0);
62 if ( !hdl->logger )
63 goto err;
64 }
65
66 hdl->xcall = xencall_open(hdl->logger, 0);
67 if ( !hdl->xcall )
68 goto err;
69
70 return hdl;
71
72 err:
73 saved_errno = errno;
74 xenmanage_close(hdl);
75 errno = saved_errno;
76
77 return NULL;
78 }
79
xenmanage_close(xenmanage_handle * hdl)80 int xenmanage_close(xenmanage_handle *hdl)
81 {
82 if ( !hdl )
83 return 0;
84
85 xencall_close(hdl->xcall);
86 xtl_logger_destroy(hdl->logger_tofree);
87 free(hdl);
88 return 0;
89 }
90
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)91 static int xenmanage_do_domctl_get_domain_state(xenmanage_handle *hdl,
92 unsigned int domid_in,
93 unsigned int *domid_out,
94 unsigned int *state,
95 unsigned int *caps,
96 uint64_t *unique_id)
97 {
98 struct xen_domctl *buf;
99 int saved_errno;
100 int ret;
101
102 buf = xencall_alloc_buffer(hdl->xcall, sizeof(*buf));
103 if ( !buf )
104 {
105 errno = ENOMEM;
106 return -1;
107 }
108
109 memset(buf, 0, sizeof(*buf));
110
111 buf->cmd = XEN_DOMCTL_get_domain_state;
112 buf->domain = domid_in;
113
114 ret = xencall1(hdl->xcall, __HYPERVISOR_domctl, (unsigned long)buf);
115 saved_errno = errno;
116 if ( !ret )
117 {
118 struct xen_domctl_get_domain_state *st = &buf->u.get_domain_state;
119
120 if ( domid_out )
121 *domid_out = buf->domain;
122 if ( state )
123 {
124 *state = 0;
125 if ( st->state & XEN_DOMCTL_GETDOMSTATE_STATE_EXIST )
126 *state |= XENMANAGE_GETDOMSTATE_STATE_EXIST;
127 if ( st->state & XEN_DOMCTL_GETDOMSTATE_STATE_SHUTDOWN )
128 *state |= XENMANAGE_GETDOMSTATE_STATE_SHUTDOWN;
129 if ( st->state & XEN_DOMCTL_GETDOMSTATE_STATE_DYING )
130 *state |= XENMANAGE_GETDOMSTATE_STATE_DYING;
131 if ( st->state & XEN_DOMCTL_GETDOMSTATE_STATE_DEAD )
132 *state |= XENMANAGE_GETDOMSTATE_STATE_DEAD;
133 }
134 if ( caps )
135 {
136 *caps = 0;
137 if ( st->caps & XEN_DOMCTL_GETDOMSTATE_CAP_CONTROL )
138 *caps |= XENMANAGE_GETDOMSTATE_CAP_CONTROL;
139 if ( st->caps & XEN_DOMCTL_GETDOMSTATE_CAP_HARDWARE )
140 *caps |= XENMANAGE_GETDOMSTATE_CAP_HARDWARE;
141 if ( st->caps & XEN_DOMCTL_GETDOMSTATE_CAP_XENSTORE )
142 *caps |= XENMANAGE_GETDOMSTATE_CAP_XENSTORE;
143 }
144 if ( unique_id )
145 *unique_id = st->unique_id;
146 }
147
148 xencall_free_buffer(hdl->xcall, buf);
149
150 errno = saved_errno;
151
152 return ret;
153 }
154
xenmanage_get_domain_info(xenmanage_handle * hdl,unsigned int domid,unsigned int * state,unsigned int * caps,uint64_t * unique_id)155 int xenmanage_get_domain_info(xenmanage_handle *hdl, unsigned int domid,
156 unsigned int *state, unsigned int *caps,
157 uint64_t *unique_id)
158 {
159 if ( !hdl || domid >= DOMID_FIRST_RESERVED )
160 {
161 errno = EINVAL;
162 return -1;
163 }
164
165 return xenmanage_do_domctl_get_domain_state(hdl, domid, NULL, state, caps,
166 unique_id);
167 }
168
xenmanage_poll_changed_domain(xenmanage_handle * hdl,unsigned int * domid,unsigned int * state,unsigned int * caps,uint64_t * unique_id)169 int xenmanage_poll_changed_domain(xenmanage_handle *hdl, unsigned int *domid,
170 unsigned int *state, unsigned int *caps,
171 uint64_t *unique_id)
172 {
173 if ( !hdl || !domid )
174 {
175 errno = EINVAL;
176 return -1;
177 }
178
179 return xenmanage_do_domctl_get_domain_state(hdl, DOMID_INVALID, domid,
180 state, caps, unique_id);
181 }
182