INIT phase of the global ResetDomain now triggers the legacy reset handlers. *qemu_devices_reset* is now equivalent to do a cold reset of the global ResetDomain.
Signed-off-by: Damien Hedde <damien.he...@greensocs.com> --- hw/core/reset.c | 109 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 95 insertions(+), 14 deletions(-) diff --git a/hw/core/reset.c b/hw/core/reset.c index d013c9feb9..1b25f9c8f8 100644 --- a/hw/core/reset.c +++ b/hw/core/reset.c @@ -26,9 +26,31 @@ #include "qemu/osdep.h" #include "qemu/queue.h" +#include "qemu/module.h" #include "sysemu/reset.h" #include "hw/reset-domain.h" +#define TYPE_SYSTEM_RESET_DOMAIN "system-reset-domain" +#define SYSTEM_RESET_DOMAIN(obj) \ + OBJECT_CHECK(SystemResetDomain, (obj), TYPE_SYSTEM_RESET_DOMAIN) +#define SYSTEM_RESET_DOMAIN_CLASS(class) \ + OBJECT_CLASS_CHECK(SystemResetDomainClass, (class), \ + TYPE_SYSTEM_RESET_DOMAIN) +#define SYSTEM_RESET_DOMAIN_GET_CLASS(obj) \ + OBJECT_GET_CLASS(SystemResetDomainClass, (obj), \ + TYPE_SYSTEM_RESET_DOMAIN) + +/** + * SystemResetDomainClass: + * Class to hold the global reset domain and handlers + * @parent_init_phase hold parent init_phase method + */ +typedef struct SystemResetDomainClass { + ResetDomainClass parent_class; + + ResettableInitPhase parent_init_phase; +} SystemResetDomainClass; + /* reset/shutdown handler */ typedef struct QEMUResetEntry { @@ -37,27 +59,35 @@ typedef struct QEMUResetEntry { void *opaque; } QEMUResetEntry; -static QTAILQ_HEAD(, QEMUResetEntry) reset_handlers = - QTAILQ_HEAD_INITIALIZER(reset_handlers); +/** + * SystemResetDomain: + * @reset_handlers list of legacy reset handlers + */ +typedef struct SystemResetDomain { + ResetDomain parent_obj; + + QTAILQ_HEAD(, QEMUResetEntry) reset_handlers; +} SystemResetDomain; /* global/system reset domain */ -static ResetDomain *reset_domain; +static SystemResetDomain *reset_domain; -static ResetDomain *get_reset_domain(void) +static SystemResetDomain *get_reset_domain(void) { if (reset_domain == NULL) { + Object *obj = object_new(TYPE_SYSTEM_RESET_DOMAIN); /* * the ref to the object will be deleted by * qemu_delete_system_reset_domain function below. */ - reset_domain = RESET_DOMAIN(object_new(TYPE_RESET_DOMAIN)); + reset_domain = SYSTEM_RESET_DOMAIN(obj); } return reset_domain; } ResetDomain *qemu_get_system_reset_domain(void) { - return get_reset_domain(); + return RESET_DOMAIN(get_reset_domain()); } void qemu_delete_system_reset_domain(void) @@ -71,34 +101,36 @@ void qemu_delete_system_reset_domain(void) void qemu_register_system_reset_domain_object(Object *obj) { - ResetDomain *domain = get_reset_domain(); + ResetDomain *domain = RESET_DOMAIN(get_reset_domain()); reset_domain_register_object(domain, obj); } void qemu_unregister_system_reset_domain_object(Object *obj) { - ResetDomain *domain = get_reset_domain(); + ResetDomain *domain = RESET_DOMAIN(get_reset_domain()); reset_domain_unregister_object(domain, obj); } void qemu_register_reset(QEMUResetHandler *func, void *opaque) { + SystemResetDomain *domain = get_reset_domain(); QEMUResetEntry *re = g_malloc0(sizeof(QEMUResetEntry)); re->func = func; re->opaque = opaque; - QTAILQ_INSERT_TAIL(&reset_handlers, re, entry); + QTAILQ_INSERT_TAIL(&domain->reset_handlers, re, entry); } void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) { + SystemResetDomain *domain = get_reset_domain(); QEMUResetEntry *re; - QTAILQ_FOREACH(re, &reset_handlers, entry) { + QTAILQ_FOREACH(re, &domain->reset_handlers, entry) { if (re->func == func && re->opaque == opaque) { - QTAILQ_REMOVE(&reset_handlers, re, entry); + QTAILQ_REMOVE(&domain->reset_handlers, re, entry); g_free(re); return; } @@ -112,15 +144,64 @@ void qemu_devices_reset(void) void qemu_system_reset_domain_reset(bool cold) { - ResetDomain *domain = get_reset_domain(); + resettable_reset(OBJECT(get_reset_domain()), cold); +} + +static void system_reset_domain_init_phase(Object *obj, bool cold) +{ + SystemResetDomain *domain = SYSTEM_RESET_DOMAIN(obj); + SystemResetDomainClass *srdc = SYSTEM_RESET_DOMAIN_GET_CLASS(obj); QEMUResetEntry *re, *nre; /* call function handlers first */ - QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) { + QTAILQ_FOREACH_SAFE(re, &domain->reset_handlers, entry, nre) { re->func(re->opaque); } /* then handle the objects in the ResetDomain */ - resettable_reset(OBJECT(domain), cold); + srdc->parent_init_phase(OBJECT(domain), cold); +} + +static void system_reset_domain_init(Object *obj) +{ + SystemResetDomain *domain = SYSTEM_RESET_DOMAIN(obj); + + QTAILQ_INIT(&domain->reset_handlers); +} + +static void system_reset_domain_finalize(Object *obj) +{ + SystemResetDomain *domain = SYSTEM_RESET_DOMAIN(obj); + QEMUResetEntry *re, *nre; + + QTAILQ_FOREACH_SAFE(re, &domain->reset_handlers, entry, nre) { + QTAILQ_REMOVE(&domain->reset_handlers, re, entry); + g_free(re); + } +} + +static void system_reset_domain_class_init(ObjectClass *class, void *data) +{ + ResettableClass *rc = RESETTABLE_CLASS(class); + SystemResetDomainClass *srdc = SYSTEM_RESET_DOMAIN_CLASS(class); + + srdc->parent_init_phase = rc->phases.init; + rc->phases.init = system_reset_domain_init_phase; +} + +static const TypeInfo system_reset_domain_type_info = { + .name = TYPE_SYSTEM_RESET_DOMAIN, + .parent = TYPE_RESET_DOMAIN, + .instance_size = sizeof(SystemResetDomain), + .instance_init = system_reset_domain_init, + .instance_finalize = system_reset_domain_finalize, + .class_init = system_reset_domain_class_init, + .class_size = sizeof(SystemResetDomainClass), +}; + +static void system_reset_register_types(void) +{ + type_register_static(&system_reset_domain_type_info); } +type_init(system_reset_register_types) -- 2.21.0