]> git.proxmox.com Git - qemu.git/blame - hw/xen_backend.c
eepro100: Support 32 bit read/write access to flash register
[qemu.git] / hw / xen_backend.c
CommitLineData
d94f9486
AL
1/*
2 * xen backend driver infrastructure
3 * (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; under version 2 of the 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 General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
8167ee88 15 * with this program; if not, see <http://www.gnu.org/licenses/>.
d94f9486
AL
16 */
17
18/*
19 * TODO: add some xenbus / xenstore concepts overview here.
20 */
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <stdarg.h>
25#include <string.h>
26#include <unistd.h>
27#include <fcntl.h>
28#include <inttypes.h>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <sys/mman.h>
32#include <sys/signal.h>
33
34#include <xs.h>
35#include <xenctrl.h>
36#include <xen/grant_table.h>
37
38#include "hw.h"
39#include "qemu-char.h"
2567f579 40#include "qemu-log.h"
d94f9486
AL
41#include "xen_backend.h"
42
43/* ------------------------------------------------------------- */
44
45/* public */
46int xen_xc;
47struct xs_handle *xenstore = NULL;
2c8b24a3 48const char *xen_protocol;
d94f9486
AL
49
50/* private */
72cf2d4f 51static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs = QTAILQ_HEAD_INITIALIZER(xendevs);
d94f9486
AL
52static int debug = 0;
53
54/* ------------------------------------------------------------- */
55
56int xenstore_write_str(const char *base, const char *node, const char *val)
57{
58 char abspath[XEN_BUFSIZE];
59
60 snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
61 if (!xs_write(xenstore, 0, abspath, val, strlen(val)))
62 return -1;
63 return 0;
64}
65
66char *xenstore_read_str(const char *base, const char *node)
67{
68 char abspath[XEN_BUFSIZE];
69 unsigned int len;
70 char *str, *ret = NULL;
71
72 snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
73 str = xs_read(xenstore, 0, abspath, &len);
74 if (str != NULL) {
75 /* move to qemu-allocated memory to make sure
76 * callers can savely qemu_free() stuff. */
77 ret = qemu_strdup(str);
78 free(str);
79 }
80 return ret;
81}
82
83int xenstore_write_int(const char *base, const char *node, int ival)
84{
85 char val[32];
86
87 snprintf(val, sizeof(val), "%d", ival);
88 return xenstore_write_str(base, node, val);
89}
90
91int xenstore_read_int(const char *base, const char *node, int *ival)
92{
93 char *val;
94 int rc = -1;
95
96 val = xenstore_read_str(base, node);
97 if (val && 1 == sscanf(val, "%d", ival))
98 rc = 0;
99 qemu_free(val);
100 return rc;
101}
102
103int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val)
104{
105 return xenstore_write_str(xendev->be, node, val);
106}
107
108int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival)
109{
110 return xenstore_write_int(xendev->be, node, ival);
111}
112
113char *xenstore_read_be_str(struct XenDevice *xendev, const char *node)
114{
115 return xenstore_read_str(xendev->be, node);
116}
117
118int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival)
119{
120 return xenstore_read_int(xendev->be, node, ival);
121}
122
123char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node)
124{
125 return xenstore_read_str(xendev->fe, node);
126}
127
128int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival)
129{
130 return xenstore_read_int(xendev->fe, node, ival);
131}
132
133/* ------------------------------------------------------------- */
134
135const char *xenbus_strstate(enum xenbus_state state)
136{
137 static const char *const name[] = {
138 [ XenbusStateUnknown ] = "Unknown",
139 [ XenbusStateInitialising ] = "Initialising",
140 [ XenbusStateInitWait ] = "InitWait",
141 [ XenbusStateInitialised ] = "Initialised",
142 [ XenbusStateConnected ] = "Connected",
143 [ XenbusStateClosing ] = "Closing",
144 [ XenbusStateClosed ] = "Closed",
145 };
146 return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
147}
148
149int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
150{
151 int rc;
152
153 rc = xenstore_write_be_int(xendev, "state", state);
154 if (rc < 0)
155 return rc;
156 xen_be_printf(xendev, 1, "backend state: %s -> %s\n",
157 xenbus_strstate(xendev->be_state), xenbus_strstate(state));
158 xendev->be_state = state;
159 return 0;
160}
161
162/* ------------------------------------------------------------- */
163
164struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev)
165{
166 struct XenDevice *xendev;
167
72cf2d4f 168 QTAILQ_FOREACH(xendev, &xendevs, next) {
d94f9486
AL
169 if (xendev->dom != dom)
170 continue;
171 if (xendev->dev != dev)
172 continue;
173 if (strcmp(xendev->type, type) != 0)
174 continue;
175 return xendev;
176 }
177 return NULL;
178}
179
180/*
181 * get xen backend device, allocate a new one if it doesn't exist.
182 */
183static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
184 struct XenDevOps *ops)
185{
186 struct XenDevice *xendev;
187 char *dom0;
188
189 xendev = xen_be_find_xendev(type, dom, dev);
190 if (xendev)
191 return xendev;
192
193 /* init new xendev */
194 xendev = qemu_mallocz(ops->size);
195 xendev->type = type;
196 xendev->dom = dom;
197 xendev->dev = dev;
198 xendev->ops = ops;
199
200 dom0 = xs_get_domain_path(xenstore, 0);
201 snprintf(xendev->be, sizeof(xendev->be), "%s/backend/%s/%d/%d",
202 dom0, xendev->type, xendev->dom, xendev->dev);
203 snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
204 xendev->type, xendev->dev);
205 free(dom0);
206
207 xendev->debug = debug;
208 xendev->local_port = -1;
209
210 xendev->evtchndev = xc_evtchn_open();
211 if (xendev->evtchndev < 0) {
212 xen_be_printf(NULL, 0, "can't open evtchn device\n");
213 qemu_free(xendev);
214 return NULL;
215 }
216 fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
217
218 if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
219 xendev->gnttabdev = xc_gnttab_open();
220 if (xendev->gnttabdev < 0) {
221 xen_be_printf(NULL, 0, "can't open gnttab device\n");
222 xc_evtchn_close(xendev->evtchndev);
223 qemu_free(xendev);
224 return NULL;
225 }
226 } else {
227 xendev->gnttabdev = -1;
228 }
229
72cf2d4f 230 QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
d94f9486
AL
231
232 if (xendev->ops->alloc)
233 xendev->ops->alloc(xendev);
234
235 return xendev;
236}
237
238/*
239 * release xen backend device.
240 */
241static struct XenDevice *xen_be_del_xendev(int dom, int dev)
242{
243 struct XenDevice *xendev, *xnext;
244
245 /*
72cf2d4f 246 * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next) but
d94f9486
AL
247 * we save the next pointer in xnext because we might free xendev.
248 */
249 xnext = xendevs.tqh_first;
250 while (xnext) {
251 xendev = xnext;
252 xnext = xendev->next.tqe_next;
253
254 if (xendev->dom != dom)
255 continue;
256 if (xendev->dev != dev && dev != -1)
257 continue;
258
259 if (xendev->ops->free)
260 xendev->ops->free(xendev);
261
262 if (xendev->fe) {
263 char token[XEN_BUFSIZE];
264 snprintf(token, sizeof(token), "fe:%p", xendev);
265 xs_unwatch(xenstore, xendev->fe, token);
266 qemu_free(xendev->fe);
267 }
268
269 if (xendev->evtchndev >= 0)
270 xc_evtchn_close(xendev->evtchndev);
271 if (xendev->gnttabdev >= 0)
272 xc_gnttab_close(xendev->gnttabdev);
273
72cf2d4f 274 QTAILQ_REMOVE(&xendevs, xendev, next);
d94f9486
AL
275 qemu_free(xendev);
276 }
277 return NULL;
278}
279
280/*
281 * Sync internal data structures on xenstore updates.
282 * Node specifies the changed field. node = NULL means
283 * update all fields (used for initialization).
284 */
285static void xen_be_backend_changed(struct XenDevice *xendev, const char *node)
286{
287 if (node == NULL || strcmp(node, "online") == 0) {
288 if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1)
289 xendev->online = 0;
290 }
291
292 if (node) {
293 xen_be_printf(xendev, 2, "backend update: %s\n", node);
294 if (xendev->ops->backend_changed)
295 xendev->ops->backend_changed(xendev, node);
296 }
297}
298
299static void xen_be_frontend_changed(struct XenDevice *xendev, const char *node)
300{
301 int fe_state;
302
303 if (node == NULL || strcmp(node, "state") == 0) {
304 if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1)
305 fe_state = XenbusStateUnknown;
306 if (xendev->fe_state != fe_state)
307 xen_be_printf(xendev, 1, "frontend state: %s -> %s\n",
308 xenbus_strstate(xendev->fe_state),
309 xenbus_strstate(fe_state));
310 xendev->fe_state = fe_state;
311 }
312 if (node == NULL || strcmp(node, "protocol") == 0) {
313 qemu_free(xendev->protocol);
314 xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
315 if (xendev->protocol)
316 xen_be_printf(xendev, 1, "frontend protocol: %s\n", xendev->protocol);
317 }
318
319 if (node) {
320 xen_be_printf(xendev, 2, "frontend update: %s\n", node);
321 if (xendev->ops->frontend_changed)
322 xendev->ops->frontend_changed(xendev, node);
323 }
324}
325
326/* ------------------------------------------------------------- */
327/* Check for possible state transitions and perform them. */
328
329/*
330 * Initial xendev setup. Read frontend path, register watch for it.
331 * Should succeed once xend finished setting up the backend device.
332 *
333 * Also sets initial state (-> Initializing) when done. Which
334 * only affects the xendev->be_state variable as xenbus should
335 * already be put into that state by xend.
336 */
337static int xen_be_try_setup(struct XenDevice *xendev)
338{
339 char token[XEN_BUFSIZE];
340 int be_state;
341
342 if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
343 xen_be_printf(xendev, 0, "reading backend state failed\n");
344 return -1;
345 }
346
347 if (be_state != XenbusStateInitialising) {
348 xen_be_printf(xendev, 0, "initial backend state is wrong (%s)\n",
349 xenbus_strstate(be_state));
350 return -1;
351 }
352
353 xendev->fe = xenstore_read_be_str(xendev, "frontend");
354 if (xendev->fe == NULL) {
355 xen_be_printf(xendev, 0, "reading frontend path failed\n");
356 return -1;
357 }
358
359 /* setup frontend watch */
360 snprintf(token, sizeof(token), "fe:%p", xendev);
361 if (!xs_watch(xenstore, xendev->fe, token)) {
362 xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
363 xendev->fe);
364 return -1;
365 }
366 xen_be_set_state(xendev, XenbusStateInitialising);
367
368 xen_be_backend_changed(xendev, NULL);
369 xen_be_frontend_changed(xendev, NULL);
370 return 0;
371}
372
373/*
374 * Try initialize xendev. Prepare everything the backend can do
375 * without synchronizing with the frontend. Fakes hotplug-status. No
376 * hotplug involved here because this is about userspace drivers, thus
377 * there are kernel backend devices which could invoke hotplug.
378 *
379 * Goes to InitWait on success.
380 */
381static int xen_be_try_init(struct XenDevice *xendev)
382{
383 int rc = 0;
384
385 if (!xendev->online) {
386 xen_be_printf(xendev, 1, "not online\n");
387 return -1;
388 }
389
390 if (xendev->ops->init)
391 rc = xendev->ops->init(xendev);
392 if (rc != 0) {
393 xen_be_printf(xendev, 1, "init() failed\n");
394 return rc;
395 }
396
397 xenstore_write_be_str(xendev, "hotplug-status", "connected");
398 xen_be_set_state(xendev, XenbusStateInitWait);
399 return 0;
400}
401
402/*
403 * Try to connect xendev. Depends on the frontend being ready
404 * for it (shared ring and evtchn info in xenstore, state being
405 * Initialised or Connected).
406 *
407 * Goes to Connected on success.
408 */
409static int xen_be_try_connect(struct XenDevice *xendev)
410{
411 int rc = 0;
412
413 if (xendev->fe_state != XenbusStateInitialised &&
414 xendev->fe_state != XenbusStateConnected) {
415 if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
416 xen_be_printf(xendev, 2, "frontend not ready, ignoring\n");
417 } else {
418 xen_be_printf(xendev, 2, "frontend not ready (yet)\n");
419 return -1;
420 }
421 }
422
423 if (xendev->ops->connect)
424 rc = xendev->ops->connect(xendev);
425 if (rc != 0) {
426 xen_be_printf(xendev, 0, "connect() failed\n");
427 return rc;
428 }
429
430 xen_be_set_state(xendev, XenbusStateConnected);
431 return 0;
432}
433
434/*
435 * Teardown connection.
436 *
437 * Goes to Closed when done.
438 */
439static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state)
440{
441 if (xendev->be_state != XenbusStateClosing &&
442 xendev->be_state != XenbusStateClosed &&
443 xendev->ops->disconnect)
444 xendev->ops->disconnect(xendev);
445 if (xendev->be_state != state)
446 xen_be_set_state(xendev, state);
447}
448
449/*
450 * Try to reset xendev, for reconnection by another frontend instance.
451 */
452static int xen_be_try_reset(struct XenDevice *xendev)
453{
454 if (xendev->fe_state != XenbusStateInitialising)
455 return -1;
456
457 xen_be_printf(xendev, 1, "device reset (for re-connect)\n");
458 xen_be_set_state(xendev, XenbusStateInitialising);
459 return 0;
460}
461
462/*
463 * state change dispatcher function
464 */
465void xen_be_check_state(struct XenDevice *xendev)
466{
467 int rc = 0;
468
469 /* frontend may request shutdown from almost anywhere */
470 if (xendev->fe_state == XenbusStateClosing ||
471 xendev->fe_state == XenbusStateClosed) {
472 xen_be_disconnect(xendev, xendev->fe_state);
473 return;
474 }
475
476 /* check for possible backend state transitions */
477 for (;;) {
478 switch (xendev->be_state) {
479 case XenbusStateUnknown:
480 rc = xen_be_try_setup(xendev);
481 break;
482 case XenbusStateInitialising:
483 rc = xen_be_try_init(xendev);
484 break;
485 case XenbusStateInitWait:
486 rc = xen_be_try_connect(xendev);
487 break;
488 case XenbusStateClosed:
489 rc = xen_be_try_reset(xendev);
490 break;
491 default:
492 rc = -1;
493 }
494 if (rc != 0)
495 break;
496 }
497}
498
499/* ------------------------------------------------------------- */
500
501static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
502{
503 struct XenDevice *xendev;
504 char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
505 char **dev = NULL, *dom0;
506 unsigned int cdev, j;
507
508 /* setup watch */
509 dom0 = xs_get_domain_path(xenstore, 0);
510 snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
511 snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
512 free(dom0);
513 if (!xs_watch(xenstore, path, token)) {
514 xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
515 return -1;
516 }
517
518 /* look for backends */
519 dev = xs_directory(xenstore, 0, path, &cdev);
520 if (!dev)
521 return 0;
522 for (j = 0; j < cdev; j++) {
523 xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
524 if (xendev == NULL)
525 continue;
526 xen_be_check_state(xendev);
527 }
528 free(dev);
529 return 0;
530}
531
532static void xenstore_update_be(char *watch, char *type, int dom,
533 struct XenDevOps *ops)
534{
535 struct XenDevice *xendev;
536 char path[XEN_BUFSIZE], *dom0;
537 unsigned int len, dev;
538
539 dom0 = xs_get_domain_path(xenstore, 0);
540 len = snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
541 free(dom0);
542 if (strncmp(path, watch, len) != 0)
543 return;
544 if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
545 strcpy(path, "");
546 if (sscanf(watch+len, "/%u", &dev) != 1)
547 dev = -1;
548 }
549 if (dev == -1)
550 return;
551
552 if (0) {
553 /* FIXME: detect devices being deleted from xenstore ... */
554 xen_be_del_xendev(dom, dev);
555 }
556
557 xendev = xen_be_get_xendev(type, dom, dev, ops);
558 if (xendev != NULL) {
559 xen_be_backend_changed(xendev, path);
560 xen_be_check_state(xendev);
561 }
562}
563
564static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
565{
566 char *node;
567 unsigned int len;
568
569 len = strlen(xendev->fe);
570 if (strncmp(xendev->fe, watch, len) != 0)
571 return;
572 if (watch[len] != '/')
573 return;
574 node = watch + len + 1;
575
576 xen_be_frontend_changed(xendev, node);
577 xen_be_check_state(xendev);
578}
579
580static void xenstore_update(void *unused)
581{
582 char **vec = NULL;
583 intptr_t type, ops, ptr;
584 unsigned int dom, count;
585
586 vec = xs_read_watch(xenstore, &count);
587 if (vec == NULL)
588 goto cleanup;
589
590 if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
591 &type, &dom, &ops) == 3)
592 xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
593 if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1)
594 xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
595
596cleanup:
834fac78 597 free(vec);
d94f9486
AL
598}
599
600static void xen_be_evtchn_event(void *opaque)
601{
602 struct XenDevice *xendev = opaque;
603 evtchn_port_t port;
604
605 port = xc_evtchn_pending(xendev->evtchndev);
606 if (port != xendev->local_port) {
607 xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
608 port, xendev->local_port);
609 return;
610 }
611 xc_evtchn_unmask(xendev->evtchndev, port);
612
613 if (xendev->ops->event)
614 xendev->ops->event(xendev);
615}
616
617/* -------------------------------------------------------------------- */
618
619int xen_be_init(void)
620{
621 xenstore = xs_daemon_open();
622 if (!xenstore) {
623 xen_be_printf(NULL, 0, "can't connect to xenstored\n");
624 return -1;
625 }
626
627 if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0)
628 goto err;
629
630 xen_xc = xc_interface_open();
631 if (xen_xc == -1) {
632 xen_be_printf(NULL, 0, "can't open xen interface\n");
633 goto err;
634 }
635 return 0;
636
637err:
638 qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
639 xs_daemon_close(xenstore);
640 xenstore = NULL;
641
642 return -1;
643}
644
645int xen_be_register(const char *type, struct XenDevOps *ops)
646{
647 return xenstore_scan(type, xen_domid, ops);
648}
649
650int xen_be_bind_evtchn(struct XenDevice *xendev)
651{
652 if (xendev->local_port != -1)
653 return 0;
654 xendev->local_port = xc_evtchn_bind_interdomain
655 (xendev->evtchndev, xendev->dom, xendev->remote_port);
656 if (xendev->local_port == -1) {
657 xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
658 return -1;
659 }
660 xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
661 qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
662 xen_be_evtchn_event, NULL, xendev);
663 return 0;
664}
665
666void xen_be_unbind_evtchn(struct XenDevice *xendev)
667{
668 if (xendev->local_port == -1)
669 return;
670 qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
671 xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
672 xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
673 xendev->local_port = -1;
674}
675
676int xen_be_send_notify(struct XenDevice *xendev)
677{
678 return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
679}
680
681/*
682 * msg_level:
683 * 0 == errors (stderr + logfile).
684 * 1 == informative debug messages (logfile only).
685 * 2 == noisy debug messages (logfile only).
686 * 3 == will flood your log (logfile only).
687 */
688void xen_be_printf(struct XenDevice *xendev, int msg_level, const char *fmt, ...)
689{
690 va_list args;
691
692 if (xendev) {
693 if (msg_level > xendev->debug)
694 return;
695 qemu_log("xen be: %s: ", xendev->name);
696 if (msg_level == 0)
697 fprintf(stderr, "xen be: %s: ", xendev->name);
698 } else {
699 if (msg_level > debug)
700 return;
701 qemu_log("xen be core: ");
702 if (msg_level == 0)
703 fprintf(stderr, "xen be core: ");
704 }
705 va_start(args, fmt);
706 qemu_log_vprintf(fmt, args);
707 va_end(args);
708 if (msg_level == 0) {
709 va_start(args, fmt);
710 vfprintf(stderr, fmt, args);
711 va_end(args);
712 }
713 qemu_log_flush();
714}