]> git.proxmox.com Git - mirror_qemu.git/blame - hw/xen/xen_pvdev.c
hw/sparc64/sun4u: Keep reference to ISA input IRQs in EbusState
[mirror_qemu.git] / hw / xen / xen_pvdev.c
CommitLineData
f0021dba
EC
1/*
2 * Xen para-virtualization device
3 *
4 * (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
61f3c91a 9 * version 2.1 of the License, or (at your option) any later version.
f0021dba
EC
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>
18 */
19
20#include "qemu/osdep.h"
b5863634 21#include "qemu/log.h"
db725815 22#include "qemu/main-loop.h"
3a6c9172 23#include "hw/qdev-core.h"
2d0ed5e6 24#include "hw/xen/xen-legacy-backend.h"
f0021dba
EC
25#include "hw/xen/xen_pvdev.h"
26
148512e0 27/* private */
f0021dba 28static int debug;
ecf79818
EC
29
30struct xs_dirs {
31 char *xs_dir;
32 QTAILQ_ENTRY(xs_dirs) list;
33};
34
b58deb34 35static QTAILQ_HEAD(, xs_dirs) xs_cleanup =
ecf79818
EC
36 QTAILQ_HEAD_INITIALIZER(xs_cleanup);
37
2d0ed5e6 38static QTAILQ_HEAD(, XenLegacyDevice) xendevs =
148512e0
EC
39 QTAILQ_HEAD_INITIALIZER(xendevs);
40
f0021dba
EC
41/* ------------------------------------------------------------- */
42
ecf79818
EC
43static void xenstore_cleanup_dir(char *dir)
44{
45 struct xs_dirs *d;
46
47 d = g_malloc(sizeof(*d));
48 d->xs_dir = dir;
49 QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
50}
51
52void xen_config_cleanup(void)
53{
54 struct xs_dirs *d;
55
56 QTAILQ_FOREACH(d, &xs_cleanup, list) {
57 xs_rm(xenstore, 0, d->xs_dir);
58 }
59}
60
61int xenstore_mkdir(char *path, int p)
62{
63 struct xs_permissions perms[2] = {
64 {
65 .id = 0, /* set owner: dom0 */
66 }, {
67 .id = xen_domid,
68 .perms = p,
69 }
70 };
71
72 if (!xs_mkdir(xenstore, 0, path)) {
96c77dba 73 xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
ecf79818
EC
74 return -1;
75 }
76 xenstore_cleanup_dir(g_strdup(path));
77
78 if (!xs_set_permissions(xenstore, 0, path, perms, 2)) {
96c77dba 79 xen_pv_printf(NULL, 0, "xs_set_permissions %s: failed\n", path);
ecf79818
EC
80 return -1;
81 }
82 return 0;
83}
84
f0021dba
EC
85int xenstore_write_str(const char *base, const char *node, const char *val)
86{
87 char abspath[XEN_BUFSIZE];
88
89 snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
90 if (!xs_write(xenstore, 0, abspath, val, strlen(val))) {
91 return -1;
92 }
93 return 0;
94}
95
96char *xenstore_read_str(const char *base, const char *node)
97{
98 char abspath[XEN_BUFSIZE];
99 unsigned int len;
100 char *str, *ret = NULL;
101
102 snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
103 str = xs_read(xenstore, 0, abspath, &len);
104 if (str != NULL) {
105 /* move to qemu-allocated memory to make sure
106 * callers can savely g_free() stuff. */
107 ret = g_strdup(str);
108 free(str);
109 }
110 return ret;
111}
112
113int xenstore_write_int(const char *base, const char *node, int ival)
114{
115 char val[12];
116
117 snprintf(val, sizeof(val), "%d", ival);
118 return xenstore_write_str(base, node, val);
119}
120
121int xenstore_write_int64(const char *base, const char *node, int64_t ival)
122{
123 char val[21];
124
125 snprintf(val, sizeof(val), "%"PRId64, ival);
126 return xenstore_write_str(base, node, val);
127}
128
129int xenstore_read_int(const char *base, const char *node, int *ival)
130{
131 char *val;
132 int rc = -1;
133
134 val = xenstore_read_str(base, node);
135 if (val && 1 == sscanf(val, "%d", ival)) {
136 rc = 0;
137 }
138 g_free(val);
139 return rc;
140}
141
142int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
143{
144 char *val;
145 int rc = -1;
146
147 val = xenstore_read_str(base, node);
148 if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
149 rc = 0;
150 }
151 g_free(val);
152 return rc;
153}
154
046db9be
EC
155void xenstore_update(void *unused)
156{
157 char **vec = NULL;
158 intptr_t type, ops, ptr;
159 unsigned int dom, count;
160
161 vec = xs_read_watch(xenstore, &count);
162 if (vec == NULL) {
163 goto cleanup;
164 }
165
166 if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
167 &type, &dom, &ops) == 3) {
168 xenstore_update_be(vec[XS_WATCH_PATH], (void *)type, dom, (void*)ops);
169 }
170 if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
171 xenstore_update_fe(vec[XS_WATCH_PATH], (void *)ptr);
172 }
173
174cleanup:
175 free(vec);
176}
177
f0021dba
EC
178const char *xenbus_strstate(enum xenbus_state state)
179{
180 static const char *const name[] = {
181 [XenbusStateUnknown] = "Unknown",
182 [XenbusStateInitialising] = "Initialising",
183 [XenbusStateInitWait] = "InitWait",
184 [XenbusStateInitialised] = "Initialised",
185 [XenbusStateConnected] = "Connected",
186 [XenbusStateClosing] = "Closing",
187 [XenbusStateClosed] = "Closed",
188 };
189 return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
190}
191
192/*
193 * msg_level:
194 * 0 == errors (stderr + logfile).
195 * 1 == informative debug messages (logfile only).
196 * 2 == noisy debug messages (logfile only).
197 * 3 == will flood your log (logfile only).
198 */
d62449da 199G_GNUC_PRINTF(3, 0)
6fef2229
RH
200static void xen_pv_output_msg(struct XenLegacyDevice *xendev,
201 FILE *f, const char *fmt, va_list args)
202{
203 if (xendev) {
204 fprintf(f, "xen be: %s: ", xendev->name);
205 } else {
206 fprintf(f, "xen be core: ");
207 }
208 vfprintf(f, fmt, args);
209}
210
2d0ed5e6 211void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level,
f0021dba
EC
212 const char *fmt, ...)
213{
6fef2229 214 FILE *logfile;
f0021dba
EC
215 va_list args;
216
6fef2229
RH
217 if (msg_level > (xendev ? xendev->debug : debug)) {
218 return;
219 }
220
221 logfile = qemu_log_trylock();
222 if (logfile) {
223 va_start(args, fmt);
224 xen_pv_output_msg(xendev, logfile, fmt, args);
225 va_end(args);
226 qemu_log_unlock(logfile);
f0021dba 227 }
6fef2229 228
f0021dba
EC
229 if (msg_level == 0) {
230 va_start(args, fmt);
6fef2229 231 xen_pv_output_msg(xendev, stderr, fmt, args);
f0021dba
EC
232 va_end(args);
233 }
f0021dba 234}
31c17aa5 235
49442d96 236void xen_pv_evtchn_event(void *opaque)
31c17aa5 237{
2d0ed5e6 238 struct XenLegacyDevice *xendev = opaque;
31c17aa5
EC
239 evtchn_port_t port;
240
241 port = xenevtchn_pending(xendev->evtchndev);
242 if (port != xendev->local_port) {
96c77dba 243 xen_pv_printf(xendev, 0,
31c17aa5
EC
244 "xenevtchn_pending returned %d (expected %d)\n",
245 port, xendev->local_port);
246 return;
247 }
248 xenevtchn_unmask(xendev->evtchndev, port);
249
250 if (xendev->ops->event) {
251 xendev->ops->event(xendev);
252 }
253}
254
2d0ed5e6 255void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev)
31c17aa5
EC
256{
257 if (xendev->local_port == -1) {
258 return;
259 }
260 qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
261 xenevtchn_unbind(xendev->evtchndev, xendev->local_port);
96c77dba 262 xen_pv_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
31c17aa5
EC
263 xendev->local_port = -1;
264}
265
2d0ed5e6 266int xen_pv_send_notify(struct XenLegacyDevice *xendev)
31c17aa5
EC
267{
268 return xenevtchn_notify(xendev->evtchndev, xendev->local_port);
269}
148512e0
EC
270
271/* ------------------------------------------------------------- */
272
2d0ed5e6 273struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev)
148512e0 274{
2d0ed5e6 275 struct XenLegacyDevice *xendev;
148512e0
EC
276
277 QTAILQ_FOREACH(xendev, &xendevs, next) {
278 if (xendev->dom != dom) {
279 continue;
280 }
281 if (xendev->dev != dev) {
282 continue;
283 }
284 if (strcmp(xendev->type, type) != 0) {
285 continue;
286 }
287 return xendev;
288 }
289 return NULL;
290}
291
292/*
293 * release xen backend device.
294 */
2d0ed5e6 295void xen_pv_del_xendev(struct XenLegacyDevice *xendev)
148512e0
EC
296{
297 if (xendev->ops->free) {
298 xendev->ops->free(xendev);
299 }
300
301 if (xendev->fe) {
302 char token[XEN_BUFSIZE];
303 snprintf(token, sizeof(token), "fe:%p", xendev);
304 xs_unwatch(xenstore, xendev->fe, token);
305 g_free(xendev->fe);
306 }
307
308 if (xendev->evtchndev != NULL) {
309 xenevtchn_close(xendev->evtchndev);
310 }
311 if (xendev->gnttabdev != NULL) {
312 xengnttab_close(xendev->gnttabdev);
313 }
314
315 QTAILQ_REMOVE(&xendevs, xendev, next);
3a6c9172
JG
316
317 qdev_unplug(&xendev->qdev, NULL);
148512e0
EC
318}
319
2d0ed5e6 320void xen_pv_insert_xendev(struct XenLegacyDevice *xendev)
148512e0
EC
321{
322 QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
323}