12f7b92a0SPaolo Bonzini /* 22f7b92a0SPaolo Bonzini * Reset handlers. 32f7b92a0SPaolo Bonzini * 42f7b92a0SPaolo Bonzini * Copyright (c) 2003-2008 Fabrice Bellard 52f7b92a0SPaolo Bonzini * Copyright (c) 2016 Red Hat, Inc. 62f7b92a0SPaolo Bonzini * 72f7b92a0SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy 82f7b92a0SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal 92f7b92a0SPaolo Bonzini * in the Software without restriction, including without limitation the rights 102f7b92a0SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 112f7b92a0SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is 122f7b92a0SPaolo Bonzini * furnished to do so, subject to the following conditions: 132f7b92a0SPaolo Bonzini * 142f7b92a0SPaolo Bonzini * The above copyright notice and this permission notice shall be included in 152f7b92a0SPaolo Bonzini * all copies or substantial portions of the Software. 162f7b92a0SPaolo Bonzini * 172f7b92a0SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 182f7b92a0SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 192f7b92a0SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 202f7b92a0SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 212f7b92a0SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 222f7b92a0SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 232f7b92a0SPaolo Bonzini * THE SOFTWARE. 242f7b92a0SPaolo Bonzini */ 252f7b92a0SPaolo Bonzini 262f7b92a0SPaolo Bonzini #include "qemu/osdep.h" 272f7b92a0SPaolo Bonzini #include "sysemu/reset.h" 2886fae16eSPeter Maydell #include "hw/resettable.h" 2986fae16eSPeter Maydell #include "hw/core/resetcontainer.h" 302f7b92a0SPaolo Bonzini 3186fae16eSPeter Maydell /* 3286fae16eSPeter Maydell * Return a pointer to the singleton container that holds all the Resettable 3386fae16eSPeter Maydell * items that will be reset when qemu_devices_reset() is called. 3486fae16eSPeter Maydell */ 3586fae16eSPeter Maydell static ResettableContainer *get_root_reset_container(void) 3686fae16eSPeter Maydell { 3786fae16eSPeter Maydell static ResettableContainer *root_reset_container; 3886fae16eSPeter Maydell 3986fae16eSPeter Maydell if (!root_reset_container) { 4086fae16eSPeter Maydell root_reset_container = 4186fae16eSPeter Maydell RESETTABLE_CONTAINER(object_new(TYPE_RESETTABLE_CONTAINER)); 4286fae16eSPeter Maydell } 4386fae16eSPeter Maydell return root_reset_container; 4486fae16eSPeter Maydell } 452f7b92a0SPaolo Bonzini 4671b3ea37SPeter Maydell /* 4771b3ea37SPeter Maydell * This is an Object which implements Resettable simply to call the 4871b3ea37SPeter Maydell * callback function in the hold phase. 4971b3ea37SPeter Maydell */ 5071b3ea37SPeter Maydell #define TYPE_LEGACY_RESET "legacy-reset" 5171b3ea37SPeter Maydell OBJECT_DECLARE_SIMPLE_TYPE(LegacyReset, LEGACY_RESET) 5271b3ea37SPeter Maydell 5371b3ea37SPeter Maydell struct LegacyReset { 5471b3ea37SPeter Maydell Object parent; 5571b3ea37SPeter Maydell ResettableState reset_state; 562f7b92a0SPaolo Bonzini QEMUResetHandler *func; 572f7b92a0SPaolo Bonzini void *opaque; 587966d70fSJason A. Donenfeld bool skip_on_snapshot_load; 5971b3ea37SPeter Maydell }; 602f7b92a0SPaolo Bonzini 6171b3ea37SPeter Maydell OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(LegacyReset, legacy_reset, LEGACY_RESET, OBJECT, { TYPE_RESETTABLE_INTERFACE }, { }) 6271b3ea37SPeter Maydell 6371b3ea37SPeter Maydell static ResettableState *legacy_reset_get_state(Object *obj) 6471b3ea37SPeter Maydell { 6571b3ea37SPeter Maydell LegacyReset *lr = LEGACY_RESET(obj); 6671b3ea37SPeter Maydell return &lr->reset_state; 6771b3ea37SPeter Maydell } 6871b3ea37SPeter Maydell 69ad80e367SPeter Maydell static void legacy_reset_hold(Object *obj, ResetType type) 7071b3ea37SPeter Maydell { 7171b3ea37SPeter Maydell LegacyReset *lr = LEGACY_RESET(obj); 7271b3ea37SPeter Maydell 73631f46d4SPeter Maydell if (type == RESET_TYPE_SNAPSHOT_LOAD && lr->skip_on_snapshot_load) { 7471b3ea37SPeter Maydell return; 7571b3ea37SPeter Maydell } 7671b3ea37SPeter Maydell lr->func(lr->opaque); 7771b3ea37SPeter Maydell } 7871b3ea37SPeter Maydell 7971b3ea37SPeter Maydell static void legacy_reset_init(Object *obj) 8071b3ea37SPeter Maydell { 8171b3ea37SPeter Maydell } 8271b3ea37SPeter Maydell 8371b3ea37SPeter Maydell static void legacy_reset_finalize(Object *obj) 8471b3ea37SPeter Maydell { 8571b3ea37SPeter Maydell } 8671b3ea37SPeter Maydell 8771b3ea37SPeter Maydell static void legacy_reset_class_init(ObjectClass *klass, void *data) 8871b3ea37SPeter Maydell { 8971b3ea37SPeter Maydell ResettableClass *rc = RESETTABLE_CLASS(klass); 9071b3ea37SPeter Maydell 9171b3ea37SPeter Maydell rc->get_state = legacy_reset_get_state; 9271b3ea37SPeter Maydell rc->phases.hold = legacy_reset_hold; 9371b3ea37SPeter Maydell } 942f7b92a0SPaolo Bonzini 952f7b92a0SPaolo Bonzini void qemu_register_reset(QEMUResetHandler *func, void *opaque) 962f7b92a0SPaolo Bonzini { 9771b3ea37SPeter Maydell Object *obj = object_new(TYPE_LEGACY_RESET); 9871b3ea37SPeter Maydell LegacyReset *lr = LEGACY_RESET(obj); 992f7b92a0SPaolo Bonzini 10071b3ea37SPeter Maydell lr->func = func; 10171b3ea37SPeter Maydell lr->opaque = opaque; 10271b3ea37SPeter Maydell qemu_register_resettable(obj); 1032f7b92a0SPaolo Bonzini } 1042f7b92a0SPaolo Bonzini 1057966d70fSJason A. Donenfeld void qemu_register_reset_nosnapshotload(QEMUResetHandler *func, void *opaque) 1067966d70fSJason A. Donenfeld { 10771b3ea37SPeter Maydell Object *obj = object_new(TYPE_LEGACY_RESET); 10871b3ea37SPeter Maydell LegacyReset *lr = LEGACY_RESET(obj); 1097966d70fSJason A. Donenfeld 11071b3ea37SPeter Maydell lr->func = func; 11171b3ea37SPeter Maydell lr->opaque = opaque; 11271b3ea37SPeter Maydell lr->skip_on_snapshot_load = true; 11371b3ea37SPeter Maydell qemu_register_resettable(obj); 11471b3ea37SPeter Maydell } 11571b3ea37SPeter Maydell 11671b3ea37SPeter Maydell typedef struct FindLegacyInfo { 11771b3ea37SPeter Maydell QEMUResetHandler *func; 11871b3ea37SPeter Maydell void *opaque; 11971b3ea37SPeter Maydell LegacyReset *lr; 12071b3ea37SPeter Maydell } FindLegacyInfo; 12171b3ea37SPeter Maydell 12271b3ea37SPeter Maydell static void find_legacy_reset_cb(Object *obj, void *opaque, ResetType type) 12371b3ea37SPeter Maydell { 12471b3ea37SPeter Maydell LegacyReset *lr; 12571b3ea37SPeter Maydell FindLegacyInfo *fli = opaque; 12671b3ea37SPeter Maydell 12771b3ea37SPeter Maydell /* Not everything in the ResettableContainer will be a LegacyReset */ 12871b3ea37SPeter Maydell lr = LEGACY_RESET(object_dynamic_cast(obj, TYPE_LEGACY_RESET)); 12971b3ea37SPeter Maydell if (lr && lr->func == fli->func && lr->opaque == fli->opaque) { 13071b3ea37SPeter Maydell fli->lr = lr; 13171b3ea37SPeter Maydell } 13271b3ea37SPeter Maydell } 13371b3ea37SPeter Maydell 13471b3ea37SPeter Maydell static LegacyReset *find_legacy_reset(QEMUResetHandler *func, void *opaque) 13571b3ea37SPeter Maydell { 13671b3ea37SPeter Maydell /* 13771b3ea37SPeter Maydell * Find the LegacyReset with the specified func and opaque, 13871b3ea37SPeter Maydell * by getting the ResettableContainer to call our callback for 13971b3ea37SPeter Maydell * every item in it. 14071b3ea37SPeter Maydell */ 14171b3ea37SPeter Maydell ResettableContainer *rootcon = get_root_reset_container(); 14271b3ea37SPeter Maydell ResettableClass *rc = RESETTABLE_GET_CLASS(rootcon); 14371b3ea37SPeter Maydell FindLegacyInfo fli; 14471b3ea37SPeter Maydell 14571b3ea37SPeter Maydell fli.func = func; 14671b3ea37SPeter Maydell fli.opaque = opaque; 14771b3ea37SPeter Maydell fli.lr = NULL; 14871b3ea37SPeter Maydell rc->child_foreach(OBJECT(rootcon), find_legacy_reset_cb, 14971b3ea37SPeter Maydell &fli, RESET_TYPE_COLD); 15071b3ea37SPeter Maydell return fli.lr; 1517966d70fSJason A. Donenfeld } 1527966d70fSJason A. Donenfeld 1532f7b92a0SPaolo Bonzini void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) 1542f7b92a0SPaolo Bonzini { 15571b3ea37SPeter Maydell Object *obj = OBJECT(find_legacy_reset(func, opaque)); 1562f7b92a0SPaolo Bonzini 15771b3ea37SPeter Maydell if (obj) { 15871b3ea37SPeter Maydell qemu_unregister_resettable(obj); 15971b3ea37SPeter Maydell object_unref(obj); 1602f7b92a0SPaolo Bonzini } 1612f7b92a0SPaolo Bonzini } 1622f7b92a0SPaolo Bonzini 16386fae16eSPeter Maydell void qemu_register_resettable(Object *obj) 16486fae16eSPeter Maydell { 16586fae16eSPeter Maydell resettable_container_add(get_root_reset_container(), obj); 16686fae16eSPeter Maydell } 16786fae16eSPeter Maydell 16886fae16eSPeter Maydell void qemu_unregister_resettable(Object *obj) 16986fae16eSPeter Maydell { 17086fae16eSPeter Maydell resettable_container_remove(get_root_reset_container(), obj); 17186fae16eSPeter Maydell } 17286fae16eSPeter Maydell 173*1b063fe2SJuraj Marcin void qemu_devices_reset(ResetType type) 1742f7b92a0SPaolo Bonzini { 17586fae16eSPeter Maydell /* Reset the simulation */ 176631f46d4SPeter Maydell resettable_reset(OBJECT(get_root_reset_container()), type); 17786fae16eSPeter Maydell } 178