]>
Commit | Line | Data |
---|---|---|
bc5a39bf DH |
1 | /* |
2 | * Resettable interface header. | |
3 | * | |
4 | * Copyright (c) 2019 GreenSocs SAS | |
5 | * | |
6 | * Authors: | |
7 | * Damien Hedde | |
8 | * | |
9 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
10 | * See the COPYING file in the top-level directory. | |
11 | */ | |
12 | ||
13 | #ifndef HW_RESETTABLE_H | |
14 | #define HW_RESETTABLE_H | |
15 | ||
16 | #include "qom/object.h" | |
17 | ||
18 | #define TYPE_RESETTABLE_INTERFACE "resettable" | |
19 | ||
db1015e9 | 20 | typedef struct ResettableClass ResettableClass; |
bc5a39bf DH |
21 | #define RESETTABLE_CLASS(class) \ |
22 | OBJECT_CLASS_CHECK(ResettableClass, (class), TYPE_RESETTABLE_INTERFACE) | |
23 | ||
24 | #define RESETTABLE_GET_CLASS(obj) \ | |
25 | OBJECT_GET_CLASS(ResettableClass, (obj), TYPE_RESETTABLE_INTERFACE) | |
26 | ||
27 | typedef struct ResettableState ResettableState; | |
28 | ||
29 | /** | |
30 | * ResetType: | |
31 | * Types of reset. | |
32 | * | |
33 | * + Cold: reset resulting from a power cycle of the object. | |
34 | * | |
35 | * TODO: Support has to be added to handle more types. In particular, | |
36 | * ResettableState structure needs to be expanded. | |
37 | */ | |
38 | typedef enum ResetType { | |
39 | RESET_TYPE_COLD, | |
40 | } ResetType; | |
41 | ||
42 | /* | |
43 | * ResettableClass: | |
44 | * Interface for resettable objects. | |
45 | * | |
46 | * See docs/devel/reset.rst for more detailed information about how QEMU models | |
47 | * reset. This whole API must only be used when holding the iothread mutex. | |
48 | * | |
49 | * All objects which can be reset must implement this interface; | |
50 | * it is usually provided by a base class such as DeviceClass or BusClass. | |
51 | * Every Resettable object must maintain some state tracking the | |
52 | * progress of a reset operation by providing a ResettableState structure. | |
53 | * The functions defined in this module take care of updating the | |
54 | * state of the reset. | |
55 | * The base class implementation of the interface provides this | |
56 | * state and implements the associated method: get_state. | |
57 | * | |
58 | * Concrete object implementations (typically specific devices | |
59 | * such as a UART model) should provide the functions | |
60 | * for the phases.enter, phases.hold and phases.exit methods, which | |
61 | * they can set in their class init function, either directly or | |
62 | * by calling resettable_class_set_parent_phases(). | |
63 | * The phase methods are guaranteed to only only ever be called once | |
64 | * for any reset event, in the order 'enter', 'hold', 'exit'. | |
65 | * An object will always move quickly from 'enter' to 'hold' | |
66 | * but might remain in 'hold' for an arbitrary period of time | |
67 | * before eventually reset is deasserted and the 'exit' phase is called. | |
68 | * Object implementations should be prepared for functions handling | |
69 | * inbound connections from other devices (such as qemu_irq handler | |
70 | * functions) to be called at any point during reset after their | |
71 | * 'enter' method has been called. | |
72 | * | |
73 | * Users of a resettable object should not call these methods | |
74 | * directly, but instead use the function resettable_reset(). | |
75 | * | |
76 | * @phases.enter: This phase is called when the object enters reset. It | |
77 | * should reset local state of the object, but it must not do anything that | |
78 | * has a side-effect on other objects, such as raising or lowering a qemu_irq | |
79 | * line or reading or writing guest memory. It takes the reset's type as | |
80 | * argument. | |
81 | * | |
82 | * @phases.hold: This phase is called for entry into reset, once every object | |
83 | * in the system which is being reset has had its @phases.enter method called. | |
84 | * At this point devices can do actions that affect other objects. | |
85 | * | |
86 | * @phases.exit: This phase is called when the object leaves the reset state. | |
87 | * Actions affecting other objects are permitted. | |
88 | * | |
89 | * @get_state: Mandatory method which must return a pointer to a | |
90 | * ResettableState. | |
91 | * | |
92 | * @get_transitional_function: transitional method to handle Resettable objects | |
93 | * not yet fully moved to this interface. It will be removed as soon as it is | |
94 | * not needed anymore. This method is optional and may return a pointer to a | |
95 | * function to be used instead of the phases. If the method exists and returns | |
96 | * a non-NULL function pointer then that function is executed as a replacement | |
97 | * of the 'hold' phase method taking the object as argument. The two other phase | |
98 | * methods are not executed. | |
99 | * | |
100 | * @child_foreach: Executes a given callback on every Resettable child. Child | |
101 | * in this context means a child in the qbus tree, so the children of a qbus | |
102 | * are the devices on it, and the children of a device are all the buses it | |
103 | * owns. This is not the same as the QOM object hierarchy. The function takes | |
104 | * additional opaque and ResetType arguments which must be passed unmodified to | |
105 | * the callback. | |
106 | */ | |
107 | typedef void (*ResettableEnterPhase)(Object *obj, ResetType type); | |
108 | typedef void (*ResettableHoldPhase)(Object *obj); | |
109 | typedef void (*ResettableExitPhase)(Object *obj); | |
110 | typedef ResettableState * (*ResettableGetState)(Object *obj); | |
111 | typedef void (*ResettableTrFunction)(Object *obj); | |
112 | typedef ResettableTrFunction (*ResettableGetTrFunction)(Object *obj); | |
113 | typedef void (*ResettableChildCallback)(Object *, void *opaque, | |
114 | ResetType type); | |
115 | typedef void (*ResettableChildForeach)(Object *obj, | |
116 | ResettableChildCallback cb, | |
117 | void *opaque, ResetType type); | |
118 | typedef struct ResettablePhases { | |
119 | ResettableEnterPhase enter; | |
120 | ResettableHoldPhase hold; | |
121 | ResettableExitPhase exit; | |
122 | } ResettablePhases; | |
db1015e9 | 123 | struct ResettableClass { |
bc5a39bf DH |
124 | InterfaceClass parent_class; |
125 | ||
126 | /* Phase methods */ | |
127 | ResettablePhases phases; | |
128 | ||
129 | /* State access method */ | |
130 | ResettableGetState get_state; | |
131 | ||
132 | /* Transitional method for legacy reset compatibility */ | |
133 | ResettableGetTrFunction get_transitional_function; | |
134 | ||
135 | /* Hierarchy handling method */ | |
136 | ResettableChildForeach child_foreach; | |
db1015e9 | 137 | }; |
bc5a39bf DH |
138 | |
139 | /** | |
140 | * ResettableState: | |
141 | * Structure holding reset related state. The fields should not be accessed | |
142 | * directly; the definition is here to allow further inclusion into other | |
143 | * objects. | |
144 | * | |
145 | * @count: Number of reset level the object is into. It is incremented when | |
146 | * the reset operation starts and decremented when it finishes. | |
147 | * @hold_phase_pending: flag which indicates that we need to invoke the 'hold' | |
148 | * phase handler for this object. | |
149 | * @exit_phase_in_progress: true if we are currently in the exit phase | |
150 | */ | |
151 | struct ResettableState { | |
152 | unsigned count; | |
153 | bool hold_phase_pending; | |
154 | bool exit_phase_in_progress; | |
155 | }; | |
156 | ||
e755e127 DH |
157 | /** |
158 | * resettable_state_clear: | |
159 | * Clear the state. It puts the state to the initial (zeroed) state required | |
160 | * to reuse an object. Typically used in realize step of base classes | |
161 | * implementing the interface. | |
162 | */ | |
163 | static inline void resettable_state_clear(ResettableState *state) | |
164 | { | |
165 | memset(state, 0, sizeof(ResettableState)); | |
166 | } | |
167 | ||
bc5a39bf DH |
168 | /** |
169 | * resettable_reset: | |
170 | * Trigger a reset on an object @obj of type @type. @obj must implement | |
171 | * Resettable interface. | |
172 | * | |
173 | * Calling this function is equivalent to calling @resettable_assert_reset() | |
174 | * then @resettable_release_reset(). | |
175 | */ | |
176 | void resettable_reset(Object *obj, ResetType type); | |
177 | ||
178 | /** | |
179 | * resettable_assert_reset: | |
180 | * Put an object @obj into reset. @obj must implement Resettable interface. | |
181 | * | |
182 | * @resettable_release_reset() must eventually be called after this call. | |
183 | * There must be one call to @resettable_release_reset() per call of | |
184 | * @resettable_assert_reset(), with the same type argument. | |
185 | * | |
186 | * NOTE: Until support for migration is added, the @resettable_release_reset() | |
187 | * must not be delayed. It must occur just after @resettable_assert_reset() so | |
188 | * that migration cannot be triggered in between. Prefer using | |
189 | * @resettable_reset() for now. | |
190 | */ | |
191 | void resettable_assert_reset(Object *obj, ResetType type); | |
192 | ||
193 | /** | |
194 | * resettable_release_reset: | |
195 | * Release the object @obj from reset. @obj must implement Resettable interface. | |
196 | * | |
197 | * See @resettable_assert_reset() description for details. | |
198 | */ | |
199 | void resettable_release_reset(Object *obj, ResetType type); | |
200 | ||
201 | /** | |
202 | * resettable_is_in_reset: | |
203 | * Return true if @obj is under reset. | |
204 | * | |
205 | * @obj must implement Resettable interface. | |
206 | */ | |
207 | bool resettable_is_in_reset(Object *obj); | |
208 | ||
614f731a DH |
209 | /** |
210 | * resettable_change_parent: | |
211 | * Indicate that the parent of Ressettable @obj is changing from @oldp to @newp. | |
212 | * All 3 objects must implement resettable interface. @oldp or @newp may be | |
213 | * NULL. | |
214 | * | |
215 | * This function will adapt the reset state of @obj so that it is coherent | |
216 | * with the reset state of @newp. It may trigger @resettable_assert_reset() | |
217 | * or @resettable_release_reset(). It will do such things only if the reset | |
218 | * state of @newp and @oldp are different. | |
219 | * | |
220 | * When using this function during reset, it must only be called during | |
221 | * a hold phase method. Calling this during enter or exit phase is an error. | |
222 | */ | |
223 | void resettable_change_parent(Object *obj, Object *newp, Object *oldp); | |
224 | ||
abb89dbf DH |
225 | /** |
226 | * resettable_cold_reset_fn: | |
227 | * Helper to call resettable_reset((Object *) opaque, RESET_TYPE_COLD). | |
228 | * | |
229 | * This function is typically useful to register a reset handler with | |
230 | * qemu_register_reset. | |
231 | */ | |
232 | void resettable_cold_reset_fn(void *opaque); | |
233 | ||
bc5a39bf DH |
234 | /** |
235 | * resettable_class_set_parent_phases: | |
236 | * | |
237 | * Save @rc current reset phases into @parent_phases and override @rc phases | |
238 | * by the given new methods (@enter, @hold and @exit). | |
239 | * Each phase is overridden only if the new one is not NULL allowing to | |
240 | * override a subset of phases. | |
241 | */ | |
242 | void resettable_class_set_parent_phases(ResettableClass *rc, | |
243 | ResettableEnterPhase enter, | |
244 | ResettableHoldPhase hold, | |
245 | ResettableExitPhase exit, | |
246 | ResettablePhases *parent_phases); | |
247 | ||
248 | #endif |