1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#include "qemu/osdep.h"
29#include "qapi/error.h"
30#include "qapi/qapi-events-qdev.h"
31#include "qapi/qmp/qdict.h"
32#include "qapi/qmp/qerror.h"
33#include "qapi/visitor.h"
34#include "qemu/error-report.h"
35#include "qemu/option.h"
36#include "hw/irq.h"
37#include "hw/qdev-properties.h"
38#include "hw/boards.h"
39#include "hw/sysbus.h"
40#include "hw/qdev-clock.h"
41#include "migration/vmstate.h"
42#include "trace.h"
43
44static bool qdev_hot_added = false;
45bool qdev_hot_removed = false;
46
47const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
48{
49 DeviceClass *dc = DEVICE_GET_CLASS(dev);
50 return dc->vmsd;
51}
52
53static void bus_free_bus_child(BusChild *kid)
54{
55 object_unref(OBJECT(kid->child));
56 g_free(kid);
57}
58
59static void bus_remove_child(BusState *bus, DeviceState *child)
60{
61 BusChild *kid;
62
63 QTAILQ_FOREACH(kid, &bus->children, sibling) {
64 if (kid->child == child) {
65 char name[32];
66
67 snprintf(name, sizeof(name), "child[%d]", kid->index);
68 QTAILQ_REMOVE_RCU(&bus->children, kid, sibling);
69
70 bus->num_children--;
71
72
73 object_property_del(OBJECT(bus), name);
74
75
76 call_rcu(kid, bus_free_bus_child, rcu);
77 break;
78 }
79 }
80}
81
82static void bus_add_child(BusState *bus, DeviceState *child)
83{
84 char name[32];
85 BusChild *kid = g_malloc0(sizeof(*kid));
86
87 bus->num_children++;
88 kid->index = bus->max_index++;
89 kid->child = child;
90 object_ref(OBJECT(kid->child));
91
92 QTAILQ_INSERT_HEAD_RCU(&bus->children, kid, sibling);
93
94
95 snprintf(name, sizeof(name), "child[%d]", kid->index);
96 object_property_add_link(OBJECT(bus), name,
97 object_get_typename(OBJECT(child)),
98 (Object **)&kid->child,
99 NULL,
100 0);
101}
102
103static bool bus_check_address(BusState *bus, DeviceState *child, Error **errp)
104{
105 BusClass *bc = BUS_GET_CLASS(bus);
106 return !bc->check_address || bc->check_address(bus, child, errp);
107}
108
109bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp)
110{
111 BusState *old_parent_bus = dev->parent_bus;
112 DeviceClass *dc = DEVICE_GET_CLASS(dev);
113
114 assert(dc->bus_type && object_dynamic_cast(OBJECT(bus), dc->bus_type));
115
116 if (!bus_check_address(bus, dev, errp)) {
117 return false;
118 }
119
120 if (old_parent_bus) {
121 trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)),
122 old_parent_bus, object_get_typename(OBJECT(old_parent_bus)),
123 OBJECT(bus), object_get_typename(OBJECT(bus)));
124
125
126
127
128
129
130
131 object_ref(OBJECT(dev));
132 bus_remove_child(dev->parent_bus, dev);
133 }
134 dev->parent_bus = bus;
135 object_ref(OBJECT(bus));
136 bus_add_child(bus, dev);
137 if (dev->realized) {
138 resettable_change_parent(OBJECT(dev), OBJECT(bus),
139 OBJECT(old_parent_bus));
140 }
141 if (old_parent_bus) {
142 object_unref(OBJECT(old_parent_bus));
143 object_unref(OBJECT(dev));
144 }
145 return true;
146}
147
148DeviceState *qdev_new(const char *name)
149{
150 if (!object_class_by_name(name)) {
151 module_load_qom_one(name);
152 }
153 return DEVICE(object_new(name));
154}
155
156DeviceState *qdev_try_new(const char *name)
157{
158 if (!module_object_class_by_name(name)) {
159 return NULL;
160 }
161 return DEVICE(object_new(name));
162}
163
164static QTAILQ_HEAD(, DeviceListener) device_listeners
165 = QTAILQ_HEAD_INITIALIZER(device_listeners);
166
167enum ListenerDirection { Forward, Reverse };
168
169#define DEVICE_LISTENER_CALL(_callback, _direction, _args...) \
170 do { \
171 DeviceListener *_listener; \
172 \
173 switch (_direction) { \
174 case Forward: \
175 QTAILQ_FOREACH(_listener, &device_listeners, link) { \
176 if (_listener->_callback) { \
177 _listener->_callback(_listener, ##_args); \
178 } \
179 } \
180 break; \
181 case Reverse: \
182 QTAILQ_FOREACH_REVERSE(_listener, &device_listeners, \
183 link) { \
184 if (_listener->_callback) { \
185 _listener->_callback(_listener, ##_args); \
186 } \
187 } \
188 break; \
189 default: \
190 abort(); \
191 } \
192 } while (0)
193
194static int device_listener_add(DeviceState *dev, void *opaque)
195{
196 DEVICE_LISTENER_CALL(realize, Forward, dev);
197
198 return 0;
199}
200
201void device_listener_register(DeviceListener *listener)
202{
203 QTAILQ_INSERT_TAIL(&device_listeners, listener, link);
204
205 qbus_walk_children(sysbus_get_default(), NULL, NULL, device_listener_add,
206 NULL, NULL);
207}
208
209void device_listener_unregister(DeviceListener *listener)
210{
211 QTAILQ_REMOVE(&device_listeners, listener, link);
212}
213
214bool qdev_should_hide_device(const QDict *opts, bool from_json, Error **errp)
215{
216 ERRP_GUARD();
217 DeviceListener *listener;
218
219 QTAILQ_FOREACH(listener, &device_listeners, link) {
220 if (listener->hide_device) {
221 if (listener->hide_device(listener, opts, from_json, errp)) {
222 return true;
223 } else if (*errp) {
224 return false;
225 }
226 }
227 }
228
229 return false;
230}
231
232void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
233 int required_for_version)
234{
235 assert(!dev->realized);
236 dev->instance_id_alias = alias_id;
237 dev->alias_required_for_version = required_for_version;
238}
239
240static int qdev_prereset(DeviceState *dev, void *opaque)
241{
242 trace_qdev_reset_tree(dev, object_get_typename(OBJECT(dev)));
243 return 0;
244}
245
246static int qbus_prereset(BusState *bus, void *opaque)
247{
248 trace_qbus_reset_tree(bus, object_get_typename(OBJECT(bus)));
249 return 0;
250}
251
252static int qdev_reset_one(DeviceState *dev, void *opaque)
253{
254 device_legacy_reset(dev);
255
256 return 0;
257}
258
259static int qbus_reset_one(BusState *bus, void *opaque)
260{
261 BusClass *bc = BUS_GET_CLASS(bus);
262 trace_qbus_reset(bus, object_get_typename(OBJECT(bus)));
263 if (bc->reset) {
264 bc->reset(bus);
265 }
266 return 0;
267}
268
269void qdev_reset_all(DeviceState *dev)
270{
271 trace_qdev_reset_all(dev, object_get_typename(OBJECT(dev)));
272 qdev_walk_children(dev, qdev_prereset, qbus_prereset,
273 qdev_reset_one, qbus_reset_one, NULL);
274}
275
276void qdev_reset_all_fn(void *opaque)
277{
278 qdev_reset_all(DEVICE(opaque));
279}
280
281void qbus_reset_all(BusState *bus)
282{
283 trace_qbus_reset_all(bus, object_get_typename(OBJECT(bus)));
284 qbus_walk_children(bus, qdev_prereset, qbus_prereset,
285 qdev_reset_one, qbus_reset_one, NULL);
286}
287
288void qbus_reset_all_fn(void *opaque)
289{
290 BusState *bus = opaque;
291 qbus_reset_all(bus);
292}
293
294void device_cold_reset(DeviceState *dev)
295{
296 resettable_reset(OBJECT(dev), RESET_TYPE_COLD);
297}
298
299bool device_is_in_reset(DeviceState *dev)
300{
301 return resettable_is_in_reset(OBJECT(dev));
302}
303
304static ResettableState *device_get_reset_state(Object *obj)
305{
306 DeviceState *dev = DEVICE(obj);
307 return &dev->reset;
308}
309
310static void device_reset_child_foreach(Object *obj, ResettableChildCallback cb,
311 void *opaque, ResetType type)
312{
313 DeviceState *dev = DEVICE(obj);
314 BusState *bus;
315
316 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
317 cb(OBJECT(bus), opaque, type);
318 }
319}
320
321bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp)
322{
323 assert(!dev->realized && !dev->parent_bus);
324
325 if (bus) {
326 if (!qdev_set_parent_bus(dev, bus, errp)) {
327 return false;
328 }
329 } else {
330 assert(!DEVICE_GET_CLASS(dev)->bus_type);
331 }
332
333 return object_property_set_bool(OBJECT(dev), "realized", true, errp);
334}
335
336bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp)
337{
338 bool ret;
339
340 ret = qdev_realize(dev, bus, errp);
341 object_unref(OBJECT(dev));
342 return ret;
343}
344
345void qdev_unrealize(DeviceState *dev)
346{
347 object_property_set_bool(OBJECT(dev), "realized", false, &error_abort);
348}
349
350static int qdev_assert_realized_properly_cb(Object *obj, void *opaque)
351{
352 DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE));
353 DeviceClass *dc;
354
355 if (dev) {
356 dc = DEVICE_GET_CLASS(dev);
357 assert(dev->realized);
358 assert(dev->parent_bus || !dc->bus_type);
359 }
360 return 0;
361}
362
363void qdev_assert_realized_properly(void)
364{
365 object_child_foreach_recursive(object_get_root(),
366 qdev_assert_realized_properly_cb, NULL);
367}
368
369bool qdev_machine_modified(void)
370{
371 return qdev_hot_added || qdev_hot_removed;
372}
373
374BusState *qdev_get_parent_bus(DeviceState *dev)
375{
376 return dev->parent_bus;
377}
378
379BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
380{
381 BusState *bus;
382 Object *child = object_resolve_path_component(OBJECT(dev), name);
383
384 bus = (BusState *)object_dynamic_cast(child, TYPE_BUS);
385 if (bus) {
386 return bus;
387 }
388
389 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
390 if (strcmp(name, bus->name) == 0) {
391 return bus;
392 }
393 }
394 return NULL;
395}
396
397int qdev_walk_children(DeviceState *dev,
398 qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
399 qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
400 void *opaque)
401{
402 BusState *bus;
403 int err;
404
405 if (pre_devfn) {
406 err = pre_devfn(dev, opaque);
407 if (err) {
408 return err;
409 }
410 }
411
412 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
413 err = qbus_walk_children(bus, pre_devfn, pre_busfn,
414 post_devfn, post_busfn, opaque);
415 if (err < 0) {
416 return err;
417 }
418 }
419
420 if (post_devfn) {
421 err = post_devfn(dev, opaque);
422 if (err) {
423 return err;
424 }
425 }
426
427 return 0;
428}
429
430DeviceState *qdev_find_recursive(BusState *bus, const char *id)
431{
432 BusChild *kid;
433 DeviceState *ret;
434 BusState *child;
435
436 WITH_RCU_READ_LOCK_GUARD() {
437 QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) {
438 DeviceState *dev = kid->child;
439
440 if (dev->id && strcmp(dev->id, id) == 0) {
441 return dev;
442 }
443
444 QLIST_FOREACH(child, &dev->child_bus, sibling) {
445 ret = qdev_find_recursive(child, id);
446 if (ret) {
447 return ret;
448 }
449 }
450 }
451 }
452 return NULL;
453}
454
455char *qdev_get_dev_path(DeviceState *dev)
456{
457 BusClass *bc;
458
459 if (!dev || !dev->parent_bus) {
460 return NULL;
461 }
462
463 bc = BUS_GET_CLASS(dev->parent_bus);
464 if (bc->get_dev_path) {
465 return bc->get_dev_path(dev);
466 }
467
468 return NULL;
469}
470
471static bool device_get_realized(Object *obj, Error **errp)
472{
473 DeviceState *dev = DEVICE(obj);
474 return dev->realized;
475}
476
477static bool check_only_migratable(Object *obj, Error **errp)
478{
479 DeviceClass *dc = DEVICE_GET_CLASS(obj);
480
481 if (!vmstate_check_only_migratable(dc->vmsd)) {
482 error_setg(errp, "Device %s is not migratable, but "
483 "--only-migratable was specified",
484 object_get_typename(obj));
485 return false;
486 }
487
488 return true;
489}
490
491static void device_set_realized(Object *obj, bool value, Error **errp)
492{
493 DeviceState *dev = DEVICE(obj);
494 DeviceClass *dc = DEVICE_GET_CLASS(dev);
495 HotplugHandler *hotplug_ctrl;
496 BusState *bus;
497 NamedClockList *ncl;
498 Error *local_err = NULL;
499 bool unattached_parent = false;
500 static int unattached_count;
501
502 if (dev->hotplugged && !dc->hotpluggable) {
503 error_setg(errp, QERR_DEVICE_NO_HOTPLUG, object_get_typename(obj));
504 return;
505 }
506
507 if (value && !dev->realized) {
508 if (!check_only_migratable(obj, errp)) {
509 goto fail;
510 }
511
512 if (!obj->parent) {
513 gchar *name = g_strdup_printf("device[%d]", unattached_count++);
514
515 object_property_add_child(container_get(qdev_get_machine(),
516 "/unattached"),
517 name, obj);
518 unattached_parent = true;
519 g_free(name);
520 }
521
522 hotplug_ctrl = qdev_get_hotplug_handler(dev);
523 if (hotplug_ctrl) {
524 hotplug_handler_pre_plug(hotplug_ctrl, dev, &local_err);
525 if (local_err != NULL) {
526 goto fail;
527 }
528 }
529
530 if (dc->realize) {
531 dc->realize(dev, &local_err);
532 if (local_err != NULL) {
533 goto fail;
534 }
535 }
536
537 DEVICE_LISTENER_CALL(realize, Forward, dev);
538
539
540
541
542
543 g_free(dev->canonical_path);
544 dev->canonical_path = object_get_canonical_path(OBJECT(dev));
545 QLIST_FOREACH(ncl, &dev->clocks, node) {
546 if (ncl->alias) {
547 continue;
548 } else {
549 clock_setup_canonical_path(ncl->clock);
550 }
551 }
552
553 if (qdev_get_vmsd(dev)) {
554 if (vmstate_register_with_alias_id(VMSTATE_IF(dev),
555 VMSTATE_INSTANCE_ID_ANY,
556 qdev_get_vmsd(dev), dev,
557 dev->instance_id_alias,
558 dev->alias_required_for_version,
559 &local_err) < 0) {
560 goto post_realize_fail;
561 }
562 }
563
564
565
566
567
568 resettable_state_clear(&dev->reset);
569
570 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
571 if (!qbus_realize(bus, errp)) {
572 goto child_realize_fail;
573 }
574 }
575 if (dev->hotplugged) {
576
577
578
579
580 resettable_assert_reset(OBJECT(dev), RESET_TYPE_COLD);
581 resettable_change_parent(OBJECT(dev), OBJECT(dev->parent_bus),
582 NULL);
583 resettable_release_reset(OBJECT(dev), RESET_TYPE_COLD);
584 }
585 dev->pending_deleted_event = false;
586
587 if (hotplug_ctrl) {
588 hotplug_handler_plug(hotplug_ctrl, dev, &local_err);
589 if (local_err != NULL) {
590 goto child_realize_fail;
591 }
592 }
593
594 qatomic_store_release(&dev->realized, value);
595
596 } else if (!value && dev->realized) {
597
598
599
600
601
602
603
604
605
606 qatomic_set(&dev->realized, value);
607
608
609
610
611 smp_wmb();
612
613 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
614 qbus_unrealize(bus);
615 }
616 if (qdev_get_vmsd(dev)) {
617 vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev);
618 }
619 if (dc->unrealize) {
620 dc->unrealize(dev);
621 }
622 dev->pending_deleted_event = true;
623 DEVICE_LISTENER_CALL(unrealize, Reverse, dev);
624 }
625
626 assert(local_err == NULL);
627 return;
628
629child_realize_fail:
630 QLIST_FOREACH(bus, &dev->child_bus, sibling) {
631 qbus_unrealize(bus);
632 }
633
634 if (qdev_get_vmsd(dev)) {
635 vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev);
636 }
637
638post_realize_fail:
639 g_free(dev->canonical_path);
640 dev->canonical_path = NULL;
641 if (dc->unrealize) {
642 dc->unrealize(dev);
643 }
644
645fail:
646 error_propagate(errp, local_err);
647 if (unattached_parent) {
648
649
650
651
652 object_unparent(OBJECT(dev));
653 unattached_count--;
654 }
655}
656
657static bool device_get_hotpluggable(Object *obj, Error **errp)
658{
659 DeviceClass *dc = DEVICE_GET_CLASS(obj);
660 DeviceState *dev = DEVICE(obj);
661
662 return dc->hotpluggable && (dev->parent_bus == NULL ||
663 qbus_is_hotpluggable(dev->parent_bus));
664}
665
666static bool device_get_hotplugged(Object *obj, Error **errp)
667{
668 DeviceState *dev = DEVICE(obj);
669
670 return dev->hotplugged;
671}
672
673static void device_initfn(Object *obj)
674{
675 DeviceState *dev = DEVICE(obj);
676
677 if (phase_check(PHASE_MACHINE_READY)) {
678 dev->hotplugged = 1;
679 qdev_hot_added = true;
680 }
681
682 dev->instance_id_alias = -1;
683 dev->realized = false;
684 dev->allow_unplug_during_migration = false;
685
686 QLIST_INIT(&dev->gpios);
687 QLIST_INIT(&dev->clocks);
688}
689
690static void device_post_init(Object *obj)
691{
692
693
694
695
696 object_apply_compat_props(obj);
697 qdev_prop_set_globals(DEVICE(obj));
698}
699
700
701static void device_finalize(Object *obj)
702{
703 NamedGPIOList *ngl, *next;
704
705 DeviceState *dev = DEVICE(obj);
706
707 QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) {
708 QLIST_REMOVE(ngl, node);
709 qemu_free_irqs(ngl->in, ngl->num_in);
710 g_free(ngl->name);
711 g_free(ngl);
712
713
714
715 }
716
717 qdev_finalize_clocklist(dev);
718
719
720 if (dev->pending_deleted_event) {
721 g_assert(dev->canonical_path);
722
723 qapi_event_send_device_deleted(!!dev->id, dev->id, dev->canonical_path);
724 g_free(dev->canonical_path);
725 dev->canonical_path = NULL;
726 }
727
728 qobject_unref(dev->opts);
729 g_free(dev->id);
730}
731
732static void device_class_base_init(ObjectClass *class, void *data)
733{
734 DeviceClass *klass = DEVICE_CLASS(class);
735
736
737
738
739 klass->props_ = NULL;
740}
741
742static void device_unparent(Object *obj)
743{
744 DeviceState *dev = DEVICE(obj);
745 BusState *bus;
746
747 if (dev->realized) {
748 qdev_unrealize(dev);
749 }
750 while (dev->num_child_bus) {
751 bus = QLIST_FIRST(&dev->child_bus);
752 object_unparent(OBJECT(bus));
753 }
754 if (dev->parent_bus) {
755 bus_remove_child(dev->parent_bus, dev);
756 object_unref(OBJECT(dev->parent_bus));
757 dev->parent_bus = NULL;
758 }
759}
760
761static char *
762device_vmstate_if_get_id(VMStateIf *obj)
763{
764 DeviceState *dev = DEVICE(obj);
765
766 return qdev_get_dev_path(dev);
767}
768
769
770
771
772
773
774static void device_phases_reset(DeviceState *dev)
775{
776 ResettableClass *rc = RESETTABLE_GET_CLASS(dev);
777
778 if (rc->phases.enter) {
779 rc->phases.enter(OBJECT(dev), RESET_TYPE_COLD);
780 }
781 if (rc->phases.hold) {
782 rc->phases.hold(OBJECT(dev));
783 }
784 if (rc->phases.exit) {
785 rc->phases.exit(OBJECT(dev));
786 }
787}
788
789static void device_transitional_reset(Object *obj)
790{
791 DeviceClass *dc = DEVICE_GET_CLASS(obj);
792
793
794
795
796
797
798 if (dc->reset) {
799 dc->reset(DEVICE(obj));
800 }
801}
802
803
804
805
806
807static ResettableTrFunction device_get_transitional_reset(Object *obj)
808{
809 DeviceClass *dc = DEVICE_GET_CLASS(obj);
810 if (dc->reset != device_phases_reset) {
811
812
813
814
815 return device_transitional_reset;
816 }
817 return NULL;
818}
819
820static void device_class_init(ObjectClass *class, void *data)
821{
822 DeviceClass *dc = DEVICE_CLASS(class);
823 VMStateIfClass *vc = VMSTATE_IF_CLASS(class);
824 ResettableClass *rc = RESETTABLE_CLASS(class);
825
826 class->unparent = device_unparent;
827
828
829
830
831
832
833
834 dc->hotpluggable = true;
835 dc->user_creatable = true;
836 vc->get_id = device_vmstate_if_get_id;
837 rc->get_state = device_get_reset_state;
838 rc->child_foreach = device_reset_child_foreach;
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853 dc->reset = device_phases_reset;
854 rc->get_transitional_function = device_get_transitional_reset;
855
856 object_class_property_add_bool(class, "realized",
857 device_get_realized, device_set_realized);
858 object_class_property_add_bool(class, "hotpluggable",
859 device_get_hotpluggable, NULL);
860 object_class_property_add_bool(class, "hotplugged",
861 device_get_hotplugged, NULL);
862 object_class_property_add_link(class, "parent_bus", TYPE_BUS,
863 offsetof(DeviceState, parent_bus), NULL, 0);
864}
865
866void device_class_set_parent_reset(DeviceClass *dc,
867 DeviceReset dev_reset,
868 DeviceReset *parent_reset)
869{
870 *parent_reset = dc->reset;
871 dc->reset = dev_reset;
872}
873
874void device_class_set_parent_realize(DeviceClass *dc,
875 DeviceRealize dev_realize,
876 DeviceRealize *parent_realize)
877{
878 *parent_realize = dc->realize;
879 dc->realize = dev_realize;
880}
881
882void device_class_set_parent_unrealize(DeviceClass *dc,
883 DeviceUnrealize dev_unrealize,
884 DeviceUnrealize *parent_unrealize)
885{
886 *parent_unrealize = dc->unrealize;
887 dc->unrealize = dev_unrealize;
888}
889
890void device_legacy_reset(DeviceState *dev)
891{
892 DeviceClass *klass = DEVICE_GET_CLASS(dev);
893
894 trace_qdev_reset(dev, object_get_typename(OBJECT(dev)));
895 if (klass->reset) {
896 klass->reset(dev);
897 }
898}
899
900Object *qdev_get_machine(void)
901{
902 static Object *dev;
903
904 if (dev == NULL) {
905 dev = container_get(object_get_root(), "/machine");
906 }
907
908 return dev;
909}
910
911static MachineInitPhase machine_phase;
912
913bool phase_check(MachineInitPhase phase)
914{
915 return machine_phase >= phase;
916}
917
918void phase_advance(MachineInitPhase phase)
919{
920 assert(machine_phase == phase - 1);
921 machine_phase = phase;
922}
923
924static const TypeInfo device_type_info = {
925 .name = TYPE_DEVICE,
926 .parent = TYPE_OBJECT,
927 .instance_size = sizeof(DeviceState),
928 .instance_init = device_initfn,
929 .instance_post_init = device_post_init,
930 .instance_finalize = device_finalize,
931 .class_base_init = device_class_base_init,
932 .class_init = device_class_init,
933 .abstract = true,
934 .class_size = sizeof(DeviceClass),
935 .interfaces = (InterfaceInfo[]) {
936 { TYPE_VMSTATE_IF },
937 { TYPE_RESETTABLE_INTERFACE },
938 { }
939 }
940};
941
942static void qdev_register_types(void)
943{
944 type_register_static(&device_type_info);
945}
946
947type_init(qdev_register_types)
948