]> git.proxmox.com Git - mirror_qemu.git/blame - hw/xen/xen-bus.c
spapr_pci: Fix interrupt leak in rtas_ibm_change_msi() error path
[mirror_qemu.git] / hw / xen / xen-bus.c
CommitLineData
108f7bba
PD
1/*
2 * Copyright (c) 2018 Citrix Systems Inc.
3 *
4 * This work is licensed under the terms of the GNU GPL, version 2 or later.
5 * See the COPYING file in the top-level directory.
6 */
7
8#include "qemu/osdep.h"
82a29e30
PD
9#include "qemu/main-loop.h"
10#include "qemu/uuid.h"
108f7bba
PD
11#include "hw/hw.h"
12#include "hw/sysbus.h"
094a2239 13#include "hw/xen/xen.h"
a783f8ad 14#include "hw/xen/xen-backend.h"
108f7bba 15#include "hw/xen/xen-bus.h"
094a2239
PD
16#include "hw/xen/xen-bus-helper.h"
17#include "monitor/monitor.h"
108f7bba 18#include "qapi/error.h"
a783f8ad 19#include "qapi/qmp/qdict.h"
094a2239 20#include "sysemu/sysemu.h"
108f7bba
PD
21#include "trace.h"
22
094a2239
PD
23static char *xen_device_get_backend_path(XenDevice *xendev)
24{
25 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
26 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
27 const char *type = object_get_typename(OBJECT(xendev));
28 const char *backend = xendev_class->backend;
29
30 if (!backend) {
31 backend = type;
32 }
33
34 return g_strdup_printf("/local/domain/%u/backend/%s/%u/%s",
35 xenbus->backend_id, backend, xendev->frontend_id,
36 xendev->name);
37}
38
39static char *xen_device_get_frontend_path(XenDevice *xendev)
40{
41 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
42 const char *type = object_get_typename(OBJECT(xendev));
43 const char *device = xendev_class->device;
44
45 if (!device) {
46 device = type;
47 }
48
49 return g_strdup_printf("/local/domain/%u/device/%s/%s",
50 xendev->frontend_id, device, xendev->name);
51}
52
b6af8926
PD
53static void xen_device_unplug(XenDevice *xendev, Error **errp)
54{
55 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
56 const char *type = object_get_typename(OBJECT(xendev));
57 Error *local_err = NULL;
58 xs_transaction_t tid;
59
60 trace_xen_device_unplug(type, xendev->name);
61
62 /* Mimic the way the Xen toolstack does an unplug */
63again:
64 tid = xs_transaction_start(xenbus->xsh);
65 if (tid == XBT_NULL) {
66 error_setg_errno(errp, errno, "failed xs_transaction_start");
67 return;
68 }
69
70 xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "online",
71 &local_err, "%u", 0);
72 if (local_err) {
73 goto abort;
74 }
75
76 xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "state",
77 &local_err, "%u", XenbusStateClosing);
78 if (local_err) {
79 goto abort;
80 }
81
82 if (!xs_transaction_end(xenbus->xsh, tid, false)) {
83 if (errno == EAGAIN) {
84 goto again;
85 }
86
87 error_setg_errno(errp, errno, "failed xs_transaction_end");
88 }
89
90 return;
91
92abort:
93 /*
94 * We only abort if there is already a failure so ignore any error
95 * from ending the transaction.
96 */
97 xs_transaction_end(xenbus->xsh, tid, true);
98 error_propagate(errp, local_err);
99}
100
094a2239
PD
101static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent)
102{
103 XenDevice *xendev = XEN_DEVICE(dev);
104
105 monitor_printf(mon, "%*sname = '%s' frontend_id = %u\n",
106 indent, "", xendev->name, xendev->frontend_id);
107}
108
109static char *xen_bus_get_dev_path(DeviceState *dev)
110{
111 return xen_device_get_backend_path(XEN_DEVICE(dev));
112}
113
82a29e30
PD
114struct XenWatch {
115 char *node, *key;
116 char *token;
117 XenWatchHandler handler;
118 void *opaque;
119 Notifier notifier;
120};
121
122static void watch_notify(Notifier *n, void *data)
123{
124 XenWatch *watch = container_of(n, XenWatch, notifier);
125 const char *token = data;
126
127 if (!strcmp(watch->token, token)) {
128 watch->handler(watch->opaque);
129 }
130}
131
132static XenWatch *new_watch(const char *node, const char *key,
133 XenWatchHandler handler, void *opaque)
134{
135 XenWatch *watch = g_new0(XenWatch, 1);
136 QemuUUID uuid;
137
138 qemu_uuid_generate(&uuid);
139
140 watch->token = qemu_uuid_unparse_strdup(&uuid);
141 watch->node = g_strdup(node);
142 watch->key = g_strdup(key);
143 watch->handler = handler;
144 watch->opaque = opaque;
145 watch->notifier.notify = watch_notify;
146
147 return watch;
148}
149
150static void free_watch(XenWatch *watch)
151{
152 g_free(watch->token);
153 g_free(watch->key);
154 g_free(watch->node);
155
156 g_free(watch);
157}
158
159static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
160 const char *key, XenWatchHandler handler,
161 void *opaque, Error **errp)
162{
163 XenWatch *watch = new_watch(node, key, handler, opaque);
164 Error *local_err = NULL;
165
166 trace_xen_bus_add_watch(watch->node, watch->key, watch->token);
167
168 notifier_list_add(&xenbus->watch_notifiers, &watch->notifier);
169
170 xs_node_watch(xenbus->xsh, node, key, watch->token, &local_err);
171 if (local_err) {
172 error_propagate(errp, local_err);
173
174 notifier_remove(&watch->notifier);
175 free_watch(watch);
176
177 return NULL;
178 }
179
180 return watch;
181}
182
183static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch,
184 Error **errp)
185{
186 trace_xen_bus_remove_watch(watch->node, watch->key, watch->token);
187
188 xs_node_unwatch(xenbus->xsh, watch->node, watch->key, watch->token,
189 errp);
190
191 notifier_remove(&watch->notifier);
192 free_watch(watch);
193}
194
a783f8ad
PD
195static void xen_bus_backend_create(XenBus *xenbus, const char *type,
196 const char *name, char *path,
197 Error **errp)
198{
199 xs_transaction_t tid;
200 char **key;
201 QDict *opts;
202 unsigned int i, n;
203 Error *local_err = NULL;
204
205 trace_xen_bus_backend_create(type, path);
206
207again:
208 tid = xs_transaction_start(xenbus->xsh);
209 if (tid == XBT_NULL) {
210 error_setg(errp, "failed xs_transaction_start");
211 return;
212 }
213
214 key = xs_directory(xenbus->xsh, tid, path, &n);
215 if (!key) {
216 if (!xs_transaction_end(xenbus->xsh, tid, true)) {
217 error_setg_errno(errp, errno, "failed xs_transaction_end");
218 }
219 return;
220 }
221
222 opts = qdict_new();
223 for (i = 0; i < n; i++) {
224 char *val;
225
226 /*
227 * Assume anything found in the xenstore backend area, other than
228 * the keys created for a generic XenDevice, are parameters
229 * to be used to configure the backend.
230 */
231 if (!strcmp(key[i], "state") ||
232 !strcmp(key[i], "online") ||
233 !strcmp(key[i], "frontend") ||
234 !strcmp(key[i], "frontend-id") ||
235 !strcmp(key[i], "hotplug-status"))
236 continue;
237
238 if (xs_node_scanf(xenbus->xsh, tid, path, key[i], NULL, "%ms",
239 &val) == 1) {
240 qdict_put_str(opts, key[i], val);
241 free(val);
242 }
243 }
244
245 free(key);
246
247 if (!xs_transaction_end(xenbus->xsh, tid, false)) {
248 qobject_unref(opts);
249
250 if (errno == EAGAIN) {
251 goto again;
252 }
253
254 error_setg_errno(errp, errno, "failed xs_transaction_end");
255 return;
256 }
257
258 xen_backend_device_create(xenbus, type, name, opts, &local_err);
259 qobject_unref(opts);
260
261 if (local_err) {
262 error_propagate_prepend(errp, local_err,
263 "failed to create '%s' device '%s': ",
264 type, name);
265 }
266}
267
268static void xen_bus_type_enumerate(XenBus *xenbus, const char *type)
269{
270 char *domain_path = g_strdup_printf("backend/%s/%u", type, xen_domid);
271 char **backend;
272 unsigned int i, n;
273
274 trace_xen_bus_type_enumerate(type);
275
276 backend = xs_directory(xenbus->xsh, XBT_NULL, domain_path, &n);
277 if (!backend) {
278 goto out;
279 }
280
281 for (i = 0; i < n; i++) {
282 char *backend_path = g_strdup_printf("%s/%s", domain_path,
283 backend[i]);
284 enum xenbus_state backend_state;
285
286 if (xs_node_scanf(xenbus->xsh, XBT_NULL, backend_path, "state",
287 NULL, "%u", &backend_state) != 1)
288 backend_state = XenbusStateUnknown;
289
290 if (backend_state == XenbusStateInitialising) {
291 Error *local_err = NULL;
292
293 xen_bus_backend_create(xenbus, type, backend[i], backend_path,
294 &local_err);
295 if (local_err) {
296 error_report_err(local_err);
297 }
298 }
299
300 g_free(backend_path);
301 }
302
303 free(backend);
304
305out:
306 g_free(domain_path);
307}
308
309static void xen_bus_enumerate(void *opaque)
310{
311 XenBus *xenbus = opaque;
312 char **type;
313 unsigned int i, n;
314
315 trace_xen_bus_enumerate();
316
317 type = xs_directory(xenbus->xsh, XBT_NULL, "backend", &n);
318 if (!type) {
319 return;
320 }
321
322 for (i = 0; i < n; i++) {
323 xen_bus_type_enumerate(xenbus, type[i]);
324 }
325
326 free(type);
327}
328
108f7bba
PD
329static void xen_bus_unrealize(BusState *bus, Error **errp)
330{
094a2239
PD
331 XenBus *xenbus = XEN_BUS(bus);
332
108f7bba 333 trace_xen_bus_unrealize();
094a2239 334
a783f8ad
PD
335 if (xenbus->backend_watch) {
336 xen_bus_remove_watch(xenbus, xenbus->backend_watch, NULL);
337 xenbus->backend_watch = NULL;
338 }
339
094a2239
PD
340 if (!xenbus->xsh) {
341 return;
342 }
343
82a29e30
PD
344 qemu_set_fd_handler(xs_fileno(xenbus->xsh), NULL, NULL, NULL);
345
094a2239 346 xs_close(xenbus->xsh);
108f7bba
PD
347}
348
82a29e30
PD
349static void xen_bus_watch(void *opaque)
350{
351 XenBus *xenbus = opaque;
352 char **v;
353 const char *token;
354
355 g_assert(xenbus->xsh);
356
357 v = xs_check_watch(xenbus->xsh);
358 if (!v) {
359 return;
360 }
361
362 token = v[XS_WATCH_TOKEN];
363
364 trace_xen_bus_watch(token);
365
366 notifier_list_notify(&xenbus->watch_notifiers, (void *)token);
367
368 free(v);
369}
370
108f7bba
PD
371static void xen_bus_realize(BusState *bus, Error **errp)
372{
094a2239
PD
373 XenBus *xenbus = XEN_BUS(bus);
374 unsigned int domid;
a783f8ad 375 Error *local_err = NULL;
094a2239 376
108f7bba 377 trace_xen_bus_realize();
094a2239
PD
378
379 xenbus->xsh = xs_open(0);
380 if (!xenbus->xsh) {
381 error_setg_errno(errp, errno, "failed xs_open");
382 goto fail;
383 }
384
385 if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */
386 "domid", NULL, "%u", &domid) == 1) {
387 xenbus->backend_id = domid;
388 } else {
389 xenbus->backend_id = 0; /* Assume lack of node means dom0 */
390 }
391
82a29e30
PD
392 notifier_list_init(&xenbus->watch_notifiers);
393 qemu_set_fd_handler(xs_fileno(xenbus->xsh), xen_bus_watch, NULL,
394 xenbus);
a783f8ad
PD
395
396 module_call_init(MODULE_INIT_XEN_BACKEND);
397
398 xenbus->backend_watch =
399 xen_bus_add_watch(xenbus, "", /* domain root node */
400 "backend", xen_bus_enumerate, xenbus, &local_err);
401 if (local_err) {
402 /* This need not be treated as a hard error so don't propagate */
403 error_reportf_err(local_err,
404 "failed to set up enumeration watch: ");
405 }
406
094a2239
PD
407 return;
408
409fail:
410 xen_bus_unrealize(bus, &error_abort);
108f7bba
PD
411}
412
b6af8926
PD
413static void xen_bus_unplug_request(HotplugHandler *hotplug,
414 DeviceState *dev,
415 Error **errp)
416{
417 XenDevice *xendev = XEN_DEVICE(dev);
418
419 xen_device_unplug(xendev, errp);
420}
421
108f7bba
PD
422static void xen_bus_class_init(ObjectClass *class, void *data)
423{
424 BusClass *bus_class = BUS_CLASS(class);
b6af8926 425 HotplugHandlerClass *hotplug_class = HOTPLUG_HANDLER_CLASS(class);
108f7bba 426
094a2239
PD
427 bus_class->print_dev = xen_bus_print_dev;
428 bus_class->get_dev_path = xen_bus_get_dev_path;
108f7bba
PD
429 bus_class->realize = xen_bus_realize;
430 bus_class->unrealize = xen_bus_unrealize;
b6af8926
PD
431
432 hotplug_class->unplug_request = xen_bus_unplug_request;
108f7bba
PD
433}
434
435static const TypeInfo xen_bus_type_info = {
436 .name = TYPE_XEN_BUS,
437 .parent = TYPE_BUS,
438 .instance_size = sizeof(XenBus),
439 .class_size = sizeof(XenBusClass),
440 .class_init = xen_bus_class_init,
441 .interfaces = (InterfaceInfo[]) {
442 { TYPE_HOTPLUG_HANDLER },
443 { }
444 },
445};
446
b6af8926
PD
447void xen_device_backend_printf(XenDevice *xendev, const char *key,
448 const char *fmt, ...)
094a2239
PD
449{
450 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
451 Error *local_err = NULL;
452 va_list ap;
453
454 g_assert(xenbus->xsh);
455
456 va_start(ap, fmt);
457 xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
458 &local_err, fmt, ap);
459 va_end(ap);
460
461 if (local_err) {
462 error_report_err(local_err);
463 }
464}
465
82a29e30
PD
466static int xen_device_backend_scanf(XenDevice *xendev, const char *key,
467 const char *fmt, ...)
468{
469 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
470 va_list ap;
471 int rc;
472
473 g_assert(xenbus->xsh);
474
475 va_start(ap, fmt);
476 rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
477 NULL, fmt, ap);
478 va_end(ap);
479
480 return rc;
481}
482
483void xen_device_backend_set_state(XenDevice *xendev,
484 enum xenbus_state state)
094a2239
PD
485{
486 const char *type = object_get_typename(OBJECT(xendev));
487
488 if (xendev->backend_state == state) {
489 return;
490 }
491
492 trace_xen_device_backend_state(type, xendev->name,
493 xs_strstate(state));
494
495 xendev->backend_state = state;
496 xen_device_backend_printf(xendev, "state", "%u", state);
497}
498
82a29e30
PD
499enum xenbus_state xen_device_backend_get_state(XenDevice *xendev)
500{
501 return xendev->backend_state;
502}
503
b6af8926
PD
504static void xen_device_backend_set_online(XenDevice *xendev, bool online)
505{
506 const char *type = object_get_typename(OBJECT(xendev));
507
508 if (xendev->backend_online == online) {
509 return;
510 }
511
512 trace_xen_device_backend_online(type, xendev->name, online);
513
514 xendev->backend_online = online;
515 xen_device_backend_printf(xendev, "online", "%u", online);
516}
517
518static void xen_device_backend_changed(void *opaque)
519{
520 XenDevice *xendev = opaque;
521 const char *type = object_get_typename(OBJECT(xendev));
522 enum xenbus_state state;
523 unsigned int online;
524
525 trace_xen_device_backend_changed(type, xendev->name);
526
527 if (xen_device_backend_scanf(xendev, "state", "%u", &state) != 1) {
528 state = XenbusStateUnknown;
529 }
530
531 xen_device_backend_set_state(xendev, state);
532
533 if (xen_device_backend_scanf(xendev, "online", "%u", &online) != 1) {
534 online = 0;
535 }
536
537 xen_device_backend_set_online(xendev, !!online);
538
539 /*
540 * If the toolstack (or unplug request callback) has set the backend
541 * state to Closing, but there is no active frontend (i.e. the
542 * state is not Connected) then set the backend state to Closed.
543 */
544 if (xendev->backend_state == XenbusStateClosing &&
545 xendev->frontend_state != XenbusStateConnected) {
546 xen_device_backend_set_state(xendev, XenbusStateClosed);
547 }
548
549 /*
67bc8e00
PD
550 * If a backend is still 'online' then we should leave it alone but,
551 * if a backend is not 'online', then the device should be destroyed
552 * once the state is Closed.
b6af8926 553 */
67bc8e00
PD
554 if (!xendev->backend_online &&
555 (xendev->backend_state == XenbusStateClosed ||
556 xendev->backend_state == XenbusStateInitialising ||
557 xendev->backend_state == XenbusStateInitWait ||
558 xendev->backend_state == XenbusStateUnknown)) {
a783f8ad
PD
559 Error *local_err = NULL;
560
561 if (!xen_backend_try_device_destroy(xendev, &local_err)) {
562 object_unparent(OBJECT(xendev));
563 }
564
565 if (local_err) {
566 error_report_err(local_err);
567 }
b6af8926
PD
568 }
569}
570
094a2239
PD
571static void xen_device_backend_create(XenDevice *xendev, Error **errp)
572{
573 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
574 struct xs_permissions perms[2];
575 Error *local_err = NULL;
576
577 xendev->backend_path = xen_device_get_backend_path(xendev);
578
579 perms[0].id = xenbus->backend_id;
580 perms[0].perms = XS_PERM_NONE;
581 perms[1].id = xendev->frontend_id;
582 perms[1].perms = XS_PERM_READ;
583
584 g_assert(xenbus->xsh);
585
586 xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path, perms,
587 ARRAY_SIZE(perms), &local_err);
588 if (local_err) {
589 error_propagate_prepend(errp, local_err,
590 "failed to create backend: ");
b6af8926
PD
591 return;
592 }
593
594 xendev->backend_state_watch =
595 xen_bus_add_watch(xenbus, xendev->backend_path,
596 "state", xen_device_backend_changed,
597 xendev, &local_err);
598 if (local_err) {
599 error_propagate_prepend(errp, local_err,
600 "failed to watch backend state: ");
601 return;
602 }
603
604 xendev->backend_online_watch =
605 xen_bus_add_watch(xenbus, xendev->backend_path,
606 "online", xen_device_backend_changed,
607 xendev, &local_err);
608 if (local_err) {
609 error_propagate_prepend(errp, local_err,
610 "failed to watch backend online: ");
611 return;
094a2239
PD
612 }
613}
614
615static void xen_device_backend_destroy(XenDevice *xendev)
616{
617 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
618 Error *local_err = NULL;
619
b6af8926
PD
620 if (xendev->backend_online_watch) {
621 xen_bus_remove_watch(xenbus, xendev->backend_online_watch, NULL);
622 xendev->backend_online_watch = NULL;
623 }
624
625 if (xendev->backend_state_watch) {
626 xen_bus_remove_watch(xenbus, xendev->backend_state_watch, NULL);
627 xendev->backend_state_watch = NULL;
628 }
629
094a2239
PD
630 if (!xendev->backend_path) {
631 return;
632 }
633
634 g_assert(xenbus->xsh);
635
636 xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->backend_path,
637 &local_err);
638 g_free(xendev->backend_path);
639 xendev->backend_path = NULL;
640
641 if (local_err) {
642 error_report_err(local_err);
643 }
644}
645
b6af8926
PD
646void xen_device_frontend_printf(XenDevice *xendev, const char *key,
647 const char *fmt, ...)
094a2239
PD
648{
649 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
650 Error *local_err = NULL;
651 va_list ap;
652
653 g_assert(xenbus->xsh);
654
655 va_start(ap, fmt);
656 xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
657 &local_err, fmt, ap);
658 va_end(ap);
659
660 if (local_err) {
661 error_report_err(local_err);
662 }
663}
664
b6af8926
PD
665int xen_device_frontend_scanf(XenDevice *xendev, const char *key,
666 const char *fmt, ...)
82a29e30
PD
667{
668 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
669 va_list ap;
670 int rc;
671
672 g_assert(xenbus->xsh);
673
674 va_start(ap, fmt);
675 rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
676 NULL, fmt, ap);
677 va_end(ap);
678
679 return rc;
680}
681
094a2239
PD
682static void xen_device_frontend_set_state(XenDevice *xendev,
683 enum xenbus_state state)
684{
685 const char *type = object_get_typename(OBJECT(xendev));
686
687 if (xendev->frontend_state == state) {
688 return;
689 }
690
691 trace_xen_device_frontend_state(type, xendev->name,
692 xs_strstate(state));
693
694 xendev->frontend_state = state;
695 xen_device_frontend_printf(xendev, "state", "%u", state);
696}
697
82a29e30
PD
698static void xen_device_frontend_changed(void *opaque)
699{
700 XenDevice *xendev = opaque;
701 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
702 const char *type = object_get_typename(OBJECT(xendev));
703 enum xenbus_state state;
704
705 trace_xen_device_frontend_changed(type, xendev->name);
706
707 if (xen_device_frontend_scanf(xendev, "state", "%u", &state) != 1) {
708 state = XenbusStateUnknown;
709 }
710
711 xen_device_frontend_set_state(xendev, state);
712
67bc8e00
PD
713 if (state == XenbusStateInitialising &&
714 xendev->backend_state == XenbusStateClosed &&
715 xendev->backend_online) {
716 /*
717 * The frontend is re-initializing so switch back to
718 * InitWait.
719 */
720 xen_device_backend_set_state(xendev, XenbusStateInitWait);
721 return;
722 }
723
82a29e30
PD
724 if (xendev_class->frontend_changed) {
725 Error *local_err = NULL;
726
727 xendev_class->frontend_changed(xendev, state, &local_err);
728
729 if (local_err) {
730 error_reportf_err(local_err, "frontend change error: ");
731 }
732 }
82a29e30
PD
733}
734
094a2239
PD
735static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
736{
737 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
738 struct xs_permissions perms[2];
739 Error *local_err = NULL;
740
741 xendev->frontend_path = xen_device_get_frontend_path(xendev);
742
743 perms[0].id = xendev->frontend_id;
744 perms[0].perms = XS_PERM_NONE;
745 perms[1].id = xenbus->backend_id;
746 perms[1].perms = XS_PERM_READ | XS_PERM_WRITE;
747
748 g_assert(xenbus->xsh);
749
750 xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms,
751 ARRAY_SIZE(perms), &local_err);
752 if (local_err) {
753 error_propagate_prepend(errp, local_err,
754 "failed to create frontend: ");
82a29e30
PD
755 return;
756 }
757
758 xendev->frontend_state_watch =
759 xen_bus_add_watch(xenbus, xendev->frontend_path, "state",
760 xen_device_frontend_changed, xendev, &local_err);
761 if (local_err) {
762 error_propagate_prepend(errp, local_err,
763 "failed to watch frontend state: ");
094a2239
PD
764 }
765}
766
767static void xen_device_frontend_destroy(XenDevice *xendev)
768{
769 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
770 Error *local_err = NULL;
771
82a29e30
PD
772 if (xendev->frontend_state_watch) {
773 xen_bus_remove_watch(xenbus, xendev->frontend_state_watch, NULL);
774 xendev->frontend_state_watch = NULL;
775 }
776
094a2239
PD
777 if (!xendev->frontend_path) {
778 return;
779 }
780
781 g_assert(xenbus->xsh);
782
783 xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->frontend_path,
784 &local_err);
785 g_free(xendev->frontend_path);
786 xendev->frontend_path = NULL;
787
788 if (local_err) {
789 error_report_err(local_err);
790 }
791}
792
4b34b5b1
PD
793void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs,
794 Error **errp)
795{
796 if (xengnttab_set_max_grants(xendev->xgth, nr_refs)) {
797 error_setg_errno(errp, errno, "xengnttab_set_max_grants failed");
798 }
799}
800
801void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs,
802 unsigned int nr_refs, int prot,
803 Error **errp)
804{
805 void *map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_refs,
806 xendev->frontend_id, refs,
807 prot);
808
809 if (!map) {
810 error_setg_errno(errp, errno,
811 "xengnttab_map_domain_grant_refs failed");
812 }
813
814 return map;
815}
816
817void xen_device_unmap_grant_refs(XenDevice *xendev, void *map,
818 unsigned int nr_refs, Error **errp)
819{
820 if (xengnttab_unmap(xendev->xgth, map, nr_refs)) {
821 error_setg_errno(errp, errno, "xengnttab_unmap failed");
822 }
823}
824
825static void compat_copy_grant_refs(XenDevice *xendev, bool to_domain,
826 XenDeviceGrantCopySegment segs[],
827 unsigned int nr_segs, Error **errp)
828{
829 uint32_t *refs = g_new(uint32_t, nr_segs);
830 int prot = to_domain ? PROT_WRITE : PROT_READ;
831 void *map;
832 unsigned int i;
833
834 for (i = 0; i < nr_segs; i++) {
835 XenDeviceGrantCopySegment *seg = &segs[i];
836
837 refs[i] = to_domain ? seg->dest.foreign.ref :
838 seg->source.foreign.ref;
839 }
840
841 map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_segs,
842 xendev->frontend_id, refs,
843 prot);
844 if (!map) {
845 error_setg_errno(errp, errno,
846 "xengnttab_map_domain_grant_refs failed");
847 goto done;
848 }
849
850 for (i = 0; i < nr_segs; i++) {
851 XenDeviceGrantCopySegment *seg = &segs[i];
852 void *page = map + (i * XC_PAGE_SIZE);
853
854 if (to_domain) {
855 memcpy(page + seg->dest.foreign.offset, seg->source.virt,
856 seg->len);
857 } else {
858 memcpy(seg->dest.virt, page + seg->source.foreign.offset,
859 seg->len);
860 }
861 }
862
863 if (xengnttab_unmap(xendev->xgth, map, nr_segs)) {
864 error_setg_errno(errp, errno, "xengnttab_unmap failed");
865 }
866
867done:
868 g_free(refs);
869}
870
871void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain,
872 XenDeviceGrantCopySegment segs[],
873 unsigned int nr_segs, Error **errp)
874{
875 xengnttab_grant_copy_segment_t *xengnttab_segs;
876 unsigned int i;
877
878 if (!xendev->feature_grant_copy) {
879 compat_copy_grant_refs(xendev, to_domain, segs, nr_segs, errp);
880 return;
881 }
882
883 xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
884
885 for (i = 0; i < nr_segs; i++) {
886 XenDeviceGrantCopySegment *seg = &segs[i];
887 xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
888
889 if (to_domain) {
890 xengnttab_seg->flags = GNTCOPY_dest_gref;
891 xengnttab_seg->dest.foreign.domid = xendev->frontend_id;
892 xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
893 xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
894 xengnttab_seg->source.virt = seg->source.virt;
895 } else {
896 xengnttab_seg->flags = GNTCOPY_source_gref;
897 xengnttab_seg->source.foreign.domid = xendev->frontend_id;
898 xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
899 xengnttab_seg->source.foreign.offset =
900 seg->source.foreign.offset;
901 xengnttab_seg->dest.virt = seg->dest.virt;
902 }
903
904 xengnttab_seg->len = seg->len;
905 }
906
907 if (xengnttab_grant_copy(xendev->xgth, nr_segs, xengnttab_segs)) {
908 error_setg_errno(errp, errno, "xengnttab_grant_copy failed");
909 goto done;
910 }
911
912 for (i = 0; i < nr_segs; i++) {
913 xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
914
915 if (xengnttab_seg->status != GNTST_okay) {
916 error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i);
917 break;
918 }
919 }
920
921done:
922 g_free(xengnttab_segs);
923}
924
a3d669c8
PD
925struct XenEventChannel {
926 evtchn_port_t local_port;
927 XenEventHandler handler;
928 void *opaque;
929 Notifier notifier;
930};
931
932static void event_notify(Notifier *n, void *data)
933{
934 XenEventChannel *channel = container_of(n, XenEventChannel, notifier);
935 unsigned long port = (unsigned long)data;
936
937 if (port == channel->local_port) {
938 channel->handler(channel->opaque);
939 }
940}
941
942XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
943 unsigned int port,
944 XenEventHandler handler,
945 void *opaque, Error **errp)
946{
947 XenEventChannel *channel = g_new0(XenEventChannel, 1);
948 xenevtchn_port_or_error_t local_port;
949
950 local_port = xenevtchn_bind_interdomain(xendev->xeh,
951 xendev->frontend_id,
952 port);
953 if (local_port < 0) {
954 error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
955
956 g_free(channel);
957 return NULL;
958 }
959
960 channel->local_port = local_port;
961 channel->handler = handler;
962 channel->opaque = opaque;
963 channel->notifier.notify = event_notify;
964
965 notifier_list_add(&xendev->event_notifiers, &channel->notifier);
966
967 return channel;
968}
969
970void xen_device_notify_event_channel(XenDevice *xendev,
971 XenEventChannel *channel,
972 Error **errp)
973{
974 if (!channel) {
975 error_setg(errp, "bad channel");
976 return;
977 }
978
979 if (xenevtchn_notify(xendev->xeh, channel->local_port) < 0) {
980 error_setg_errno(errp, errno, "xenevtchn_notify failed");
981 }
982}
983
984void xen_device_unbind_event_channel(XenDevice *xendev,
985 XenEventChannel *channel,
986 Error **errp)
987{
988 if (!channel) {
989 error_setg(errp, "bad channel");
990 return;
991 }
992
993 notifier_remove(&channel->notifier);
994
995 if (xenevtchn_unbind(xendev->xeh, channel->local_port) < 0) {
996 error_setg_errno(errp, errno, "xenevtchn_unbind failed");
997 }
998
999 g_free(channel);
1000}
1001
108f7bba
PD
1002static void xen_device_unrealize(DeviceState *dev, Error **errp)
1003{
1004 XenDevice *xendev = XEN_DEVICE(dev);
1005 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1006 const char *type = object_get_typename(OBJECT(xendev));
1007
094a2239
PD
1008 if (!xendev->name) {
1009 return;
1010 }
1011
1012 trace_xen_device_unrealize(type, xendev->name);
1013
1014 if (xendev->exit.notify) {
1015 qemu_remove_exit_notifier(&xendev->exit);
1016 xendev->exit.notify = NULL;
1017 }
108f7bba
PD
1018
1019 if (xendev_class->unrealize) {
1020 xendev_class->unrealize(xendev, errp);
1021 }
094a2239
PD
1022
1023 xen_device_frontend_destroy(xendev);
1024 xen_device_backend_destroy(xendev);
1025
a3d669c8
PD
1026 if (xendev->xeh) {
1027 qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), NULL, NULL, NULL);
1028 xenevtchn_close(xendev->xeh);
1029 xendev->xeh = NULL;
1030 }
1031
4b34b5b1
PD
1032 if (xendev->xgth) {
1033 xengnttab_close(xendev->xgth);
1034 xendev->xgth = NULL;
1035 }
1036
094a2239
PD
1037 g_free(xendev->name);
1038 xendev->name = NULL;
1039}
1040
1041static void xen_device_exit(Notifier *n, void *data)
1042{
1043 XenDevice *xendev = container_of(n, XenDevice, exit);
1044
1045 xen_device_unrealize(DEVICE(xendev), &error_abort);
108f7bba
PD
1046}
1047
a3d669c8
PD
1048static void xen_device_event(void *opaque)
1049{
1050 XenDevice *xendev = opaque;
1051 unsigned long port = xenevtchn_pending(xendev->xeh);
1052
1053 notifier_list_notify(&xendev->event_notifiers, (void *)port);
1054
1055 xenevtchn_unmask(xendev->xeh, port);
1056}
1057
108f7bba
PD
1058static void xen_device_realize(DeviceState *dev, Error **errp)
1059{
1060 XenDevice *xendev = XEN_DEVICE(dev);
1061 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
094a2239 1062 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
108f7bba
PD
1063 const char *type = object_get_typename(OBJECT(xendev));
1064 Error *local_err = NULL;
1065
094a2239
PD
1066 if (xendev->frontend_id == DOMID_INVALID) {
1067 xendev->frontend_id = xen_domid;
1068 }
1069
1070 if (xendev->frontend_id >= DOMID_FIRST_RESERVED) {
1071 error_setg(errp, "invalid frontend-id");
1072 goto unrealize;
1073 }
1074
1075 if (!xendev_class->get_name) {
1076 error_setg(errp, "get_name method not implemented");
1077 goto unrealize;
1078 }
1079
1080 xendev->name = xendev_class->get_name(xendev, &local_err);
1081 if (local_err) {
1082 error_propagate_prepend(errp, local_err,
1083 "failed to get device name: ");
1084 goto unrealize;
1085 }
1086
1087 trace_xen_device_realize(type, xendev->name);
1088
4b34b5b1
PD
1089 xendev->xgth = xengnttab_open(NULL, 0);
1090 if (!xendev->xgth) {
1091 error_setg_errno(errp, errno, "failed xengnttab_open");
1092 goto unrealize;
1093 }
1094
1095 xendev->feature_grant_copy =
1096 (xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0);
1097
a3d669c8
PD
1098 xendev->xeh = xenevtchn_open(NULL, 0);
1099 if (!xendev->xeh) {
1100 error_setg_errno(errp, errno, "failed xenevtchn_open");
1101 goto unrealize;
1102 }
1103
1104 notifier_list_init(&xendev->event_notifiers);
1105 qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), xen_device_event, NULL,
1106 xendev);
1107
094a2239
PD
1108 xen_device_backend_create(xendev, &local_err);
1109 if (local_err) {
1110 error_propagate(errp, local_err);
1111 goto unrealize;
1112 }
1113
1114 xen_device_frontend_create(xendev, &local_err);
1115 if (local_err) {
1116 error_propagate(errp, local_err);
1117 goto unrealize;
1118 }
108f7bba
PD
1119
1120 if (xendev_class->realize) {
1121 xendev_class->realize(xendev, &local_err);
1122 if (local_err) {
1123 error_propagate(errp, local_err);
1124 goto unrealize;
1125 }
1126 }
1127
094a2239
PD
1128 xen_device_backend_printf(xendev, "frontend", "%s",
1129 xendev->frontend_path);
1130 xen_device_backend_printf(xendev, "frontend-id", "%u",
1131 xendev->frontend_id);
094a2239
PD
1132 xen_device_backend_printf(xendev, "hotplug-status", "connected");
1133
b6af8926 1134 xen_device_backend_set_online(xendev, true);
094a2239
PD
1135 xen_device_backend_set_state(xendev, XenbusStateInitWait);
1136
1137 xen_device_frontend_printf(xendev, "backend", "%s",
1138 xendev->backend_path);
1139 xen_device_frontend_printf(xendev, "backend-id", "%u",
1140 xenbus->backend_id);
1141
1142 xen_device_frontend_set_state(xendev, XenbusStateInitialising);
1143
1144 xendev->exit.notify = xen_device_exit;
1145 qemu_add_exit_notifier(&xendev->exit);
108f7bba
PD
1146 return;
1147
1148unrealize:
1149 xen_device_unrealize(dev, &error_abort);
1150}
1151
094a2239
PD
1152static Property xen_device_props[] = {
1153 DEFINE_PROP_UINT16("frontend-id", XenDevice, frontend_id,
1154 DOMID_INVALID),
1155 DEFINE_PROP_END_OF_LIST()
1156};
1157
108f7bba
PD
1158static void xen_device_class_init(ObjectClass *class, void *data)
1159{
1160 DeviceClass *dev_class = DEVICE_CLASS(class);
1161
1162 dev_class->realize = xen_device_realize;
1163 dev_class->unrealize = xen_device_unrealize;
094a2239 1164 dev_class->props = xen_device_props;
108f7bba
PD
1165 dev_class->bus_type = TYPE_XEN_BUS;
1166}
1167
1168static const TypeInfo xen_device_type_info = {
1169 .name = TYPE_XEN_DEVICE,
1170 .parent = TYPE_DEVICE,
1171 .instance_size = sizeof(XenDevice),
1172 .abstract = true,
1173 .class_size = sizeof(XenDeviceClass),
1174 .class_init = xen_device_class_init,
1175};
1176
1177typedef struct XenBridge {
1178 SysBusDevice busdev;
1179} XenBridge;
1180
1181#define TYPE_XEN_BRIDGE "xen-bridge"
1182
1183static const TypeInfo xen_bridge_type_info = {
1184 .name = TYPE_XEN_BRIDGE,
1185 .parent = TYPE_SYS_BUS_DEVICE,
1186 .instance_size = sizeof(XenBridge),
1187};
1188
1189static void xen_register_types(void)
1190{
1191 type_register_static(&xen_bridge_type_info);
1192 type_register_static(&xen_bus_type_info);
1193 type_register_static(&xen_device_type_info);
1194}
1195
1196type_init(xen_register_types)
1197
1198void xen_bus_init(void)
1199{
1200 DeviceState *dev = qdev_create(NULL, TYPE_XEN_BRIDGE);
1201 BusState *bus = qbus_create(TYPE_XEN_BUS, dev, NULL);
1202
1203 qdev_init_nofail(dev);
1204 qbus_set_bus_hotplug_handler(bus, &error_abort);
1205}