diff options
Diffstat (limited to 'hw/core')
| -rw-r--r-- | hw/core/Makefile.objs | 1 | ||||
| -rw-r--r-- | hw/core/bus.c | 102 | ||||
| -rw-r--r-- | hw/core/or-irq.c | 2 | ||||
| -rw-r--r-- | hw/core/qdev.c | 160 | ||||
| -rw-r--r-- | hw/core/resettable.c | 301 | ||||
| -rw-r--r-- | hw/core/trace-events | 27 |
6 files changed, 582 insertions, 11 deletions
diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index a522b7297d..9e41ec9a15 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -2,6 +2,7 @@ common-obj-y += qdev.o qdev-properties.o common-obj-y += bus.o common-obj-y += cpu.o +common-obj-y += resettable.o common-obj-y += hotplug.o common-obj-y += vmstate-if.o # irq.o needed for qdev GPIO handling: diff --git a/hw/core/bus.c b/hw/core/bus.c index 7f3d2a3dbd..3dc0a825f0 100644 --- a/hw/core/bus.c +++ b/hw/core/bus.c @@ -68,6 +68,33 @@ int qbus_walk_children(BusState *bus, return 0; } +void bus_cold_reset(BusState *bus) +{ + resettable_reset(OBJECT(bus), RESET_TYPE_COLD); +} + +bool bus_is_in_reset(BusState *bus) +{ + return resettable_is_in_reset(OBJECT(bus)); +} + +static ResettableState *bus_get_reset_state(Object *obj) +{ + BusState *bus = BUS(obj); + return &bus->reset; +} + +static void bus_reset_child_foreach(Object *obj, ResettableChildCallback cb, + void *opaque, ResetType type) +{ + BusState *bus = BUS(obj); + BusChild *kid; + + QTAILQ_FOREACH(kid, &bus->children, sibling) { + cb(OBJECT(kid->child), opaque, type); + } +} + static void qbus_realize(BusState *bus, DeviceState *parent, const char *name) { const char *typename = object_get_typename(OBJECT(bus)); @@ -199,12 +226,83 @@ static char *default_bus_get_fw_dev_path(DeviceState *dev) return g_strdup(object_get_typename(OBJECT(dev))); } +/** + * bus_phases_reset: + * Transition reset method for buses to allow moving + * smoothly from legacy reset method to multi-phases + */ +static void bus_phases_reset(BusState *bus) +{ + ResettableClass *rc = RESETTABLE_GET_CLASS(bus); + + if (rc->phases.enter) { + rc->phases.enter(OBJECT(bus), RESET_TYPE_COLD); + } + if (rc->phases.hold) { + rc->phases.hold(OBJECT(bus)); + } + if (rc->phases.exit) { + rc->phases.exit(OBJECT(bus)); + } +} + +static void bus_transitional_reset(Object *obj) +{ + BusClass *bc = BUS_GET_CLASS(obj); + + /* + * This will call either @bus_phases_reset (for multi-phases transitioned + * buses) or a bus's specific method for not-yet transitioned buses. + * In both case, it does not reset children. + */ + if (bc->reset) { + bc->reset(BUS(obj)); + } +} + +/** + * bus_get_transitional_reset: + * check if the bus's class is ready for multi-phase + */ +static ResettableTrFunction bus_get_transitional_reset(Object *obj) +{ + BusClass *dc = BUS_GET_CLASS(obj); + if (dc->reset != bus_phases_reset) { + /* + * dc->reset has been overridden by a subclass, + * the bus is not ready for multi phase yet. + */ + return bus_transitional_reset; + } + return NULL; +} + static void bus_class_init(ObjectClass *class, void *data) { BusClass *bc = BUS_CLASS(class); + ResettableClass *rc = RESETTABLE_CLASS(class); class->unparent = bus_unparent; bc->get_fw_dev_path = default_bus_get_fw_dev_path; + + rc->get_state = bus_get_reset_state; + rc->child_foreach = bus_reset_child_foreach; + + /* + * @bus_phases_reset is put as the default reset method below, allowing + * to do the multi-phase transition from base classes to leaf classes. It + * allows a legacy-reset Bus class to extend a multi-phases-reset + * Bus class for the following reason: + * + If a base class B has been moved to multi-phase, then it does not + * override this default reset method and may have defined phase methods. + * + A child class C (extending class B) which uses + * bus_class_set_parent_reset() (or similar means) to override the + * reset method will still work as expected. @bus_phases_reset function + * will be registered as the parent reset method and effectively call + * parent reset phases. + */ + bc->reset = bus_phases_reset; + rc->get_transitional_function = bus_get_transitional_reset; } static void qbus_finalize(Object *obj) @@ -223,6 +321,10 @@ static const TypeInfo bus_info = { .instance_init = qbus_initfn, .instance_finalize = qbus_finalize, .class_init = bus_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_RESETTABLE_INTERFACE }, + { } + }, }; static void bus_register_types(void) diff --git a/hw/core/or-irq.c b/hw/core/or-irq.c index 4bbdbcb321..d8f3754e96 100644 --- a/hw/core/or-irq.c +++ b/hw/core/or-irq.c @@ -58,7 +58,7 @@ static void or_irq_realize(DeviceState *dev, Error **errp) { qemu_or_irq *s = OR_IRQ(dev); - assert(s->num_lines < MAX_OR_LINES); + assert(s->num_lines <= MAX_OR_LINES); qdev_init_gpio_in(dev, or_irq_handler, s->num_lines); } diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 05c31df52d..3937d1eb1a 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -38,6 +38,7 @@ #include "hw/boards.h" #include "hw/sysbus.h" #include "migration/vmstate.h" +#include "trace.h" bool qdev_hotplug = false; static bool qdev_hot_added = false; @@ -95,21 +96,31 @@ static void bus_add_child(BusState *bus, DeviceState *child) void qdev_set_parent_bus(DeviceState *dev, BusState *bus) { - bool replugging = dev->parent_bus != NULL; + BusState *old_parent_bus = dev->parent_bus; - if (replugging) { - /* Keep a reference to the device while it's not plugged into + if (old_parent_bus) { + trace_qdev_update_parent_bus(dev, object_get_typename(OBJECT(dev)), + old_parent_bus, object_get_typename(OBJECT(old_parent_bus)), + OBJECT(bus), object_get_typename(OBJECT(bus))); + /* + * Keep a reference to the device while it's not plugged into * any bus, to avoid it potentially evaporating when it is * dereffed in bus_remove_child(). + * Also keep the ref of the parent bus until the end, so that + * we can safely call resettable_change_parent() below. */ object_ref(OBJECT(dev)); bus_remove_child(dev->parent_bus, dev); - object_unref(OBJECT(dev->parent_bus)); } dev->parent_bus = bus; object_ref(OBJECT(bus)); bus_add_child(bus, dev); - if (replugging) { + if (dev->realized) { + resettable_change_parent(OBJECT(dev), OBJECT(bus), + OBJECT(old_parent_bus)); + } + if (old_parent_bus) { + object_unref(OBJECT(old_parent_bus)); object_unref(OBJECT(dev)); } } @@ -296,9 +307,21 @@ HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) return hotplug_ctrl; } +static int qdev_prereset(DeviceState *dev, void *opaque) +{ + trace_qdev_reset_tree(dev, object_get_typename(OBJECT(dev))); + return 0; +} + +static int qbus_prereset(BusState *bus, void *opaque) +{ + trace_qbus_reset_tree(bus, object_get_typename(OBJECT(bus))); + return 0; +} + static int qdev_reset_one(DeviceState *dev, void *opaque) { - device_reset(dev); + device_legacy_reset(dev); return 0; } @@ -306,6 +329,7 @@ static int qdev_reset_one(DeviceState *dev, void *opaque) static int qbus_reset_one(BusState *bus, void *opaque) { BusClass *bc = BUS_GET_CLASS(bus); + trace_qbus_reset(bus, object_get_typename(OBJECT(bus))); if (bc->reset) { bc->reset(bus); } @@ -314,7 +338,9 @@ static int qbus_reset_one(BusState *bus, void *opaque) void qdev_reset_all(DeviceState *dev) { - qdev_walk_children(dev, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL); + trace_qdev_reset_all(dev, object_get_typename(OBJECT(dev))); + qdev_walk_children(dev, qdev_prereset, qbus_prereset, + qdev_reset_one, qbus_reset_one, NULL); } void qdev_reset_all_fn(void *opaque) @@ -324,7 +350,9 @@ void qdev_reset_all_fn(void *opaque) void qbus_reset_all(BusState *bus) { - qbus_walk_children(bus, NULL, NULL, qdev_reset_one, qbus_reset_one, NULL); + trace_qbus_reset_all(bus, object_get_typename(OBJECT(bus))); + qbus_walk_children(bus, qdev_prereset, qbus_prereset, + qdev_reset_one, qbus_reset_one, NULL); } void qbus_reset_all_fn(void *opaque) @@ -333,6 +361,33 @@ void qbus_reset_all_fn(void *opaque) qbus_reset_all(bus); } +void device_cold_reset(DeviceState *dev) +{ + resettable_reset(OBJECT(dev), RESET_TYPE_COLD); +} + +bool device_is_in_reset(DeviceState *dev) +{ + return resettable_is_in_reset(OBJECT(dev)); +} + +static ResettableState *device_get_reset_state(Object *obj) +{ + DeviceState *dev = DEVICE(obj); + return &dev->reset; +} + +static void device_reset_child_foreach(Object *obj, ResettableChildCallback cb, + void *opaque, ResetType type) +{ + DeviceState *dev = DEVICE(obj); + BusState *bus; + + QLIST_FOREACH(bus, &dev->child_bus, sibling) { + cb(OBJECT(bus), opaque, type); + } +} + /* can be used as ->unplug() callback for the simple cases */ void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) @@ -859,6 +914,12 @@ static void device_set_realized(Object *obj, bool value, Error **errp) } } + /* + * Clear the reset state, in case the object was previously unrealized + * with a dirty state. + */ + resettable_state_clear(&dev->reset); + QLIST_FOREACH(bus, &dev->child_bus, sibling) { object_property_set_bool(OBJECT(bus), true, "realized", &local_err); @@ -867,7 +928,14 @@ static void device_set_realized(Object *obj, bool value, Error **errp) } } if (dev->hotplugged) { - device_reset(dev); + /* + * Reset the device, as well as its subtree which, at this point, + * should be realized too. + */ + resettable_assert_reset(OBJECT(dev), RESET_TYPE_COLD); + resettable_change_parent(OBJECT(dev), OBJECT(dev->parent_bus), + NULL); + resettable_release_reset(OBJECT(dev), RESET_TYPE_COLD); } dev->pending_deleted_event = false; @@ -1035,10 +1103,62 @@ device_vmstate_if_get_id(VMStateIf *obj) return qdev_get_dev_path(dev); } +/** + * device_phases_reset: + * Transition reset method for devices to allow moving + * smoothly from legacy reset method to multi-phases + */ +static void device_phases_reset(DeviceState *dev) +{ + ResettableClass *rc = RESETTABLE_GET_CLASS(dev); + + if (rc->phases.enter) { + rc->phases.enter(OBJECT(dev), RESET_TYPE_COLD); + } + if (rc->phases.hold) { + rc->phases.hold(OBJECT(dev)); + } + if (rc->phases.exit) { + rc->phases.exit(OBJECT(dev)); + } +} + +static void device_transitional_reset(Object *obj) +{ + DeviceClass *dc = DEVICE_GET_CLASS(obj); + + /* + * This will call either @device_phases_reset (for multi-phases transitioned + * devices) or a device's specific method for not-yet transitioned devices. + * In both case, it does not reset children. + */ + if (dc->reset) { + dc->reset(DEVICE(obj)); + } +} + +/** + * device_get_transitional_reset: + * check if the device's class is ready for multi-phase + */ +static ResettableTrFunction device_get_transitional_reset(Object *obj) +{ + DeviceClass *dc = DEVICE_GET_CLASS(obj); + if (dc->reset != device_phases_reset) { + /* + * dc->reset has been overridden by a subclass, + * the device is not ready for multi phase yet. + */ + return device_transitional_reset; + } + return NULL; +} + static void device_class_init(ObjectClass *class, void *data) { DeviceClass *dc = DEVICE_CLASS(class); VMStateIfClass *vc = VMSTATE_IF_CLASS(class); + ResettableClass *rc = RESETTABLE_CLASS(class); class->unparent = device_unparent; @@ -1051,6 +1171,24 @@ static void device_class_init(ObjectClass *class, void *data) dc->hotpluggable = true; dc->user_creatable = true; vc->get_id = device_vmstate_if_get_id; + rc->get_state = device_get_reset_state; + rc->child_foreach = device_reset_child_foreach; + + /* + * @device_phases_reset is put as the default reset method below, allowing + * to do the multi-phase transition from base classes to leaf classes. It + * allows a legacy-reset Device class to extend a multi-phases-reset + * Device class for the following reason: + * + If a base class B has been moved to multi-phase, then it does not + * override this default reset method and may have defined phase methods. + * + A child class C (extending class B) which uses + * device_class_set_parent_reset() (or similar means) to override the + * reset method will still work as expected. @device_phases_reset function + * will be registered as the parent reset method and effectively call + * parent reset phases. + */ + dc->reset = device_phases_reset; + rc->get_transitional_function = device_get_transitional_reset; object_class_property_add_bool(class, "realized", device_get_realized, device_set_realized, @@ -1101,10 +1239,11 @@ void device_class_set_parent_unrealize(DeviceClass *dc, dc->unrealize = dev_unrealize; } -void device_reset(DeviceState *dev) +void device_legacy_reset(DeviceState *dev) { DeviceClass *klass = DEVICE_GET_CLASS(dev); + trace_qdev_reset(dev, object_get_typename(OBJECT(dev))); if (klass->reset) { klass->reset(dev); } @@ -1134,6 +1273,7 @@ static const TypeInfo device_type_info = { .class_size = sizeof(DeviceClass), .interfaces = (InterfaceInfo[]) { { TYPE_VMSTATE_IF }, + { TYPE_RESETTABLE_INTERFACE }, { } } }; diff --git a/hw/core/resettable.c b/hw/core/resettable.c new file mode 100644 index 0000000000..96a99ce39e --- /dev/null +++ b/hw/core/resettable.c @@ -0,0 +1,301 @@ +/* + * Resettable interface. + * + * Copyright (c) 2019 GreenSocs SAS + * + * Authors: + * Damien Hedde + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/module.h" +#include "hw/resettable.h" +#include "trace.h" + +/** + * resettable_phase_enter/hold/exit: + * Function executing a phase recursively in a resettable object and its + * children. + */ +static void resettable_phase_enter(Object *obj, void *opaque, ResetType type); +static void resettable_phase_hold(Object *obj, void *opaque, ResetType type); +static void resettable_phase_exit(Object *obj, void *opaque, ResetType type); + +/** + * enter_phase_in_progress: + * True if we are currently in reset enter phase. + * + * exit_phase_in_progress: + * count the number of exit phase we are in. + * + * Note: These flags are only used to guarantee (using asserts) that the reset + * API is used correctly. We can use global variables because we rely on the + * iothread mutex to ensure only one reset operation is in a progress at a + * given time. + */ +static bool enter_phase_in_progress; +static unsigned exit_phase_in_progress; + +void resettable_reset(Object *obj, ResetType type) +{ + trace_resettable_reset(obj, type); + resettable_assert_reset(obj, type); + resettable_release_reset(obj, type); +} + +void resettable_assert_reset(Object *obj, ResetType type) +{ + /* TODO: change this assert when adding support for other reset types */ + assert(type == RESET_TYPE_COLD); + trace_resettable_reset_assert_begin(obj, type); + assert(!enter_phase_in_progress); + + enter_phase_in_progress = true; + resettable_phase_enter(obj, NULL, type); + enter_phase_in_progress = false; + + resettable_phase_hold(obj, NULL, type); + + trace_resettable_reset_assert_end(obj); +} + +void resettable_release_reset(Object *obj, ResetType type) +{ + /* TODO: change this assert when adding support for other reset types */ + assert(type == RESET_TYPE_COLD); + trace_resettable_reset_release_begin(obj, type); + assert(!enter_phase_in_progress); + + exit_phase_in_progress += 1; + resettable_phase_exit(obj, NULL, type); + exit_phase_in_progress -= 1; + + trace_resettable_reset_release_end(obj); +} + +bool resettable_is_in_reset(Object *obj) +{ + ResettableClass *rc = RESETTABLE_GET_CLASS(obj); + ResettableState *s = rc->get_state(obj); + + return s->count > 0; +} + +/** + * resettable_child_foreach: + * helper to avoid checking the existence of the method. + */ +static void resettable_child_foreach(ResettableClass *rc, Object *obj, + ResettableChildCallback cb, + void *opaque, ResetType type) +{ + if (rc->child_foreach) { + rc->child_foreach(obj, cb, opaque, type); + } +} + +/** + * resettable_get_tr_func: + * helper to fetch transitional reset callback if any. + */ +static ResettableTrFunction resettable_get_tr_func(ResettableClass *rc, + Object *obj) +{ + ResettableTrFunction tr_func = NULL; + if (rc->get_transitional_function) { + tr_func = rc->get_transitional_function(obj); + } + return tr_func; +} + +static void resettable_phase_enter(Object *obj, void *opaque, ResetType type) +{ + ResettableClass *rc = RESETTABLE_GET_CLASS(obj); + ResettableState *s = rc->get_state(obj); + const char *obj_typename = object_get_typename(obj); + bool action_needed = false; + + /* exit phase has to finish properly before entering back in reset */ + assert(!s->exit_phase_in_progress); + + trace_resettable_phase_enter_begin(obj, obj_typename, s->count, type); + + /* Only take action if we really enter reset for the 1st time. */ + /* + * TODO: if adding more ResetType support, some additional checks + * are probably needed here. + */ + if (s->count++ == 0) { + action_needed = true; + } + /* + * We limit the count to an arbitrary "big" value. The value is big + * enough not to be triggered normally. + * The assert will stop an infinite loop if there is a cycle in the + * reset tree. The loop goes through resettable_foreach_child below + * which at some point will call us again. + */ + assert(s->count <= 50); + + /* + * handle the children even if action_needed is at false so that + * child counts are incremented too + */ + resettable_child_foreach(rc, obj, resettable_phase_enter, NULL, type); + + /* execute enter phase for the object if needed */ + if (action_needed) { + trace_resettable_phase_enter_exec(obj, obj_typename, type, + !!rc->phases.enter); + if (rc->phases.enter && !resettable_get_tr_func(rc, obj)) { + rc->phases.enter(obj, type); + } + s->hold_phase_pending = true; + } + trace_resettable_phase_enter_end(obj, obj_typename, s->count); +} + +static void resettable_phase_hold(Object *obj, void *opaque, ResetType type) +{ + ResettableClass *rc = RESETTABLE_GET_CLASS(obj); + ResettableState *s = rc->get_state(obj); + const char *obj_typename = object_get_typename(obj); + + /* exit phase has to finish properly before entering back in reset */ + assert(!s->exit_phase_in_progress); + + trace_resettable_phase_hold_begin(obj, obj_typename, s->count, type); + + /* handle children first */ + resettable_child_foreach(rc, obj, resettable_phase_hold, NULL, type); + + /* exec hold phase */ + if (s->hold_phase_pending) { + s->hold_phase_pending = false; + ResettableTrFunction tr_func = resettable_get_tr_func(rc, obj); + trace_resettable_phase_hold_exec(obj, obj_typename, !!rc->phases.hold); + if (tr_func) { + trace_resettable_transitional_function(obj, obj_typename); + tr_func(obj); + } else if (rc->phases.hold) { + rc->phases.hold(obj); + } + } + trace_resettable_phase_hold_end(obj, obj_typename, s->count); +} + +static void resettable_phase_exit(Object *obj, void *opaque, ResetType type) +{ + ResettableClass *rc = RESETTABLE_GET_CLASS(obj); + ResettableState *s = rc->get_state(obj); + const char *obj_typename = object_get_typename(obj); + + assert(!s->exit_phase_in_progress); + trace_resettable_phase_exit_begin(obj, obj_typename, s->count, type); + + /* exit_phase_in_progress ensures this phase is 'atomic' */ + s->exit_phase_in_progress = true; + resettable_child_foreach(rc, obj, resettable_phase_exit, NULL, type); + + assert(s->count > 0); + if (s->count == 1) { + trace_resettable_phase_exit_exec(obj, obj_typename, !!rc->phases.exit); + if (rc->phases.exit && !resettable_get_tr_func(rc, obj)) { + rc->phases.exit(obj); + } + s->count = 0; + } + s->exit_phase_in_progress = false; + trace_resettable_phase_exit_end(obj, obj_typename, s->count); +} + +/* + * resettable_get_count: + * Get the count of the Resettable object @obj. Return 0 if @obj is NULL. + */ +static unsigned resettable_get_count(Object *obj) +{ + if (obj) { + ResettableClass *rc = RESETTABLE_GET_CLASS(obj); + return rc->get_state(obj)->count; + } + return 0; +} + +void resettable_change_parent(Object *obj, Object *newp, Object *oldp) +{ + ResettableClass *rc = RESETTABLE_GET_CLASS(obj); + ResettableState *s = rc->get_state(obj); + unsigned newp_count = resettable_get_count(newp); + unsigned oldp_count = resettable_get_count(oldp); + + /* + * Ensure we do not change parent when in enter or exit phase. + * During these phases, the reset subtree being updated is partly in reset + * and partly not in reset (it depends on the actual position in + * resettable_child_foreach()s). We are not able to tell in which part is a + * leaving or arriving device. Thus we cannot set the reset count of the + * moving device to the proper value. + */ + assert(!enter_phase_in_progress && !exit_phase_in_progress); + trace_resettable_change_parent(obj, oldp, oldp_count, newp, newp_count); + + /* + * At most one of the two 'for' loops will be executed below + * in order to cope with the difference between the two counts. + */ + /* if newp is more reset than oldp */ + for (unsigned i = oldp_count; i < newp_count; i++) { + resettable_assert_reset(obj, RESET_TYPE_COLD); + } + /* + * if obj is leaving a bus under reset, we need to ensure + * hold phase is not pending. + */ + if (oldp_count && s->hold_phase_pending) { + resettable_phase_hold(obj, NULL, RESET_TYPE_COLD); + } + /* if oldp is more reset than newp */ + for (unsigned i = newp_count; i < oldp_count; i++) { + resettable_release_reset(obj, RESET_TYPE_COLD); + } +} + +void resettable_cold_reset_fn(void *opaque) +{ + resettable_reset((Object *) opaque, RESET_TYPE_COLD); +} + +void resettable_class_set_parent_phases(ResettableClass *rc, + ResettableEnterPhase enter, + ResettableHoldPhase hold, + ResettableExitPhase exit, + ResettablePhases *parent_phases) +{ + *parent_phases = rc->phases; + if (enter) { + rc->phases.enter = enter; + } + if (hold) { + rc->phases.hold = hold; + } + if (exit) { + rc->phases.exit = exit; + } +} + +static const TypeInfo resettable_interface_info = { + .name = TYPE_RESETTABLE_INTERFACE, + .parent = TYPE_INTERFACE, + .class_size = sizeof(ResettableClass), +}; + +static void reset_register_types(void) +{ + type_register_static(&resettable_interface_info); +} + +type_init(reset_register_types) diff --git a/hw/core/trace-events b/hw/core/trace-events index fe47a9c8cb..aecd8e160e 100644 --- a/hw/core/trace-events +++ b/hw/core/trace-events @@ -1,2 +1,29 @@ # loader.c loader_write_rom(const char *name, uint64_t gpa, uint64_t size, bool isrom) "%s: @0x%"PRIx64" size=0x%"PRIx64" ROM=%d" + +# qdev.c +qdev_reset(void *obj, const char *objtype) "obj=%p(%s)" +qdev_reset_all(void *obj, const char *objtype) "obj=%p(%s)" +qdev_reset_tree(void *obj, const char *objtype) "obj=%p(%s)" +qbus_reset(void *obj, const char *objtype) "obj=%p(%s)" +qbus_reset_all(void *obj, const char *objtype) "obj=%p(%s)" +qbus_reset_tree(void *obj, const char *objtype) "obj=%p(%s)" +qdev_update_parent_bus(void *obj, const char *objtype, void *oldp, const char *oldptype, void *newp, const char *newptype) "obj=%p(%s) old_parent=%p(%s) new_parent=%p(%s)" + +# resettable.c +resettable_reset(void *obj, int cold) "obj=%p cold=%d" +resettable_reset_assert_begin(void *obj, int cold) "obj=%p cold=%d" +resettable_reset_assert_end(void *obj) "obj=%p" +resettable_reset_release_begin(void *obj, int cold) "obj=%p cold=%d" +resettable_reset_release_end(void *obj) "obj=%p" +resettable_change_parent(void *obj, void *o, unsigned oc, void *n, unsigned nc) "obj=%p from=%p(%d) to=%p(%d)" +resettable_phase_enter_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d" +resettable_phase_enter_exec(void *obj, const char *objtype, int type, int has_method) "obj=%p(%s) type=%d method=%d" +resettable_phase_enter_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d" +resettable_phase_hold_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d" +resettable_phase_hold_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d" +resettable_phase_hold_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d" +resettable_phase_exit_begin(void *obj, const char *objtype, unsigned count, int type) "obj=%p(%s) count=%d type=%d" +resettable_phase_exit_exec(void *obj, const char *objtype, int has_method) "obj=%p(%s) method=%d" +resettable_phase_exit_end(void *obj, const char *objtype, unsigned count) "obj=%p(%s) count=%d" +resettable_transitional_function(void *obj, const char *objtype) "obj=%p(%s)" |