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