]> git.proxmox.com Git - mirror_qemu.git/blame - hw/xen/xen-bus.c
xen: purge 'blk' and 'ioreq' from function names in dataplane/xen-block.c
[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"
108f7bba 14#include "hw/xen/xen-bus.h"
094a2239
PD
15#include "hw/xen/xen-bus-helper.h"
16#include "monitor/monitor.h"
108f7bba 17#include "qapi/error.h"
094a2239 18#include "sysemu/sysemu.h"
108f7bba
PD
19#include "trace.h"
20
094a2239
PD
21static char *xen_device_get_backend_path(XenDevice *xendev)
22{
23 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
24 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
25 const char *type = object_get_typename(OBJECT(xendev));
26 const char *backend = xendev_class->backend;
27
28 if (!backend) {
29 backend = type;
30 }
31
32 return g_strdup_printf("/local/domain/%u/backend/%s/%u/%s",
33 xenbus->backend_id, backend, xendev->frontend_id,
34 xendev->name);
35}
36
37static char *xen_device_get_frontend_path(XenDevice *xendev)
38{
39 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
40 const char *type = object_get_typename(OBJECT(xendev));
41 const char *device = xendev_class->device;
42
43 if (!device) {
44 device = type;
45 }
46
47 return g_strdup_printf("/local/domain/%u/device/%s/%s",
48 xendev->frontend_id, device, xendev->name);
49}
50
51static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent)
52{
53 XenDevice *xendev = XEN_DEVICE(dev);
54
55 monitor_printf(mon, "%*sname = '%s' frontend_id = %u\n",
56 indent, "", xendev->name, xendev->frontend_id);
57}
58
59static char *xen_bus_get_dev_path(DeviceState *dev)
60{
61 return xen_device_get_backend_path(XEN_DEVICE(dev));
62}
63
82a29e30
PD
64struct XenWatch {
65 char *node, *key;
66 char *token;
67 XenWatchHandler handler;
68 void *opaque;
69 Notifier notifier;
70};
71
72static void watch_notify(Notifier *n, void *data)
73{
74 XenWatch *watch = container_of(n, XenWatch, notifier);
75 const char *token = data;
76
77 if (!strcmp(watch->token, token)) {
78 watch->handler(watch->opaque);
79 }
80}
81
82static XenWatch *new_watch(const char *node, const char *key,
83 XenWatchHandler handler, void *opaque)
84{
85 XenWatch *watch = g_new0(XenWatch, 1);
86 QemuUUID uuid;
87
88 qemu_uuid_generate(&uuid);
89
90 watch->token = qemu_uuid_unparse_strdup(&uuid);
91 watch->node = g_strdup(node);
92 watch->key = g_strdup(key);
93 watch->handler = handler;
94 watch->opaque = opaque;
95 watch->notifier.notify = watch_notify;
96
97 return watch;
98}
99
100static void free_watch(XenWatch *watch)
101{
102 g_free(watch->token);
103 g_free(watch->key);
104 g_free(watch->node);
105
106 g_free(watch);
107}
108
109static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
110 const char *key, XenWatchHandler handler,
111 void *opaque, Error **errp)
112{
113 XenWatch *watch = new_watch(node, key, handler, opaque);
114 Error *local_err = NULL;
115
116 trace_xen_bus_add_watch(watch->node, watch->key, watch->token);
117
118 notifier_list_add(&xenbus->watch_notifiers, &watch->notifier);
119
120 xs_node_watch(xenbus->xsh, node, key, watch->token, &local_err);
121 if (local_err) {
122 error_propagate(errp, local_err);
123
124 notifier_remove(&watch->notifier);
125 free_watch(watch);
126
127 return NULL;
128 }
129
130 return watch;
131}
132
133static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch,
134 Error **errp)
135{
136 trace_xen_bus_remove_watch(watch->node, watch->key, watch->token);
137
138 xs_node_unwatch(xenbus->xsh, watch->node, watch->key, watch->token,
139 errp);
140
141 notifier_remove(&watch->notifier);
142 free_watch(watch);
143}
144
108f7bba
PD
145static void xen_bus_unrealize(BusState *bus, Error **errp)
146{
094a2239
PD
147 XenBus *xenbus = XEN_BUS(bus);
148
108f7bba 149 trace_xen_bus_unrealize();
094a2239
PD
150
151 if (!xenbus->xsh) {
152 return;
153 }
154
82a29e30
PD
155 qemu_set_fd_handler(xs_fileno(xenbus->xsh), NULL, NULL, NULL);
156
094a2239 157 xs_close(xenbus->xsh);
108f7bba
PD
158}
159
82a29e30
PD
160static void xen_bus_watch(void *opaque)
161{
162 XenBus *xenbus = opaque;
163 char **v;
164 const char *token;
165
166 g_assert(xenbus->xsh);
167
168 v = xs_check_watch(xenbus->xsh);
169 if (!v) {
170 return;
171 }
172
173 token = v[XS_WATCH_TOKEN];
174
175 trace_xen_bus_watch(token);
176
177 notifier_list_notify(&xenbus->watch_notifiers, (void *)token);
178
179 free(v);
180}
181
108f7bba
PD
182static void xen_bus_realize(BusState *bus, Error **errp)
183{
094a2239
PD
184 XenBus *xenbus = XEN_BUS(bus);
185 unsigned int domid;
186
108f7bba 187 trace_xen_bus_realize();
094a2239
PD
188
189 xenbus->xsh = xs_open(0);
190 if (!xenbus->xsh) {
191 error_setg_errno(errp, errno, "failed xs_open");
192 goto fail;
193 }
194
195 if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */
196 "domid", NULL, "%u", &domid) == 1) {
197 xenbus->backend_id = domid;
198 } else {
199 xenbus->backend_id = 0; /* Assume lack of node means dom0 */
200 }
201
82a29e30
PD
202 notifier_list_init(&xenbus->watch_notifiers);
203 qemu_set_fd_handler(xs_fileno(xenbus->xsh), xen_bus_watch, NULL,
204 xenbus);
094a2239
PD
205 return;
206
207fail:
208 xen_bus_unrealize(bus, &error_abort);
108f7bba
PD
209}
210
211static void xen_bus_class_init(ObjectClass *class, void *data)
212{
213 BusClass *bus_class = BUS_CLASS(class);
214
094a2239
PD
215 bus_class->print_dev = xen_bus_print_dev;
216 bus_class->get_dev_path = xen_bus_get_dev_path;
108f7bba
PD
217 bus_class->realize = xen_bus_realize;
218 bus_class->unrealize = xen_bus_unrealize;
219}
220
221static const TypeInfo xen_bus_type_info = {
222 .name = TYPE_XEN_BUS,
223 .parent = TYPE_BUS,
224 .instance_size = sizeof(XenBus),
225 .class_size = sizeof(XenBusClass),
226 .class_init = xen_bus_class_init,
227 .interfaces = (InterfaceInfo[]) {
228 { TYPE_HOTPLUG_HANDLER },
229 { }
230 },
231};
232
094a2239
PD
233static void xen_device_backend_printf(XenDevice *xendev, const char *key,
234 const char *fmt, ...)
235{
236 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
237 Error *local_err = NULL;
238 va_list ap;
239
240 g_assert(xenbus->xsh);
241
242 va_start(ap, fmt);
243 xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
244 &local_err, fmt, ap);
245 va_end(ap);
246
247 if (local_err) {
248 error_report_err(local_err);
249 }
250}
251
82a29e30
PD
252static int xen_device_backend_scanf(XenDevice *xendev, const char *key,
253 const char *fmt, ...)
254{
255 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
256 va_list ap;
257 int rc;
258
259 g_assert(xenbus->xsh);
260
261 va_start(ap, fmt);
262 rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
263 NULL, fmt, ap);
264 va_end(ap);
265
266 return rc;
267}
268
269void xen_device_backend_set_state(XenDevice *xendev,
270 enum xenbus_state state)
094a2239
PD
271{
272 const char *type = object_get_typename(OBJECT(xendev));
273
274 if (xendev->backend_state == state) {
275 return;
276 }
277
278 trace_xen_device_backend_state(type, xendev->name,
279 xs_strstate(state));
280
281 xendev->backend_state = state;
282 xen_device_backend_printf(xendev, "state", "%u", state);
283}
284
82a29e30
PD
285enum xenbus_state xen_device_backend_get_state(XenDevice *xendev)
286{
287 return xendev->backend_state;
288}
289
094a2239
PD
290static void xen_device_backend_create(XenDevice *xendev, Error **errp)
291{
292 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
293 struct xs_permissions perms[2];
294 Error *local_err = NULL;
295
296 xendev->backend_path = xen_device_get_backend_path(xendev);
297
298 perms[0].id = xenbus->backend_id;
299 perms[0].perms = XS_PERM_NONE;
300 perms[1].id = xendev->frontend_id;
301 perms[1].perms = XS_PERM_READ;
302
303 g_assert(xenbus->xsh);
304
305 xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path, perms,
306 ARRAY_SIZE(perms), &local_err);
307 if (local_err) {
308 error_propagate_prepend(errp, local_err,
309 "failed to create backend: ");
310 }
311}
312
313static void xen_device_backend_destroy(XenDevice *xendev)
314{
315 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
316 Error *local_err = NULL;
317
318 if (!xendev->backend_path) {
319 return;
320 }
321
322 g_assert(xenbus->xsh);
323
324 xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->backend_path,
325 &local_err);
326 g_free(xendev->backend_path);
327 xendev->backend_path = NULL;
328
329 if (local_err) {
330 error_report_err(local_err);
331 }
332}
333
334static void xen_device_frontend_printf(XenDevice *xendev, const char *key,
335 const char *fmt, ...)
336{
337 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
338 Error *local_err = NULL;
339 va_list ap;
340
341 g_assert(xenbus->xsh);
342
343 va_start(ap, fmt);
344 xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
345 &local_err, fmt, ap);
346 va_end(ap);
347
348 if (local_err) {
349 error_report_err(local_err);
350 }
351}
352
82a29e30
PD
353static int xen_device_frontend_scanf(XenDevice *xendev, const char *key,
354 const char *fmt, ...)
355{
356 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
357 va_list ap;
358 int rc;
359
360 g_assert(xenbus->xsh);
361
362 va_start(ap, fmt);
363 rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
364 NULL, fmt, ap);
365 va_end(ap);
366
367 return rc;
368}
369
094a2239
PD
370static void xen_device_frontend_set_state(XenDevice *xendev,
371 enum xenbus_state state)
372{
373 const char *type = object_get_typename(OBJECT(xendev));
374
375 if (xendev->frontend_state == state) {
376 return;
377 }
378
379 trace_xen_device_frontend_state(type, xendev->name,
380 xs_strstate(state));
381
382 xendev->frontend_state = state;
383 xen_device_frontend_printf(xendev, "state", "%u", state);
384}
385
82a29e30
PD
386static void xen_device_frontend_changed(void *opaque)
387{
388 XenDevice *xendev = opaque;
389 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
390 const char *type = object_get_typename(OBJECT(xendev));
391 enum xenbus_state state;
392
393 trace_xen_device_frontend_changed(type, xendev->name);
394
395 if (xen_device_frontend_scanf(xendev, "state", "%u", &state) != 1) {
396 state = XenbusStateUnknown;
397 }
398
399 xen_device_frontend_set_state(xendev, state);
400
401 if (xendev_class->frontend_changed) {
402 Error *local_err = NULL;
403
404 xendev_class->frontend_changed(xendev, state, &local_err);
405
406 if (local_err) {
407 error_reportf_err(local_err, "frontend change error: ");
408 }
409 }
410
411 /*
412 * If a backend is still 'online' then its state should be cycled
413 * back round to InitWait in order for a new frontend instance to
414 * connect. This may happen when, for example, a frontend driver is
415 * re-installed or updated.
416 */
417 if (xendev->backend_state == XenbusStateClosed) {
418 unsigned int online;
419
420 if (xen_device_backend_scanf(xendev, "online", "%u", &online) != 1) {
421 online = 0;
422 }
423
424 if (online) {
425 xen_device_backend_set_state(xendev, XenbusStateInitWait);
426 }
427 }
428}
429
094a2239
PD
430static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
431{
432 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
433 struct xs_permissions perms[2];
434 Error *local_err = NULL;
435
436 xendev->frontend_path = xen_device_get_frontend_path(xendev);
437
438 perms[0].id = xendev->frontend_id;
439 perms[0].perms = XS_PERM_NONE;
440 perms[1].id = xenbus->backend_id;
441 perms[1].perms = XS_PERM_READ | XS_PERM_WRITE;
442
443 g_assert(xenbus->xsh);
444
445 xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms,
446 ARRAY_SIZE(perms), &local_err);
447 if (local_err) {
448 error_propagate_prepend(errp, local_err,
449 "failed to create frontend: ");
82a29e30
PD
450 return;
451 }
452
453 xendev->frontend_state_watch =
454 xen_bus_add_watch(xenbus, xendev->frontend_path, "state",
455 xen_device_frontend_changed, xendev, &local_err);
456 if (local_err) {
457 error_propagate_prepend(errp, local_err,
458 "failed to watch frontend state: ");
094a2239
PD
459 }
460}
461
462static void xen_device_frontend_destroy(XenDevice *xendev)
463{
464 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
465 Error *local_err = NULL;
466
82a29e30
PD
467 if (xendev->frontend_state_watch) {
468 xen_bus_remove_watch(xenbus, xendev->frontend_state_watch, NULL);
469 xendev->frontend_state_watch = NULL;
470 }
471
094a2239
PD
472 if (!xendev->frontend_path) {
473 return;
474 }
475
476 g_assert(xenbus->xsh);
477
478 xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->frontend_path,
479 &local_err);
480 g_free(xendev->frontend_path);
481 xendev->frontend_path = NULL;
482
483 if (local_err) {
484 error_report_err(local_err);
485 }
486}
487
4b34b5b1
PD
488void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs,
489 Error **errp)
490{
491 if (xengnttab_set_max_grants(xendev->xgth, nr_refs)) {
492 error_setg_errno(errp, errno, "xengnttab_set_max_grants failed");
493 }
494}
495
496void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs,
497 unsigned int nr_refs, int prot,
498 Error **errp)
499{
500 void *map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_refs,
501 xendev->frontend_id, refs,
502 prot);
503
504 if (!map) {
505 error_setg_errno(errp, errno,
506 "xengnttab_map_domain_grant_refs failed");
507 }
508
509 return map;
510}
511
512void xen_device_unmap_grant_refs(XenDevice *xendev, void *map,
513 unsigned int nr_refs, Error **errp)
514{
515 if (xengnttab_unmap(xendev->xgth, map, nr_refs)) {
516 error_setg_errno(errp, errno, "xengnttab_unmap failed");
517 }
518}
519
520static void compat_copy_grant_refs(XenDevice *xendev, bool to_domain,
521 XenDeviceGrantCopySegment segs[],
522 unsigned int nr_segs, Error **errp)
523{
524 uint32_t *refs = g_new(uint32_t, nr_segs);
525 int prot = to_domain ? PROT_WRITE : PROT_READ;
526 void *map;
527 unsigned int i;
528
529 for (i = 0; i < nr_segs; i++) {
530 XenDeviceGrantCopySegment *seg = &segs[i];
531
532 refs[i] = to_domain ? seg->dest.foreign.ref :
533 seg->source.foreign.ref;
534 }
535
536 map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_segs,
537 xendev->frontend_id, refs,
538 prot);
539 if (!map) {
540 error_setg_errno(errp, errno,
541 "xengnttab_map_domain_grant_refs failed");
542 goto done;
543 }
544
545 for (i = 0; i < nr_segs; i++) {
546 XenDeviceGrantCopySegment *seg = &segs[i];
547 void *page = map + (i * XC_PAGE_SIZE);
548
549 if (to_domain) {
550 memcpy(page + seg->dest.foreign.offset, seg->source.virt,
551 seg->len);
552 } else {
553 memcpy(seg->dest.virt, page + seg->source.foreign.offset,
554 seg->len);
555 }
556 }
557
558 if (xengnttab_unmap(xendev->xgth, map, nr_segs)) {
559 error_setg_errno(errp, errno, "xengnttab_unmap failed");
560 }
561
562done:
563 g_free(refs);
564}
565
566void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain,
567 XenDeviceGrantCopySegment segs[],
568 unsigned int nr_segs, Error **errp)
569{
570 xengnttab_grant_copy_segment_t *xengnttab_segs;
571 unsigned int i;
572
573 if (!xendev->feature_grant_copy) {
574 compat_copy_grant_refs(xendev, to_domain, segs, nr_segs, errp);
575 return;
576 }
577
578 xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
579
580 for (i = 0; i < nr_segs; i++) {
581 XenDeviceGrantCopySegment *seg = &segs[i];
582 xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
583
584 if (to_domain) {
585 xengnttab_seg->flags = GNTCOPY_dest_gref;
586 xengnttab_seg->dest.foreign.domid = xendev->frontend_id;
587 xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
588 xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
589 xengnttab_seg->source.virt = seg->source.virt;
590 } else {
591 xengnttab_seg->flags = GNTCOPY_source_gref;
592 xengnttab_seg->source.foreign.domid = xendev->frontend_id;
593 xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
594 xengnttab_seg->source.foreign.offset =
595 seg->source.foreign.offset;
596 xengnttab_seg->dest.virt = seg->dest.virt;
597 }
598
599 xengnttab_seg->len = seg->len;
600 }
601
602 if (xengnttab_grant_copy(xendev->xgth, nr_segs, xengnttab_segs)) {
603 error_setg_errno(errp, errno, "xengnttab_grant_copy failed");
604 goto done;
605 }
606
607 for (i = 0; i < nr_segs; i++) {
608 xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
609
610 if (xengnttab_seg->status != GNTST_okay) {
611 error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i);
612 break;
613 }
614 }
615
616done:
617 g_free(xengnttab_segs);
618}
619
a3d669c8
PD
620struct XenEventChannel {
621 evtchn_port_t local_port;
622 XenEventHandler handler;
623 void *opaque;
624 Notifier notifier;
625};
626
627static void event_notify(Notifier *n, void *data)
628{
629 XenEventChannel *channel = container_of(n, XenEventChannel, notifier);
630 unsigned long port = (unsigned long)data;
631
632 if (port == channel->local_port) {
633 channel->handler(channel->opaque);
634 }
635}
636
637XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
638 unsigned int port,
639 XenEventHandler handler,
640 void *opaque, Error **errp)
641{
642 XenEventChannel *channel = g_new0(XenEventChannel, 1);
643 xenevtchn_port_or_error_t local_port;
644
645 local_port = xenevtchn_bind_interdomain(xendev->xeh,
646 xendev->frontend_id,
647 port);
648 if (local_port < 0) {
649 error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
650
651 g_free(channel);
652 return NULL;
653 }
654
655 channel->local_port = local_port;
656 channel->handler = handler;
657 channel->opaque = opaque;
658 channel->notifier.notify = event_notify;
659
660 notifier_list_add(&xendev->event_notifiers, &channel->notifier);
661
662 return channel;
663}
664
665void xen_device_notify_event_channel(XenDevice *xendev,
666 XenEventChannel *channel,
667 Error **errp)
668{
669 if (!channel) {
670 error_setg(errp, "bad channel");
671 return;
672 }
673
674 if (xenevtchn_notify(xendev->xeh, channel->local_port) < 0) {
675 error_setg_errno(errp, errno, "xenevtchn_notify failed");
676 }
677}
678
679void xen_device_unbind_event_channel(XenDevice *xendev,
680 XenEventChannel *channel,
681 Error **errp)
682{
683 if (!channel) {
684 error_setg(errp, "bad channel");
685 return;
686 }
687
688 notifier_remove(&channel->notifier);
689
690 if (xenevtchn_unbind(xendev->xeh, channel->local_port) < 0) {
691 error_setg_errno(errp, errno, "xenevtchn_unbind failed");
692 }
693
694 g_free(channel);
695}
696
108f7bba
PD
697static void xen_device_unrealize(DeviceState *dev, Error **errp)
698{
699 XenDevice *xendev = XEN_DEVICE(dev);
700 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
701 const char *type = object_get_typename(OBJECT(xendev));
702
094a2239
PD
703 if (!xendev->name) {
704 return;
705 }
706
707 trace_xen_device_unrealize(type, xendev->name);
708
709 if (xendev->exit.notify) {
710 qemu_remove_exit_notifier(&xendev->exit);
711 xendev->exit.notify = NULL;
712 }
108f7bba
PD
713
714 if (xendev_class->unrealize) {
715 xendev_class->unrealize(xendev, errp);
716 }
094a2239
PD
717
718 xen_device_frontend_destroy(xendev);
719 xen_device_backend_destroy(xendev);
720
a3d669c8
PD
721 if (xendev->xeh) {
722 qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), NULL, NULL, NULL);
723 xenevtchn_close(xendev->xeh);
724 xendev->xeh = NULL;
725 }
726
4b34b5b1
PD
727 if (xendev->xgth) {
728 xengnttab_close(xendev->xgth);
729 xendev->xgth = NULL;
730 }
731
094a2239
PD
732 g_free(xendev->name);
733 xendev->name = NULL;
734}
735
736static void xen_device_exit(Notifier *n, void *data)
737{
738 XenDevice *xendev = container_of(n, XenDevice, exit);
739
740 xen_device_unrealize(DEVICE(xendev), &error_abort);
108f7bba
PD
741}
742
a3d669c8
PD
743static void xen_device_event(void *opaque)
744{
745 XenDevice *xendev = opaque;
746 unsigned long port = xenevtchn_pending(xendev->xeh);
747
748 notifier_list_notify(&xendev->event_notifiers, (void *)port);
749
750 xenevtchn_unmask(xendev->xeh, port);
751}
752
108f7bba
PD
753static void xen_device_realize(DeviceState *dev, Error **errp)
754{
755 XenDevice *xendev = XEN_DEVICE(dev);
756 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
094a2239 757 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
108f7bba
PD
758 const char *type = object_get_typename(OBJECT(xendev));
759 Error *local_err = NULL;
760
094a2239
PD
761 if (xendev->frontend_id == DOMID_INVALID) {
762 xendev->frontend_id = xen_domid;
763 }
764
765 if (xendev->frontend_id >= DOMID_FIRST_RESERVED) {
766 error_setg(errp, "invalid frontend-id");
767 goto unrealize;
768 }
769
770 if (!xendev_class->get_name) {
771 error_setg(errp, "get_name method not implemented");
772 goto unrealize;
773 }
774
775 xendev->name = xendev_class->get_name(xendev, &local_err);
776 if (local_err) {
777 error_propagate_prepend(errp, local_err,
778 "failed to get device name: ");
779 goto unrealize;
780 }
781
782 trace_xen_device_realize(type, xendev->name);
783
4b34b5b1
PD
784 xendev->xgth = xengnttab_open(NULL, 0);
785 if (!xendev->xgth) {
786 error_setg_errno(errp, errno, "failed xengnttab_open");
787 goto unrealize;
788 }
789
790 xendev->feature_grant_copy =
791 (xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0);
792
a3d669c8
PD
793 xendev->xeh = xenevtchn_open(NULL, 0);
794 if (!xendev->xeh) {
795 error_setg_errno(errp, errno, "failed xenevtchn_open");
796 goto unrealize;
797 }
798
799 notifier_list_init(&xendev->event_notifiers);
800 qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), xen_device_event, NULL,
801 xendev);
802
094a2239
PD
803 xen_device_backend_create(xendev, &local_err);
804 if (local_err) {
805 error_propagate(errp, local_err);
806 goto unrealize;
807 }
808
809 xen_device_frontend_create(xendev, &local_err);
810 if (local_err) {
811 error_propagate(errp, local_err);
812 goto unrealize;
813 }
108f7bba
PD
814
815 if (xendev_class->realize) {
816 xendev_class->realize(xendev, &local_err);
817 if (local_err) {
818 error_propagate(errp, local_err);
819 goto unrealize;
820 }
821 }
822
094a2239
PD
823 xen_device_backend_printf(xendev, "frontend", "%s",
824 xendev->frontend_path);
825 xen_device_backend_printf(xendev, "frontend-id", "%u",
826 xendev->frontend_id);
827 xen_device_backend_printf(xendev, "online", "%u", 1);
828 xen_device_backend_printf(xendev, "hotplug-status", "connected");
829
830 xen_device_backend_set_state(xendev, XenbusStateInitWait);
831
832 xen_device_frontend_printf(xendev, "backend", "%s",
833 xendev->backend_path);
834 xen_device_frontend_printf(xendev, "backend-id", "%u",
835 xenbus->backend_id);
836
837 xen_device_frontend_set_state(xendev, XenbusStateInitialising);
838
839 xendev->exit.notify = xen_device_exit;
840 qemu_add_exit_notifier(&xendev->exit);
108f7bba
PD
841 return;
842
843unrealize:
844 xen_device_unrealize(dev, &error_abort);
845}
846
094a2239
PD
847static Property xen_device_props[] = {
848 DEFINE_PROP_UINT16("frontend-id", XenDevice, frontend_id,
849 DOMID_INVALID),
850 DEFINE_PROP_END_OF_LIST()
851};
852
108f7bba
PD
853static void xen_device_class_init(ObjectClass *class, void *data)
854{
855 DeviceClass *dev_class = DEVICE_CLASS(class);
856
857 dev_class->realize = xen_device_realize;
858 dev_class->unrealize = xen_device_unrealize;
094a2239 859 dev_class->props = xen_device_props;
108f7bba
PD
860 dev_class->bus_type = TYPE_XEN_BUS;
861}
862
863static const TypeInfo xen_device_type_info = {
864 .name = TYPE_XEN_DEVICE,
865 .parent = TYPE_DEVICE,
866 .instance_size = sizeof(XenDevice),
867 .abstract = true,
868 .class_size = sizeof(XenDeviceClass),
869 .class_init = xen_device_class_init,
870};
871
872typedef struct XenBridge {
873 SysBusDevice busdev;
874} XenBridge;
875
876#define TYPE_XEN_BRIDGE "xen-bridge"
877
878static const TypeInfo xen_bridge_type_info = {
879 .name = TYPE_XEN_BRIDGE,
880 .parent = TYPE_SYS_BUS_DEVICE,
881 .instance_size = sizeof(XenBridge),
882};
883
884static void xen_register_types(void)
885{
886 type_register_static(&xen_bridge_type_info);
887 type_register_static(&xen_bus_type_info);
888 type_register_static(&xen_device_type_info);
889}
890
891type_init(xen_register_types)
892
893void xen_bus_init(void)
894{
895 DeviceState *dev = qdev_create(NULL, TYPE_XEN_BRIDGE);
896 BusState *bus = qbus_create(TYPE_XEN_BUS, dev, NULL);
897
898 qdev_init_nofail(dev);
899 qbus_set_bus_hotplug_handler(bus, &error_abort);
900}