xref: /openbmc/qemu/hw/core/qdev.c (revision c94bee4cd6693c1c65ba43bb8970cf909dec378b)
149ab747fSPaolo Bonzini /*
249ab747fSPaolo Bonzini  *  Dynamic device configuration and creation.
349ab747fSPaolo Bonzini  *
449ab747fSPaolo Bonzini  *  Copyright (c) 2009 CodeSourcery
549ab747fSPaolo Bonzini  *
649ab747fSPaolo Bonzini  * This library is free software; you can redistribute it and/or
749ab747fSPaolo Bonzini  * modify it under the terms of the GNU Lesser General Public
849ab747fSPaolo Bonzini  * License as published by the Free Software Foundation; either
961f3c91aSChetan Pant  * version 2.1 of the License, or (at your option) any later version.
1049ab747fSPaolo Bonzini  *
1149ab747fSPaolo Bonzini  * This library is distributed in the hope that it will be useful,
1249ab747fSPaolo Bonzini  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1349ab747fSPaolo Bonzini  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1449ab747fSPaolo Bonzini  * Lesser General Public License for more details.
1549ab747fSPaolo Bonzini  *
1649ab747fSPaolo Bonzini  * You should have received a copy of the GNU Lesser General Public
1749ab747fSPaolo Bonzini  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1849ab747fSPaolo Bonzini  */
1949ab747fSPaolo Bonzini 
2049ab747fSPaolo Bonzini /* The theory here is that it should be possible to create a machine without
2149ab747fSPaolo Bonzini    knowledge of specific devices.  Historically board init routines have
2249ab747fSPaolo Bonzini    passed a bunch of arguments to each device, requiring the board know
2349ab747fSPaolo Bonzini    exactly which device it is dealing with.  This file provides an abstract
2449ab747fSPaolo Bonzini    API for device configuration and initialization.  Devices will generally
2549ab747fSPaolo Bonzini    inherit from a particular bus (e.g. PCI or I2C) rather than
2649ab747fSPaolo Bonzini    this API directly.  */
2749ab747fSPaolo Bonzini 
2818c86e2bSPeter Maydell #include "qemu/osdep.h"
29e688df6bSMarkus Armbruster #include "qapi/error.h"
30c577ff62SMarkus Armbruster #include "qapi/qapi-events-qdev.h"
31f3558b1bSKevin Wolf #include "qapi/qmp/qdict.h"
3249ab747fSPaolo Bonzini #include "qapi/visitor.h"
33d49b6836SMarkus Armbruster #include "qemu/error-report.h"
34922a01a0SMarkus Armbruster #include "qemu/option.h"
3564552b6bSMarkus Armbruster #include "hw/irq.h"
36a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
37b7454548SIgor Mammedov #include "hw/boards.h"
387474f1beSPeter Maydell #include "hw/sysbus.h"
390e6934f2SDamien Hedde #include "hw/qdev-clock.h"
40d6454270SMarkus Armbruster #include "migration/vmstate.h"
4170804c83SDamien Hedde #include "trace.h"
4249ab747fSPaolo Bonzini 
4349ab747fSPaolo Bonzini static bool qdev_hot_added = false;
4421def24aSJuan Quintela bool qdev_hot_removed = false;
4549ab747fSPaolo Bonzini 
qdev_get_vmsd(DeviceState * dev)4649ab747fSPaolo Bonzini const VMStateDescription *qdev_get_vmsd(DeviceState *dev)
4749ab747fSPaolo Bonzini {
4849ab747fSPaolo Bonzini     DeviceClass *dc = DEVICE_GET_CLASS(dev);
4949ab747fSPaolo Bonzini     return dc->vmsd;
5049ab747fSPaolo Bonzini }
5149ab747fSPaolo Bonzini 
bus_free_bus_child(BusChild * kid)522d24a646SMaxim Levitsky static void bus_free_bus_child(BusChild *kid)
532d24a646SMaxim Levitsky {
542d24a646SMaxim Levitsky     object_unref(OBJECT(kid->child));
552d24a646SMaxim Levitsky     g_free(kid);
562d24a646SMaxim Levitsky }
572d24a646SMaxim Levitsky 
bus_remove_child(BusState * bus,DeviceState * child)5849ab747fSPaolo Bonzini static void bus_remove_child(BusState *bus, DeviceState *child)
5949ab747fSPaolo Bonzini {
6049ab747fSPaolo Bonzini     BusChild *kid;
6149ab747fSPaolo Bonzini 
6249ab747fSPaolo Bonzini     QTAILQ_FOREACH(kid, &bus->children, sibling) {
6349ab747fSPaolo Bonzini         if (kid->child == child) {
6449ab747fSPaolo Bonzini             char name[32];
6549ab747fSPaolo Bonzini 
6649ab747fSPaolo Bonzini             snprintf(name, sizeof(name), "child[%d]", kid->index);
672d24a646SMaxim Levitsky             QTAILQ_REMOVE_RCU(&bus->children, kid, sibling);
6849ab747fSPaolo Bonzini 
6912b2e9f3STony Krowiak             bus->num_children--;
7012b2e9f3STony Krowiak 
7149ab747fSPaolo Bonzini             /* This gives back ownership of kid->child back to us.  */
72df4fe0b2SMarkus Armbruster             object_property_del(OBJECT(bus), name);
732d24a646SMaxim Levitsky 
742d24a646SMaxim Levitsky             /* free the bus kid, when it is safe to do so*/
752d24a646SMaxim Levitsky             call_rcu(kid, bus_free_bus_child, rcu);
762d24a646SMaxim Levitsky             break;
7749ab747fSPaolo Bonzini         }
7849ab747fSPaolo Bonzini     }
7949ab747fSPaolo Bonzini }
8049ab747fSPaolo Bonzini 
bus_add_child(BusState * bus,DeviceState * child)8149ab747fSPaolo Bonzini static void bus_add_child(BusState *bus, DeviceState *child)
8249ab747fSPaolo Bonzini {
8349ab747fSPaolo Bonzini     char name[32];
8449ab747fSPaolo Bonzini     BusChild *kid = g_malloc0(sizeof(*kid));
8549ab747fSPaolo Bonzini 
8612b2e9f3STony Krowiak     bus->num_children++;
8749ab747fSPaolo Bonzini     kid->index = bus->max_index++;
8849ab747fSPaolo Bonzini     kid->child = child;
8949ab747fSPaolo Bonzini     object_ref(OBJECT(kid->child));
9049ab747fSPaolo Bonzini 
912d24a646SMaxim Levitsky     QTAILQ_INSERT_HEAD_RCU(&bus->children, kid, sibling);
9249ab747fSPaolo Bonzini 
9349ab747fSPaolo Bonzini     /* This transfers ownership of kid->child to the property.  */
9449ab747fSPaolo Bonzini     snprintf(name, sizeof(name), "child[%d]", kid->index);
9549ab747fSPaolo Bonzini     object_property_add_link(OBJECT(bus), name,
9649ab747fSPaolo Bonzini                              object_get_typename(OBJECT(child)),
9739f72ef9SStefan Hajnoczi                              (Object **)&kid->child,
9839f72ef9SStefan Hajnoczi                              NULL, /* read-only property */
99d2623129SMarkus Armbruster                              0);
10049ab747fSPaolo Bonzini }
10149ab747fSPaolo Bonzini 
bus_check_address(BusState * bus,DeviceState * child,Error ** errp)102bb755ba4SPaolo Bonzini static bool bus_check_address(BusState *bus, DeviceState *child, Error **errp)
103bb755ba4SPaolo Bonzini {
104bb755ba4SPaolo Bonzini     BusClass *bc = BUS_GET_CLASS(bus);
105bb755ba4SPaolo Bonzini     return !bc->check_address || bc->check_address(bus, child, errp);
106bb755ba4SPaolo Bonzini }
107bb755ba4SPaolo Bonzini 
qdev_set_parent_bus(DeviceState * dev,BusState * bus,Error ** errp)108bb755ba4SPaolo Bonzini bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp)
10949ab747fSPaolo Bonzini {
110a7c3a4f9SDamien Hedde     BusState *old_parent_bus = dev->parent_bus;
11181cb0573SMarkus Armbruster     DeviceClass *dc = DEVICE_GET_CLASS(dev);
11281cb0573SMarkus Armbruster 
11381cb0573SMarkus Armbruster     assert(dc->bus_type && object_dynamic_cast(OBJECT(bus), dc->bus_type));
11491c968acSPeter Maydell 
115bb755ba4SPaolo Bonzini     if (!bus_check_address(bus, dev, errp)) {
116bb755ba4SPaolo Bonzini         return false;
117bb755ba4SPaolo Bonzini     }
118bb755ba4SPaolo Bonzini 
119a7c3a4f9SDamien Hedde     if (old_parent_bus) {
12070804c83SDamien Hedde         trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)),
121a7c3a4f9SDamien Hedde             old_parent_bus, object_get_typename(OBJECT(old_parent_bus)),
12270804c83SDamien Hedde             OBJECT(bus), object_get_typename(OBJECT(bus)));
12370804c83SDamien Hedde         /*
12470804c83SDamien Hedde          * Keep a reference to the device while it's not plugged into
12591c968acSPeter Maydell          * any bus, to avoid it potentially evaporating when it is
12691c968acSPeter Maydell          * dereffed in bus_remove_child().
127a7c3a4f9SDamien Hedde          * Also keep the ref of the parent bus until the end, so that
128a7c3a4f9SDamien Hedde          * we can safely call resettable_change_parent() below.
12991c968acSPeter Maydell          */
13091c968acSPeter Maydell         object_ref(OBJECT(dev));
13191c968acSPeter Maydell         bus_remove_child(dev->parent_bus, dev);
13291c968acSPeter Maydell     }
13349ab747fSPaolo Bonzini     dev->parent_bus = bus;
13449ab747fSPaolo Bonzini     object_ref(OBJECT(bus));
13549ab747fSPaolo Bonzini     bus_add_child(bus, dev);
136a7c3a4f9SDamien Hedde     if (dev->realized) {
137a7c3a4f9SDamien Hedde         resettable_change_parent(OBJECT(dev), OBJECT(bus),
138a7c3a4f9SDamien Hedde                                  OBJECT(old_parent_bus));
139a7c3a4f9SDamien Hedde     }
140a7c3a4f9SDamien Hedde     if (old_parent_bus) {
141a7c3a4f9SDamien Hedde         object_unref(OBJECT(old_parent_bus));
14291c968acSPeter Maydell         object_unref(OBJECT(dev));
14391c968acSPeter Maydell     }
144bb755ba4SPaolo Bonzini     return true;
14549ab747fSPaolo Bonzini }
14649ab747fSPaolo Bonzini 
qdev_new(const char * name)1479940b2cfSMarkus Armbruster DeviceState *qdev_new(const char *name)
1489940b2cfSMarkus Armbruster {
1499940b2cfSMarkus Armbruster     return DEVICE(object_new(name));
1509940b2cfSMarkus Armbruster }
1519940b2cfSMarkus Armbruster 
qdev_try_new(const char * name)1529940b2cfSMarkus Armbruster DeviceState *qdev_try_new(const char *name)
1539940b2cfSMarkus Armbruster {
154*b801e3cbSPaolo Bonzini     ObjectClass *oc = module_object_class_by_name(name);
155*b801e3cbSPaolo Bonzini     if (!oc) {
1569940b2cfSMarkus Armbruster         return NULL;
1579940b2cfSMarkus Armbruster     }
158*b801e3cbSPaolo Bonzini     return DEVICE(object_new_with_class(oc));
1599940b2cfSMarkus Armbruster }
1609940b2cfSMarkus Armbruster 
161eae3eb3eSPaolo Bonzini static QTAILQ_HEAD(, DeviceListener) device_listeners
162707ff800SPaul Durrant     = QTAILQ_HEAD_INITIALIZER(device_listeners);
163707ff800SPaul Durrant 
164707ff800SPaul Durrant enum ListenerDirection { Forward, Reverse };
165707ff800SPaul Durrant 
166707ff800SPaul Durrant #define DEVICE_LISTENER_CALL(_callback, _direction, _args...)     \
167707ff800SPaul Durrant     do {                                                          \
168707ff800SPaul Durrant         DeviceListener *_listener;                                \
169707ff800SPaul Durrant                                                                   \
170707ff800SPaul Durrant         switch (_direction) {                                     \
171707ff800SPaul Durrant         case Forward:                                             \
172707ff800SPaul Durrant             QTAILQ_FOREACH(_listener, &device_listeners, link) {  \
173707ff800SPaul Durrant                 if (_listener->_callback) {                       \
174707ff800SPaul Durrant                     _listener->_callback(_listener, ##_args);     \
175707ff800SPaul Durrant                 }                                                 \
176707ff800SPaul Durrant             }                                                     \
177707ff800SPaul Durrant             break;                                                \
178707ff800SPaul Durrant         case Reverse:                                             \
179707ff800SPaul Durrant             QTAILQ_FOREACH_REVERSE(_listener, &device_listeners,  \
180eae3eb3eSPaolo Bonzini                                    link) {                        \
181707ff800SPaul Durrant                 if (_listener->_callback) {                       \
182707ff800SPaul Durrant                     _listener->_callback(_listener, ##_args);     \
183707ff800SPaul Durrant                 }                                                 \
184707ff800SPaul Durrant             }                                                     \
185707ff800SPaul Durrant             break;                                                \
186707ff800SPaul Durrant         default:                                                  \
187707ff800SPaul Durrant             abort();                                              \
188707ff800SPaul Durrant         }                                                         \
189707ff800SPaul Durrant     } while (0)
190707ff800SPaul Durrant 
device_listener_add(DeviceState * dev,void * opaque)191707ff800SPaul Durrant static int device_listener_add(DeviceState *dev, void *opaque)
192707ff800SPaul Durrant {
193707ff800SPaul Durrant     DEVICE_LISTENER_CALL(realize, Forward, dev);
194707ff800SPaul Durrant 
195707ff800SPaul Durrant     return 0;
196707ff800SPaul Durrant }
197707ff800SPaul Durrant 
device_listener_register(DeviceListener * listener)198707ff800SPaul Durrant void device_listener_register(DeviceListener *listener)
199707ff800SPaul Durrant {
200707ff800SPaul Durrant     QTAILQ_INSERT_TAIL(&device_listeners, listener, link);
201707ff800SPaul Durrant 
202707ff800SPaul Durrant     qbus_walk_children(sysbus_get_default(), NULL, NULL, device_listener_add,
203707ff800SPaul Durrant                        NULL, NULL);
204707ff800SPaul Durrant }
205707ff800SPaul Durrant 
device_listener_unregister(DeviceListener * listener)206707ff800SPaul Durrant void device_listener_unregister(DeviceListener *listener)
207707ff800SPaul Durrant {
208707ff800SPaul Durrant     QTAILQ_REMOVE(&device_listeners, listener, link);
209707ff800SPaul Durrant }
210707ff800SPaul Durrant 
qdev_should_hide_device(const QDict * opts,bool from_json,Error ** errp)211f3558b1bSKevin Wolf bool qdev_should_hide_device(const QDict *opts, bool from_json, Error **errp)
212f3a85056SJens Freimann {
2137d618082SKevin Wolf     ERRP_GUARD();
214f3a85056SJens Freimann     DeviceListener *listener;
215f3a85056SJens Freimann 
216f3a85056SJens Freimann     QTAILQ_FOREACH(listener, &device_listeners, link) {
217b91ad981SJuan Quintela         if (listener->hide_device) {
218f3558b1bSKevin Wolf             if (listener->hide_device(listener, opts, from_json, errp)) {
21989631fedSJuan Quintela                 return true;
2207d618082SKevin Wolf             } else if (*errp) {
2217d618082SKevin Wolf                 return false;
222f3a85056SJens Freimann             }
223f3a85056SJens Freimann         }
224f3a85056SJens Freimann     }
225f3a85056SJens Freimann 
22689631fedSJuan Quintela     return false;
227f3a85056SJens Freimann }
228f3a85056SJens Freimann 
qdev_set_legacy_instance_id(DeviceState * dev,int alias_id,int required_for_version)22949ab747fSPaolo Bonzini void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
23049ab747fSPaolo Bonzini                                  int required_for_version)
23149ab747fSPaolo Bonzini {
23249ab747fSPaolo Bonzini     assert(!dev->realized);
23349ab747fSPaolo Bonzini     dev->instance_id_alias = alias_id;
23449ab747fSPaolo Bonzini     dev->alias_required_for_version = required_for_version;
23549ab747fSPaolo Bonzini }
23649ab747fSPaolo Bonzini 
device_cold_reset(DeviceState * dev)237abb89dbfSDamien Hedde void device_cold_reset(DeviceState *dev)
238abb89dbfSDamien Hedde {
239abb89dbfSDamien Hedde     resettable_reset(OBJECT(dev), RESET_TYPE_COLD);
240abb89dbfSDamien Hedde }
241abb89dbfSDamien Hedde 
device_is_in_reset(DeviceState * dev)242c11256aaSDamien Hedde bool device_is_in_reset(DeviceState *dev)
243c11256aaSDamien Hedde {
244c11256aaSDamien Hedde     return resettable_is_in_reset(OBJECT(dev));
245c11256aaSDamien Hedde }
246c11256aaSDamien Hedde 
device_get_reset_state(Object * obj)247c11256aaSDamien Hedde static ResettableState *device_get_reset_state(Object *obj)
248c11256aaSDamien Hedde {
249c11256aaSDamien Hedde     DeviceState *dev = DEVICE(obj);
250c11256aaSDamien Hedde     return &dev->reset;
251c11256aaSDamien Hedde }
252c11256aaSDamien Hedde 
device_reset_child_foreach(Object * obj,ResettableChildCallback cb,void * opaque,ResetType type)253c11256aaSDamien Hedde static void device_reset_child_foreach(Object *obj, ResettableChildCallback cb,
254c11256aaSDamien Hedde                                        void *opaque, ResetType type)
255c11256aaSDamien Hedde {
256c11256aaSDamien Hedde     DeviceState *dev = DEVICE(obj);
257c11256aaSDamien Hedde     BusState *bus;
258c11256aaSDamien Hedde 
259c11256aaSDamien Hedde     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
260c11256aaSDamien Hedde         cb(OBJECT(bus), opaque, type);
261c11256aaSDamien Hedde     }
262c11256aaSDamien Hedde }
263c11256aaSDamien Hedde 
qdev_realize(DeviceState * dev,BusState * bus,Error ** errp)2649940b2cfSMarkus Armbruster bool qdev_realize(DeviceState *dev, BusState *bus, Error **errp)
2659940b2cfSMarkus Armbruster {
2669940b2cfSMarkus Armbruster     assert(!dev->realized && !dev->parent_bus);
2679940b2cfSMarkus Armbruster 
268510ef98dSMarkus Armbruster     if (bus) {
269bb755ba4SPaolo Bonzini         if (!qdev_set_parent_bus(dev, bus, errp)) {
270bb755ba4SPaolo Bonzini             return false;
271bb755ba4SPaolo Bonzini         }
272510ef98dSMarkus Armbruster     } else {
273510ef98dSMarkus Armbruster         assert(!DEVICE_GET_CLASS(dev)->bus_type);
274510ef98dSMarkus Armbruster     }
2759940b2cfSMarkus Armbruster 
276f07ad48dSMarkus Armbruster     return object_property_set_bool(OBJECT(dev), "realized", true, errp);
2779940b2cfSMarkus Armbruster }
2789940b2cfSMarkus Armbruster 
qdev_realize_and_unref(DeviceState * dev,BusState * bus,Error ** errp)2799940b2cfSMarkus Armbruster bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp)
2809940b2cfSMarkus Armbruster {
2819940b2cfSMarkus Armbruster     bool ret;
2829940b2cfSMarkus Armbruster 
2839940b2cfSMarkus Armbruster     ret = qdev_realize(dev, bus, errp);
2849940b2cfSMarkus Armbruster     object_unref(OBJECT(dev));
2859940b2cfSMarkus Armbruster     return ret;
2869940b2cfSMarkus Armbruster }
2879940b2cfSMarkus Armbruster 
qdev_unrealize(DeviceState * dev)2889940b2cfSMarkus Armbruster void qdev_unrealize(DeviceState *dev)
2899940b2cfSMarkus Armbruster {
2905325cc34SMarkus Armbruster     object_property_set_bool(OBJECT(dev), "realized", false, &error_abort);
2919940b2cfSMarkus Armbruster }
2929940b2cfSMarkus Armbruster 
qdev_assert_realized_properly_cb(Object * obj,void * opaque)293f66dc873SPaolo Bonzini static int qdev_assert_realized_properly_cb(Object *obj, void *opaque)
294dfe8c79cSMarkus Armbruster {
295dfe8c79cSMarkus Armbruster     DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE));
296dfe8c79cSMarkus Armbruster     DeviceClass *dc;
297dfe8c79cSMarkus Armbruster 
298dfe8c79cSMarkus Armbruster     if (dev) {
299dfe8c79cSMarkus Armbruster         dc = DEVICE_GET_CLASS(dev);
300dfe8c79cSMarkus Armbruster         assert(dev->realized);
301dfe8c79cSMarkus Armbruster         assert(dev->parent_bus || !dc->bus_type);
302dfe8c79cSMarkus Armbruster     }
303dfe8c79cSMarkus Armbruster     return 0;
304dfe8c79cSMarkus Armbruster }
305dfe8c79cSMarkus Armbruster 
qdev_assert_realized_properly(void)306f66dc873SPaolo Bonzini void qdev_assert_realized_properly(void)
30749ab747fSPaolo Bonzini {
308dfe8c79cSMarkus Armbruster     object_child_foreach_recursive(object_get_root(),
309f66dc873SPaolo Bonzini                                    qdev_assert_realized_properly_cb, NULL);
31049ab747fSPaolo Bonzini }
31149ab747fSPaolo Bonzini 
qdev_machine_modified(void)31249ab747fSPaolo Bonzini bool qdev_machine_modified(void)
31349ab747fSPaolo Bonzini {
31449ab747fSPaolo Bonzini     return qdev_hot_added || qdev_hot_removed;
31549ab747fSPaolo Bonzini }
31649ab747fSPaolo Bonzini 
qdev_get_parent_bus(const DeviceState * dev)3172d2f2507SPhilippe Mathieu-Daudé BusState *qdev_get_parent_bus(const DeviceState *dev)
31849ab747fSPaolo Bonzini {
31949ab747fSPaolo Bonzini     return dev->parent_bus;
32049ab747fSPaolo Bonzini }
32149ab747fSPaolo Bonzini 
qdev_get_child_bus(DeviceState * dev,const char * name)32249ab747fSPaolo Bonzini BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
32349ab747fSPaolo Bonzini {
32449ab747fSPaolo Bonzini     BusState *bus;
325f698c8baSPeter Crosthwaite     Object *child = object_resolve_path_component(OBJECT(dev), name);
326f698c8baSPeter Crosthwaite 
327f698c8baSPeter Crosthwaite     bus = (BusState *)object_dynamic_cast(child, TYPE_BUS);
328f698c8baSPeter Crosthwaite     if (bus) {
329f698c8baSPeter Crosthwaite         return bus;
330f698c8baSPeter Crosthwaite     }
33149ab747fSPaolo Bonzini 
33249ab747fSPaolo Bonzini     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
33349ab747fSPaolo Bonzini         if (strcmp(name, bus->name) == 0) {
33449ab747fSPaolo Bonzini             return bus;
33549ab747fSPaolo Bonzini         }
33649ab747fSPaolo Bonzini     }
33749ab747fSPaolo Bonzini     return NULL;
33849ab747fSPaolo Bonzini }
33949ab747fSPaolo Bonzini 
qdev_walk_children(DeviceState * dev,qdev_walkerfn * pre_devfn,qbus_walkerfn * pre_busfn,qdev_walkerfn * post_devfn,qbus_walkerfn * post_busfn,void * opaque)3400293214bSPaolo Bonzini int qdev_walk_children(DeviceState *dev,
3410293214bSPaolo Bonzini                        qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
3420293214bSPaolo Bonzini                        qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
3430293214bSPaolo Bonzini                        void *opaque)
34449ab747fSPaolo Bonzini {
34549ab747fSPaolo Bonzini     BusState *bus;
34649ab747fSPaolo Bonzini     int err;
34749ab747fSPaolo Bonzini 
3480293214bSPaolo Bonzini     if (pre_devfn) {
3490293214bSPaolo Bonzini         err = pre_devfn(dev, opaque);
35049ab747fSPaolo Bonzini         if (err) {
35149ab747fSPaolo Bonzini             return err;
35249ab747fSPaolo Bonzini         }
35349ab747fSPaolo Bonzini     }
35449ab747fSPaolo Bonzini 
35549ab747fSPaolo Bonzini     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
3560293214bSPaolo Bonzini         err = qbus_walk_children(bus, pre_devfn, pre_busfn,
3570293214bSPaolo Bonzini                                  post_devfn, post_busfn, opaque);
35849ab747fSPaolo Bonzini         if (err < 0) {
35949ab747fSPaolo Bonzini             return err;
36049ab747fSPaolo Bonzini         }
36149ab747fSPaolo Bonzini     }
36249ab747fSPaolo Bonzini 
3630293214bSPaolo Bonzini     if (post_devfn) {
3640293214bSPaolo Bonzini         err = post_devfn(dev, opaque);
3650293214bSPaolo Bonzini         if (err) {
3660293214bSPaolo Bonzini             return err;
3670293214bSPaolo Bonzini         }
3680293214bSPaolo Bonzini     }
3690293214bSPaolo Bonzini 
37049ab747fSPaolo Bonzini     return 0;
37149ab747fSPaolo Bonzini }
37249ab747fSPaolo Bonzini 
qdev_find_recursive(BusState * bus,const char * id)37349ab747fSPaolo Bonzini DeviceState *qdev_find_recursive(BusState *bus, const char *id)
37449ab747fSPaolo Bonzini {
37549ab747fSPaolo Bonzini     BusChild *kid;
37649ab747fSPaolo Bonzini     DeviceState *ret;
37749ab747fSPaolo Bonzini     BusState *child;
37849ab747fSPaolo Bonzini 
3792d24a646SMaxim Levitsky     WITH_RCU_READ_LOCK_GUARD() {
3802d24a646SMaxim Levitsky         QTAILQ_FOREACH_RCU(kid, &bus->children, sibling) {
38149ab747fSPaolo Bonzini             DeviceState *dev = kid->child;
38249ab747fSPaolo Bonzini 
38349ab747fSPaolo Bonzini             if (dev->id && strcmp(dev->id, id) == 0) {
38449ab747fSPaolo Bonzini                 return dev;
38549ab747fSPaolo Bonzini             }
38649ab747fSPaolo Bonzini 
38749ab747fSPaolo Bonzini             QLIST_FOREACH(child, &dev->child_bus, sibling) {
38849ab747fSPaolo Bonzini                 ret = qdev_find_recursive(child, id);
38949ab747fSPaolo Bonzini                 if (ret) {
39049ab747fSPaolo Bonzini                     return ret;
39149ab747fSPaolo Bonzini                 }
39249ab747fSPaolo Bonzini             }
39349ab747fSPaolo Bonzini         }
3942d24a646SMaxim Levitsky     }
39549ab747fSPaolo Bonzini     return NULL;
39649ab747fSPaolo Bonzini }
39749ab747fSPaolo Bonzini 
qdev_get_dev_path(DeviceState * dev)39849ab747fSPaolo Bonzini char *qdev_get_dev_path(DeviceState *dev)
39949ab747fSPaolo Bonzini {
40049ab747fSPaolo Bonzini     BusClass *bc;
40149ab747fSPaolo Bonzini 
40249ab747fSPaolo Bonzini     if (!dev || !dev->parent_bus) {
40349ab747fSPaolo Bonzini         return NULL;
40449ab747fSPaolo Bonzini     }
40549ab747fSPaolo Bonzini 
40649ab747fSPaolo Bonzini     bc = BUS_GET_CLASS(dev->parent_bus);
40749ab747fSPaolo Bonzini     if (bc->get_dev_path) {
40849ab747fSPaolo Bonzini         return bc->get_dev_path(dev);
40949ab747fSPaolo Bonzini     }
41049ab747fSPaolo Bonzini 
41149ab747fSPaolo Bonzini     return NULL;
41249ab747fSPaolo Bonzini }
41349ab747fSPaolo Bonzini 
qdev_add_unplug_blocker(DeviceState * dev,Error * reason)414217c7f01SJagannathan Raman void qdev_add_unplug_blocker(DeviceState *dev, Error *reason)
415217c7f01SJagannathan Raman {
416217c7f01SJagannathan Raman     dev->unplug_blockers = g_slist_prepend(dev->unplug_blockers, reason);
417217c7f01SJagannathan Raman }
418217c7f01SJagannathan Raman 
qdev_del_unplug_blocker(DeviceState * dev,Error * reason)419217c7f01SJagannathan Raman void qdev_del_unplug_blocker(DeviceState *dev, Error *reason)
420217c7f01SJagannathan Raman {
421217c7f01SJagannathan Raman     dev->unplug_blockers = g_slist_remove(dev->unplug_blockers, reason);
422217c7f01SJagannathan Raman }
423217c7f01SJagannathan Raman 
qdev_unplug_blocked(DeviceState * dev,Error ** errp)424217c7f01SJagannathan Raman bool qdev_unplug_blocked(DeviceState *dev, Error **errp)
425217c7f01SJagannathan Raman {
426217c7f01SJagannathan Raman     if (dev->unplug_blockers) {
427217c7f01SJagannathan Raman         error_propagate(errp, error_copy(dev->unplug_blockers->data));
428217c7f01SJagannathan Raman         return true;
429217c7f01SJagannathan Raman     }
430217c7f01SJagannathan Raman 
431217c7f01SJagannathan Raman     return false;
432217c7f01SJagannathan Raman }
433217c7f01SJagannathan Raman 
device_get_realized(Object * obj,Error ** errp)434a7737e44SMarkus Armbruster static bool device_get_realized(Object *obj, Error **errp)
43549ab747fSPaolo Bonzini {
43649ab747fSPaolo Bonzini     DeviceState *dev = DEVICE(obj);
43749ab747fSPaolo Bonzini     return dev->realized;
43849ab747fSPaolo Bonzini }
43949ab747fSPaolo Bonzini 
check_only_migratable(Object * obj,Error ** errp)44040f03bd5SVladimir Sementsov-Ogievskiy static bool check_only_migratable(Object *obj, Error **errp)
4411bfe5f05SJuan Quintela {
4421bfe5f05SJuan Quintela     DeviceClass *dc = DEVICE_GET_CLASS(obj);
4431bfe5f05SJuan Quintela 
4441bfe5f05SJuan Quintela     if (!vmstate_check_only_migratable(dc->vmsd)) {
44540f03bd5SVladimir Sementsov-Ogievskiy         error_setg(errp, "Device %s is not migratable, but "
4461bfe5f05SJuan Quintela                    "--only-migratable was specified",
4471bfe5f05SJuan Quintela                    object_get_typename(obj));
4481bfe5f05SJuan Quintela         return false;
4491bfe5f05SJuan Quintela     }
4501bfe5f05SJuan Quintela 
4511bfe5f05SJuan Quintela     return true;
4521bfe5f05SJuan Quintela }
4531bfe5f05SJuan Quintela 
device_set_realized(Object * obj,bool value,Error ** errp)454a7737e44SMarkus Armbruster static void device_set_realized(Object *obj, bool value, Error **errp)
45549ab747fSPaolo Bonzini {
45649ab747fSPaolo Bonzini     DeviceState *dev = DEVICE(obj);
45749ab747fSPaolo Bonzini     DeviceClass *dc = DEVICE_GET_CLASS(dev);
4587716b8caSIgor Mammedov     HotplugHandler *hotplug_ctrl;
4595c21ce77SBandan Das     BusState *bus;
4600e6934f2SDamien Hedde     NamedClockList *ncl;
46149ab747fSPaolo Bonzini     Error *local_err = NULL;
46269382d8bSIgor Mammedov     bool unattached_parent = false;
46369382d8bSIgor Mammedov     static int unattached_count;
46449ab747fSPaolo Bonzini 
4651a37eca1SIgor Mammedov     if (dev->hotplugged && !dc->hotpluggable) {
466f95b25c3SPhilippe Mathieu-Daudé         error_setg(errp, "Device '%s' does not support hotplugging",
467f95b25c3SPhilippe Mathieu-Daudé                    object_get_typename(obj));
4681a37eca1SIgor Mammedov         return;
4691a37eca1SIgor Mammedov     }
4701a37eca1SIgor Mammedov 
47149ab747fSPaolo Bonzini     if (value && !dev->realized) {
472a5f9b9dfSMarkus Armbruster         if (!check_only_migratable(obj, errp)) {
4737562f907SAshijeet Acharya             goto fail;
4747562f907SAshijeet Acharya         }
4757562f907SAshijeet Acharya 
476d578029eSGonglei         if (!obj->parent) {
47749ab747fSPaolo Bonzini             gchar *name = g_strdup_printf("device[%d]", unattached_count++);
47849ab747fSPaolo Bonzini 
47949ab747fSPaolo Bonzini             object_property_add_child(container_get(qdev_get_machine(),
48049ab747fSPaolo Bonzini                                                     "/unattached"),
481d2623129SMarkus Armbruster                                       name, obj);
48269382d8bSIgor Mammedov             unattached_parent = true;
48349ab747fSPaolo Bonzini             g_free(name);
48449ab747fSPaolo Bonzini         }
48549ab747fSPaolo Bonzini 
48641346263SIgor Mammedov         hotplug_ctrl = qdev_get_hotplug_handler(dev);
48741346263SIgor Mammedov         if (hotplug_ctrl) {
48841346263SIgor Mammedov             hotplug_handler_pre_plug(hotplug_ctrl, dev, &local_err);
48941346263SIgor Mammedov             if (local_err != NULL) {
49041346263SIgor Mammedov                 goto fail;
49141346263SIgor Mammedov             }
49241346263SIgor Mammedov         }
49341346263SIgor Mammedov 
494a7ddba52SIgor Mammedov         if (dc->realize) {
495a7ddba52SIgor Mammedov             dc->realize(dev, &local_err);
4961d45a705SGonglei             if (local_err != NULL) {
4971d45a705SGonglei                 goto fail;
4981d45a705SGonglei             }
49940f03bd5SVladimir Sementsov-Ogievskiy         }
5001d45a705SGonglei 
501707ff800SPaul Durrant         DEVICE_LISTENER_CALL(realize, Forward, dev);
502707ff800SPaul Durrant 
50304162f8fSMichael Roth         /*
50404162f8fSMichael Roth          * always free/re-initialize here since the value cannot be cleaned up
50504162f8fSMichael Roth          * in device_unrealize due to its usage later on in the unplug path
50604162f8fSMichael Roth          */
50704162f8fSMichael Roth         g_free(dev->canonical_path);
50804162f8fSMichael Roth         dev->canonical_path = object_get_canonical_path(OBJECT(dev));
5090e6934f2SDamien Hedde         QLIST_FOREACH(ncl, &dev->clocks, node) {
5100e6934f2SDamien Hedde             if (ncl->alias) {
5110e6934f2SDamien Hedde                 continue;
5120e6934f2SDamien Hedde             } else {
5130e6934f2SDamien Hedde                 clock_setup_canonical_path(ncl->clock);
5140e6934f2SDamien Hedde             }
5150e6934f2SDamien Hedde         }
51604162f8fSMichael Roth 
5171d45a705SGonglei         if (qdev_get_vmsd(dev)) {
5183cad405bSMarc-André Lureau             if (vmstate_register_with_alias_id(VMSTATE_IF(dev),
5191df2c9a2SPeter Xu                                                VMSTATE_INSTANCE_ID_ANY,
5201df2c9a2SPeter Xu                                                qdev_get_vmsd(dev), dev,
52149ab747fSPaolo Bonzini                                                dev->instance_id_alias,
522bc5c4f21SDr. David Alan Gilbert                                                dev->alias_required_for_version,
52367980031SDr. David Alan Gilbert                                                &local_err) < 0) {
52467980031SDr. David Alan Gilbert                 goto post_realize_fail;
52567980031SDr. David Alan Gilbert             }
52649ab747fSPaolo Bonzini         }
5271d45a705SGonglei 
528e755e127SDamien Hedde         /*
529e755e127SDamien Hedde          * Clear the reset state, in case the object was previously unrealized
530e755e127SDamien Hedde          * with a dirty state.
531e755e127SDamien Hedde          */
532e755e127SDamien Hedde         resettable_state_clear(&dev->reset);
533e755e127SDamien Hedde 
5345c21ce77SBandan Das         QLIST_FOREACH(bus, &dev->child_bus, sibling) {
535f1483b46SMarkus Armbruster             if (!qbus_realize(bus, errp)) {
5361d45a705SGonglei                 goto child_realize_fail;
5375c21ce77SBandan Das             }
5385c21ce77SBandan Das         }
5391d45a705SGonglei         if (dev->hotplugged) {
540e755e127SDamien Hedde             /*
541e755e127SDamien Hedde              * Reset the device, as well as its subtree which, at this point,
542e755e127SDamien Hedde              * should be realized too.
543e755e127SDamien Hedde              */
544e755e127SDamien Hedde             resettable_assert_reset(OBJECT(dev), RESET_TYPE_COLD);
545e755e127SDamien Hedde             resettable_change_parent(OBJECT(dev), OBJECT(dev->parent_bus),
546e755e127SDamien Hedde                                      NULL);
547e755e127SDamien Hedde             resettable_release_reset(OBJECT(dev), RESET_TYPE_COLD);
54849ab747fSPaolo Bonzini         }
549352e8da7SPaolo Bonzini         dev->pending_deleted_event = false;
55025e89788SStefan Hajnoczi 
55125e89788SStefan Hajnoczi         if (hotplug_ctrl) {
5528b5e6cafSIgor Mammedov             hotplug_handler_plug(hotplug_ctrl, dev, &local_err);
5538b5e6cafSIgor Mammedov             if (local_err != NULL) {
5548b5e6cafSIgor Mammedov                 goto child_realize_fail;
55525e89788SStefan Hajnoczi             }
5568b5e6cafSIgor Mammedov        }
5578b5e6cafSIgor Mammedov 
558a23151e8SMaxim Levitsky        qatomic_store_release(&dev->realized, value);
559a23151e8SMaxim Levitsky 
56049ab747fSPaolo Bonzini     } else if (!value && dev->realized) {
561a23151e8SMaxim Levitsky 
562a23151e8SMaxim Levitsky         /*
563a23151e8SMaxim Levitsky          * Change the value so that any concurrent users are aware
564a23151e8SMaxim Levitsky          * that the device is going to be unrealized
565a23151e8SMaxim Levitsky          *
566a23151e8SMaxim Levitsky          * TODO: change .realized property to enum that states
567a23151e8SMaxim Levitsky          * each phase of the device realization/unrealization
568a23151e8SMaxim Levitsky          */
569a23151e8SMaxim Levitsky 
570a23151e8SMaxim Levitsky         qatomic_set(&dev->realized, value);
571a23151e8SMaxim Levitsky         /*
572a23151e8SMaxim Levitsky          * Ensure that concurrent users see this update prior to
573a23151e8SMaxim Levitsky          * any other changes done by unrealize.
574a23151e8SMaxim Levitsky          */
575a23151e8SMaxim Levitsky         smp_wmb();
576a23151e8SMaxim Levitsky 
5775c21ce77SBandan Das         QLIST_FOREACH(bus, &dev->child_bus, sibling) {
578f1483b46SMarkus Armbruster             qbus_unrealize(bus);
5795c21ce77SBandan Das         }
580cd4520adSGonglei         if (qdev_get_vmsd(dev)) {
5813cad405bSMarc-André Lureau             vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev);
582fe6c2117SAndreas Färber         }
583cd4520adSGonglei         if (dc->unrealize) {
584b69c3c21SMarkus Armbruster             dc->unrealize(dev);
58549ab747fSPaolo Bonzini         }
586352e8da7SPaolo Bonzini         dev->pending_deleted_event = true;
587707ff800SPaul Durrant         DEVICE_LISTENER_CALL(unrealize, Reverse, dev);
58840f03bd5SVladimir Sementsov-Ogievskiy     }
58949ab747fSPaolo Bonzini 
59040f03bd5SVladimir Sementsov-Ogievskiy     assert(local_err == NULL);
5911d45a705SGonglei     return;
5921d45a705SGonglei 
5931d45a705SGonglei child_realize_fail:
5941d45a705SGonglei     QLIST_FOREACH(bus, &dev->child_bus, sibling) {
595f1483b46SMarkus Armbruster         qbus_unrealize(bus);
5961d45a705SGonglei     }
5971d45a705SGonglei 
5981d45a705SGonglei     if (qdev_get_vmsd(dev)) {
5993cad405bSMarc-André Lureau         vmstate_unregister(VMSTATE_IF(dev), qdev_get_vmsd(dev), dev);
6001d45a705SGonglei     }
6011d45a705SGonglei 
6021d45a705SGonglei post_realize_fail:
60304162f8fSMichael Roth     g_free(dev->canonical_path);
60404162f8fSMichael Roth     dev->canonical_path = NULL;
6051d45a705SGonglei     if (dc->unrealize) {
606b69c3c21SMarkus Armbruster         dc->unrealize(dev);
6071d45a705SGonglei     }
6081d45a705SGonglei 
6091d45a705SGonglei fail:
6101d45a705SGonglei     error_propagate(errp, local_err);
61169382d8bSIgor Mammedov     if (unattached_parent) {
6129940b2cfSMarkus Armbruster         /*
6139940b2cfSMarkus Armbruster          * Beware, this doesn't just revert
6149940b2cfSMarkus Armbruster          * object_property_add_child(), it also runs bus_remove()!
6159940b2cfSMarkus Armbruster          */
61669382d8bSIgor Mammedov         object_unparent(OBJECT(dev));
61769382d8bSIgor Mammedov         unattached_count--;
61869382d8bSIgor Mammedov     }
61949ab747fSPaolo Bonzini }
62049ab747fSPaolo Bonzini 
device_get_hotpluggable(Object * obj,Error ** errp)621a7737e44SMarkus Armbruster static bool device_get_hotpluggable(Object *obj, Error **errp)
6221a37eca1SIgor Mammedov {
6231a37eca1SIgor Mammedov     DeviceClass *dc = DEVICE_GET_CLASS(obj);
6241a37eca1SIgor Mammedov     DeviceState *dev = DEVICE(obj);
6251a37eca1SIgor Mammedov 
6262b81b35fSAndreas Färber     return dc->hotpluggable && (dev->parent_bus == NULL ||
62739b888bdSIgor Mammedov                                 qbus_is_hotpluggable(dev->parent_bus));
6281a37eca1SIgor Mammedov }
6291a37eca1SIgor Mammedov 
device_get_hotplugged(Object * obj,Error ** errp)63040f03bd5SVladimir Sementsov-Ogievskiy static bool device_get_hotplugged(Object *obj, Error **errp)
631d012ffc1SIgor Mammedov {
632d012ffc1SIgor Mammedov     DeviceState *dev = DEVICE(obj);
633d012ffc1SIgor Mammedov 
634d012ffc1SIgor Mammedov     return dev->hotplugged;
635d012ffc1SIgor Mammedov }
636d012ffc1SIgor Mammedov 
device_initfn(Object * obj)63749ab747fSPaolo Bonzini static void device_initfn(Object *obj)
63849ab747fSPaolo Bonzini {
63949ab747fSPaolo Bonzini     DeviceState *dev = DEVICE(obj);
64049ab747fSPaolo Bonzini 
6412f181fbdSPaolo Bonzini     if (phase_check(PHASE_MACHINE_READY)) {
64249ab747fSPaolo Bonzini         dev->hotplugged = 1;
64349ab747fSPaolo Bonzini         qdev_hot_added = true;
64449ab747fSPaolo Bonzini     }
64549ab747fSPaolo Bonzini 
64649ab747fSPaolo Bonzini     dev->instance_id_alias = -1;
64749ab747fSPaolo Bonzini     dev->realized = false;
648a1190ab6SJens Freimann     dev->allow_unplug_during_migration = false;
64949ab747fSPaolo Bonzini 
650a5f54290SPeter Crosthwaite     QLIST_INIT(&dev->gpios);
6510e6934f2SDamien Hedde     QLIST_INIT(&dev->clocks);
65249ab747fSPaolo Bonzini }
65349ab747fSPaolo Bonzini 
device_post_init(Object * obj)6541c3994f6SMarc-André Lureau static void device_post_init(Object *obj)
6551c3994f6SMarc-André Lureau {
6561a3ec8c1SMarkus Armbruster     /*
6571a3ec8c1SMarkus Armbruster      * Note: ordered so that the user's global properties take
6581a3ec8c1SMarkus Armbruster      * precedence.
6591a3ec8c1SMarkus Armbruster      */
6601c3994f6SMarc-André Lureau     object_apply_compat_props(obj);
66125f8dd96SMarkus Armbruster     qdev_prop_set_globals(DEVICE(obj));
66299a0b036SEduardo Habkost }
66399a0b036SEduardo Habkost 
66449ab747fSPaolo Bonzini /* Unlink device from bus and free the structure.  */
device_finalize(Object * obj)66549ab747fSPaolo Bonzini static void device_finalize(Object *obj)
66649ab747fSPaolo Bonzini {
667a5f54290SPeter Crosthwaite     NamedGPIOList *ngl, *next;
668a5f54290SPeter Crosthwaite 
66949ab747fSPaolo Bonzini     DeviceState *dev = DEVICE(obj);
670a5f54290SPeter Crosthwaite 
671217c7f01SJagannathan Raman     g_assert(!dev->unplug_blockers);
672217c7f01SJagannathan Raman 
673a5f54290SPeter Crosthwaite     QLIST_FOREACH_SAFE(ngl, &dev->gpios, node, next) {
674a5f54290SPeter Crosthwaite         QLIST_REMOVE(ngl, node);
675f173d57aSPeter Crosthwaite         qemu_free_irqs(ngl->in, ngl->num_in);
676a5f54290SPeter Crosthwaite         g_free(ngl->name);
677a5f54290SPeter Crosthwaite         g_free(ngl);
678a5f54290SPeter Crosthwaite         /* ngl->out irqs are owned by the other end and should not be freed
679a5f54290SPeter Crosthwaite          * here
680a5f54290SPeter Crosthwaite          */
681a5f54290SPeter Crosthwaite     }
682f7b879e0SMichael Roth 
6830e6934f2SDamien Hedde     qdev_finalize_clocklist(dev);
6840e6934f2SDamien Hedde 
685f7b879e0SMichael Roth     /* Only send event if the device had been completely realized */
686f7b879e0SMichael Roth     if (dev->pending_deleted_event) {
687f7b879e0SMichael Roth         g_assert(dev->canonical_path);
688f7b879e0SMichael Roth 
689047f2ca1SMarkus Armbruster         qapi_event_send_device_deleted(dev->id, dev->canonical_path);
690f7b879e0SMichael Roth         g_free(dev->canonical_path);
691f7b879e0SMichael Roth         dev->canonical_path = NULL;
692f7b879e0SMichael Roth     }
693f7b879e0SMichael Roth 
694f3558b1bSKevin Wolf     qobject_unref(dev->opts);
695163f3847SKevin Wolf     g_free(dev->id);
69649ab747fSPaolo Bonzini }
69749ab747fSPaolo Bonzini 
device_class_base_init(ObjectClass * class,void * data)69849ab747fSPaolo Bonzini static void device_class_base_init(ObjectClass *class, void *data)
69949ab747fSPaolo Bonzini {
70049ab747fSPaolo Bonzini     DeviceClass *klass = DEVICE_CLASS(class);
70149ab747fSPaolo Bonzini 
70249ab747fSPaolo Bonzini     /* We explicitly look up properties in the superclasses,
70349ab747fSPaolo Bonzini      * so do not propagate them to the subclasses.
70449ab747fSPaolo Bonzini      */
705385d8f22SPaolo Bonzini     klass->props_ = NULL;
70649ab747fSPaolo Bonzini }
70749ab747fSPaolo Bonzini 
device_unparent(Object * obj)70849ab747fSPaolo Bonzini static void device_unparent(Object *obj)
70949ab747fSPaolo Bonzini {
71049ab747fSPaolo Bonzini     DeviceState *dev = DEVICE(obj);
71149ab747fSPaolo Bonzini     BusState *bus;
71249ab747fSPaolo Bonzini 
7135c21ce77SBandan Das     if (dev->realized) {
714dc3edf8dSMarkus Armbruster         qdev_unrealize(dev);
7155c21ce77SBandan Das     }
71649ab747fSPaolo Bonzini     while (dev->num_child_bus) {
71749ab747fSPaolo Bonzini         bus = QLIST_FIRST(&dev->child_bus);
7186780a22cSStefan Hajnoczi         object_unparent(OBJECT(bus));
71949ab747fSPaolo Bonzini     }
72049ab747fSPaolo Bonzini     if (dev->parent_bus) {
72149ab747fSPaolo Bonzini         bus_remove_child(dev->parent_bus, dev);
72249ab747fSPaolo Bonzini         object_unref(OBJECT(dev->parent_bus));
72349ab747fSPaolo Bonzini         dev->parent_bus = NULL;
72449ab747fSPaolo Bonzini     }
72549ab747fSPaolo Bonzini }
72649ab747fSPaolo Bonzini 
727107b5969SMarc-André Lureau static char *
device_vmstate_if_get_id(VMStateIf * obj)728107b5969SMarc-André Lureau device_vmstate_if_get_id(VMStateIf *obj)
729107b5969SMarc-André Lureau {
730107b5969SMarc-André Lureau     DeviceState *dev = DEVICE(obj);
731107b5969SMarc-André Lureau 
732107b5969SMarc-André Lureau     return qdev_get_dev_path(dev);
733107b5969SMarc-André Lureau }
734107b5969SMarc-André Lureau 
device_class_init(ObjectClass * class,void * data)73549ab747fSPaolo Bonzini static void device_class_init(ObjectClass *class, void *data)
73649ab747fSPaolo Bonzini {
73749ab747fSPaolo Bonzini     DeviceClass *dc = DEVICE_CLASS(class);
738107b5969SMarc-André Lureau     VMStateIfClass *vc = VMSTATE_IF_CLASS(class);
739c11256aaSDamien Hedde     ResettableClass *rc = RESETTABLE_CLASS(class);
74049ab747fSPaolo Bonzini 
74149ab747fSPaolo Bonzini     class->unparent = device_unparent;
742267a3264SIgor Mammedov 
743267a3264SIgor Mammedov     /* by default all devices were considered as hotpluggable,
744267a3264SIgor Mammedov      * so with intent to check it in generic qdev_unplug() /
745267a3264SIgor Mammedov      * device_set_realized() functions make every device
746267a3264SIgor Mammedov      * hotpluggable. Devices that shouldn't be hotpluggable,
747267a3264SIgor Mammedov      * should override it in their class_init()
748267a3264SIgor Mammedov      */
749267a3264SIgor Mammedov     dc->hotpluggable = true;
750e90f2a8cSEduardo Habkost     dc->user_creatable = true;
751107b5969SMarc-André Lureau     vc->get_id = device_vmstate_if_get_id;
752c11256aaSDamien Hedde     rc->get_state = device_get_reset_state;
753c11256aaSDamien Hedde     rc->child_foreach = device_reset_child_foreach;
754c11256aaSDamien Hedde 
755c11256aaSDamien Hedde     /*
756b5fe9bf2SPeter Maydell      * A NULL legacy_reset implies a three-phase reset device. Devices can
757b5fe9bf2SPeter Maydell      * only be reset using three-phase aware mechanisms, but we still support
758b5fe9bf2SPeter Maydell      * for transitional purposes leaf classes which set the old legacy_reset
7595fdb6cd2SPeter Maydell      * method via device_class_set_legacy_reset().
760c11256aaSDamien Hedde      */
761b5fe9bf2SPeter Maydell     dc->legacy_reset = NULL;
762c68fc935SMarc-André Lureau 
763c68fc935SMarc-André Lureau     object_class_property_add_bool(class, "realized",
764d2623129SMarkus Armbruster                                    device_get_realized, device_set_realized);
765c68fc935SMarc-André Lureau     object_class_property_add_bool(class, "hotpluggable",
766d2623129SMarkus Armbruster                                    device_get_hotpluggable, NULL);
767c68fc935SMarc-André Lureau     object_class_property_add_bool(class, "hotplugged",
768d2623129SMarkus Armbruster                                    device_get_hotplugged, NULL);
769c68fc935SMarc-André Lureau     object_class_property_add_link(class, "parent_bus", TYPE_BUS,
770d2623129SMarkus Armbruster                                    offsetof(DeviceState, parent_bus), NULL, 0);
77149ab747fSPaolo Bonzini }
77249ab747fSPaolo Bonzini 
do_legacy_reset(Object * obj,ResetType type)7735fdb6cd2SPeter Maydell static void do_legacy_reset(Object *obj, ResetType type)
7745fdb6cd2SPeter Maydell {
7755fdb6cd2SPeter Maydell     DeviceClass *dc = DEVICE_GET_CLASS(obj);
7765fdb6cd2SPeter Maydell 
7775fdb6cd2SPeter Maydell     dc->legacy_reset(DEVICE(obj));
7785fdb6cd2SPeter Maydell }
7795fdb6cd2SPeter Maydell 
device_class_set_legacy_reset(DeviceClass * dc,DeviceReset dev_reset)780134e0944SPeter Maydell void device_class_set_legacy_reset(DeviceClass *dc, DeviceReset dev_reset)
781134e0944SPeter Maydell {
7825fdb6cd2SPeter Maydell     /*
7835fdb6cd2SPeter Maydell      * A legacy DeviceClass::reset has identical semantics to the
7845fdb6cd2SPeter Maydell      * three-phase "hold" method, with no "enter" or "exit"
7855fdb6cd2SPeter Maydell      * behaviour. Classes that use this legacy function must be leaf
7865fdb6cd2SPeter Maydell      * classes that do not chain up to their parent class reset.
7875fdb6cd2SPeter Maydell      * There is no mechanism for resetting a device that does not
7885fdb6cd2SPeter Maydell      * use the three-phase APIs, so the only place which calls
7895fdb6cd2SPeter Maydell      * the legacy_reset hook is do_legacy_reset().
7905fdb6cd2SPeter Maydell      */
7915fdb6cd2SPeter Maydell     ResettableClass *rc = RESETTABLE_CLASS(dc);
7925fdb6cd2SPeter Maydell 
7935fdb6cd2SPeter Maydell     rc->phases.enter = NULL;
7945fdb6cd2SPeter Maydell     rc->phases.hold = do_legacy_reset;
7955fdb6cd2SPeter Maydell     rc->phases.exit = NULL;
7961000872dSPeter Maydell     dc->legacy_reset = dev_reset;
797134e0944SPeter Maydell }
798134e0944SPeter Maydell 
device_class_set_parent_realize(DeviceClass * dc,DeviceRealize dev_realize,DeviceRealize * parent_realize)79946795cf2SPhilippe Mathieu-Daudé void device_class_set_parent_realize(DeviceClass *dc,
80046795cf2SPhilippe Mathieu-Daudé                                      DeviceRealize dev_realize,
80146795cf2SPhilippe Mathieu-Daudé                                      DeviceRealize *parent_realize)
80246795cf2SPhilippe Mathieu-Daudé {
80346795cf2SPhilippe Mathieu-Daudé     *parent_realize = dc->realize;
80446795cf2SPhilippe Mathieu-Daudé     dc->realize = dev_realize;
80546795cf2SPhilippe Mathieu-Daudé }
80646795cf2SPhilippe Mathieu-Daudé 
device_class_set_parent_unrealize(DeviceClass * dc,DeviceUnrealize dev_unrealize,DeviceUnrealize * parent_unrealize)80746795cf2SPhilippe Mathieu-Daudé void device_class_set_parent_unrealize(DeviceClass *dc,
80846795cf2SPhilippe Mathieu-Daudé                                        DeviceUnrealize dev_unrealize,
80946795cf2SPhilippe Mathieu-Daudé                                        DeviceUnrealize *parent_unrealize)
81046795cf2SPhilippe Mathieu-Daudé {
81146795cf2SPhilippe Mathieu-Daudé     *parent_unrealize = dc->unrealize;
81246795cf2SPhilippe Mathieu-Daudé     dc->unrealize = dev_unrealize;
81346795cf2SPhilippe Mathieu-Daudé }
81446795cf2SPhilippe Mathieu-Daudé 
qdev_get_machine(void)81549ab747fSPaolo Bonzini Object *qdev_get_machine(void)
81649ab747fSPaolo Bonzini {
81749ab747fSPaolo Bonzini     static Object *dev;
81849ab747fSPaolo Bonzini 
81949ab747fSPaolo Bonzini     if (dev == NULL) {
82049ab747fSPaolo Bonzini         dev = container_get(object_get_root(), "/machine");
82149ab747fSPaolo Bonzini     }
82249ab747fSPaolo Bonzini 
82349ab747fSPaolo Bonzini     return dev;
82449ab747fSPaolo Bonzini }
82549ab747fSPaolo Bonzini 
qdev_get_human_name(DeviceState * dev)826956ef499SManos Pitsidianakis char *qdev_get_human_name(DeviceState *dev)
827956ef499SManos Pitsidianakis {
828956ef499SManos Pitsidianakis     g_assert(dev != NULL);
829956ef499SManos Pitsidianakis 
830956ef499SManos Pitsidianakis     return dev->id ?
831956ef499SManos Pitsidianakis            g_strdup(dev->id) : object_get_canonical_path(OBJECT(dev));
832956ef499SManos Pitsidianakis }
833956ef499SManos Pitsidianakis 
8342f181fbdSPaolo Bonzini static MachineInitPhase machine_phase;
8352f181fbdSPaolo Bonzini 
phase_check(MachineInitPhase phase)8362f181fbdSPaolo Bonzini bool phase_check(MachineInitPhase phase)
8372f181fbdSPaolo Bonzini {
8382f181fbdSPaolo Bonzini     return machine_phase >= phase;
8392f181fbdSPaolo Bonzini }
8402f181fbdSPaolo Bonzini 
phase_advance(MachineInitPhase phase)8412f181fbdSPaolo Bonzini void phase_advance(MachineInitPhase phase)
8422f181fbdSPaolo Bonzini {
8432f181fbdSPaolo Bonzini     assert(machine_phase == phase - 1);
8442f181fbdSPaolo Bonzini     machine_phase = phase;
8452f181fbdSPaolo Bonzini }
8462f181fbdSPaolo Bonzini 
84749ab747fSPaolo Bonzini static const TypeInfo device_type_info = {
84849ab747fSPaolo Bonzini     .name = TYPE_DEVICE,
84949ab747fSPaolo Bonzini     .parent = TYPE_OBJECT,
85049ab747fSPaolo Bonzini     .instance_size = sizeof(DeviceState),
85149ab747fSPaolo Bonzini     .instance_init = device_initfn,
85299a0b036SEduardo Habkost     .instance_post_init = device_post_init,
85349ab747fSPaolo Bonzini     .instance_finalize = device_finalize,
85449ab747fSPaolo Bonzini     .class_base_init = device_class_base_init,
85549ab747fSPaolo Bonzini     .class_init = device_class_init,
85649ab747fSPaolo Bonzini     .abstract = true,
85749ab747fSPaolo Bonzini     .class_size = sizeof(DeviceClass),
858107b5969SMarc-André Lureau     .interfaces = (InterfaceInfo[]) {
859107b5969SMarc-André Lureau         { TYPE_VMSTATE_IF },
860c11256aaSDamien Hedde         { TYPE_RESETTABLE_INTERFACE },
861107b5969SMarc-André Lureau         { }
862107b5969SMarc-André Lureau     }
86349ab747fSPaolo Bonzini };
86449ab747fSPaolo Bonzini 
qdev_register_types(void)86549ab747fSPaolo Bonzini static void qdev_register_types(void)
86649ab747fSPaolo Bonzini {
86749ab747fSPaolo Bonzini     type_register_static(&device_type_info);
86849ab747fSPaolo Bonzini }
86949ab747fSPaolo Bonzini 
87049ab747fSPaolo Bonzini type_init(qdev_register_types)
871