xref: /openbmc/qemu/hw/core/reset.c (revision 86fae16ed298518ea851d6accc48643e6bdf8ed1)
1 /*
2  *  Reset handlers.
3  *
4  * Copyright (c) 2003-2008 Fabrice Bellard
5  * Copyright (c) 2016 Red Hat, Inc.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 
26 #include "qemu/osdep.h"
27 #include "qemu/queue.h"
28 #include "sysemu/reset.h"
29 #include "hw/resettable.h"
30 #include "hw/core/resetcontainer.h"
31 
32 /*
33  * Return a pointer to the singleton container that holds all the Resettable
34  * items that will be reset when qemu_devices_reset() is called.
35  */
36 static ResettableContainer *get_root_reset_container(void)
37 {
38     static ResettableContainer *root_reset_container;
39 
40     if (!root_reset_container) {
41         root_reset_container =
42             RESETTABLE_CONTAINER(object_new(TYPE_RESETTABLE_CONTAINER));
43     }
44     return root_reset_container;
45 }
46 
47 typedef struct QEMUResetEntry {
48     QTAILQ_ENTRY(QEMUResetEntry) entry;
49     QEMUResetHandler *func;
50     void *opaque;
51     bool skip_on_snapshot_load;
52 } QEMUResetEntry;
53 
54 static QTAILQ_HEAD(, QEMUResetEntry) reset_handlers =
55     QTAILQ_HEAD_INITIALIZER(reset_handlers);
56 
57 void qemu_register_reset(QEMUResetHandler *func, void *opaque)
58 {
59     QEMUResetEntry *re = g_new0(QEMUResetEntry, 1);
60 
61     re->func = func;
62     re->opaque = opaque;
63     QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
64 }
65 
66 void qemu_register_reset_nosnapshotload(QEMUResetHandler *func, void *opaque)
67 {
68     QEMUResetEntry *re = g_new0(QEMUResetEntry, 1);
69 
70     re->func = func;
71     re->opaque = opaque;
72     re->skip_on_snapshot_load = true;
73     QTAILQ_INSERT_TAIL(&reset_handlers, re, entry);
74 }
75 
76 void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
77 {
78     QEMUResetEntry *re;
79 
80     QTAILQ_FOREACH(re, &reset_handlers, entry) {
81         if (re->func == func && re->opaque == opaque) {
82             QTAILQ_REMOVE(&reset_handlers, re, entry);
83             g_free(re);
84             return;
85         }
86     }
87 }
88 
89 void qemu_register_resettable(Object *obj)
90 {
91     resettable_container_add(get_root_reset_container(), obj);
92 }
93 
94 void qemu_unregister_resettable(Object *obj)
95 {
96     resettable_container_remove(get_root_reset_container(), obj);
97 }
98 
99 void qemu_devices_reset(ShutdownCause reason)
100 {
101     QEMUResetEntry *re, *nre;
102 
103     /* reset all devices */
104     QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) {
105         if (reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD &&
106             re->skip_on_snapshot_load) {
107             continue;
108         }
109         re->func(re->opaque);
110     }
111 
112     /* Reset the simulation */
113     resettable_reset(OBJECT(get_root_reset_container()), RESET_TYPE_COLD);
114 }
115