summaryrefslogtreecommitdiff
path: root/include/hw/resettable.h
blob: bdcd1276b695ad648f641ae7e9c747189710a38d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
/*
 * Resettable interface header.
 *
 * 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.
 */

#ifndef HW_RESETTABLE_H
#define HW_RESETTABLE_H

#include "qom/object.h"

#define TYPE_RESETTABLE_INTERFACE "resettable"

typedef struct ResettableClass ResettableClass;
DECLARE_CLASS_CHECKERS(ResettableClass, RESETTABLE,
                       TYPE_RESETTABLE_INTERFACE)


typedef struct ResettableState ResettableState;

/**
 * ResetType:
 * Types of reset.
 *
 * + Cold: reset resulting from a power cycle of the object.
 *
 * TODO: Support has to be added to handle more types. In particular,
 * ResettableState structure needs to be expanded.
 */
typedef enum ResetType {
    RESET_TYPE_COLD,
} ResetType;

/*
 * ResettableClass:
 * Interface for resettable objects.
 *
 * See docs/devel/reset.rst for more detailed information about how QEMU models
 * reset. This whole API must only be used when holding the iothread mutex.
 *
 * All objects which can be reset must implement this interface;
 * it is usually provided by a base class such as DeviceClass or BusClass.
 * Every Resettable object must maintain some state tracking the
 * progress of a reset operation by providing a ResettableState structure.
 * The functions defined in this module take care of updating the
 * state of the reset.
 * The base class implementation of the interface provides this
 * state and implements the associated method: get_state.
 *
 * Concrete object implementations (typically specific devices
 * such as a UART model) should provide the functions
 * for the phases.enter, phases.hold and phases.exit methods, which
 * they can set in their class init function, either directly or
 * by calling resettable_class_set_parent_phases().
 * The phase methods are guaranteed to only only ever be called once
 * for any reset event, in the order 'enter', 'hold', 'exit'.
 * An object will always move quickly from 'enter' to 'hold'
 * but might remain in 'hold' for an arbitrary period of time
 * before eventually reset is deasserted and the 'exit' phase is called.
 * Object implementations should be prepared for functions handling
 * inbound connections from other devices (such as qemu_irq handler
 * functions) to be called at any point during reset after their
 * 'enter' method has been called.
 *
 * Users of a resettable object should not call these methods
 * directly, but instead use the function resettable_reset().
 *
 * @phases.enter: This phase is called when the object enters reset. It
 * should reset local state of the object, but it must not do anything that
 * has a side-effect on other objects, such as raising or lowering a qemu_irq
 * line or reading or writing guest memory. It takes the reset's type as
 * argument.
 *
 * @phases.hold: This phase is called for entry into reset, once every object
 * in the system which is being reset has had its @phases.enter method called.
 * At this point devices can do actions that affect other objects.
 *
 * @phases.exit: This phase is called when the object leaves the reset state.
 * Actions affecting other objects are permitted.
 *
 * @get_state: Mandatory method which must return a pointer to a
 * ResettableState.
 *
 * @get_transitional_function: transitional method to handle Resettable objects
 * not yet fully moved to this interface. It will be removed as soon as it is
 * not needed anymore. This method is optional and may return a pointer to a
 * function to be used instead of the phases. If the method exists and returns
 * a non-NULL function pointer then that function is executed as a replacement
 * of the 'hold' phase method taking the object as argument. The two other phase
 * methods are not executed.
 *
 * @child_foreach: Executes a given callback on every Resettable child. Child
 * in this context means a child in the qbus tree, so the children of a qbus
 * are the devices on it, and the children of a device are all the buses it
 * owns. This is not the same as the QOM object hierarchy. The function takes
 * additional opaque and ResetType arguments which must be passed unmodified to
 * the callback.
 */
typedef void (*ResettableEnterPhase)(Object *obj, ResetType type);
typedef void (*ResettableHoldPhase)(Object *obj);
typedef void (*ResettableExitPhase)(Object *obj);
typedef ResettableState * (*ResettableGetState)(Object *obj);
typedef void (*ResettableTrFunction)(Object *obj);
typedef ResettableTrFunction (*ResettableGetTrFunction)(Object *obj);
typedef void (*ResettableChildCallback)(Object *, void *opaque,
                                        ResetType type);
typedef void (*ResettableChildForeach)(Object *obj,
                                       ResettableChildCallback cb,
                                       void *opaque, ResetType type);
typedef struct ResettablePhases {
    ResettableEnterPhase enter;
    ResettableHoldPhase hold;
    ResettableExitPhase exit;
} ResettablePhases;
struct ResettableClass {
    InterfaceClass parent_class;

    /* Phase methods */
    ResettablePhases phases;

    /* State access method */
    ResettableGetState get_state;

    /* Transitional method for legacy reset compatibility */
    ResettableGetTrFunction get_transitional_function;

    /* Hierarchy handling method */
    ResettableChildForeach child_foreach;
};

/**
 * ResettableState:
 * Structure holding reset related state. The fields should not be accessed
 * directly; the definition is here to allow further inclusion into other
 * objects.
 *
 * @count: Number of reset level the object is into. It is incremented when
 * the reset operation starts and decremented when it finishes.
 * @hold_phase_pending: flag which indicates that we need to invoke the 'hold'
 * phase handler for this object.
 * @exit_phase_in_progress: true if we are currently in the exit phase
 */
struct ResettableState {
    unsigned count;
    bool hold_phase_pending;
    bool exit_phase_in_progress;
};

/**
 * resettable_state_clear:
 * Clear the state. It puts the state to the initial (zeroed) state required
 * to reuse an object. Typically used in realize step of base classes
 * implementing the interface.
 */
static inline void resettable_state_clear(ResettableState *state)
{
    memset(state, 0, sizeof(ResettableState));
}

/**
 * resettable_reset:
 * Trigger a reset on an object @obj of type @type. @obj must implement
 * Resettable interface.
 *
 * Calling this function is equivalent to calling @resettable_assert_reset()
 * then @resettable_release_reset().
 */
void resettable_reset(Object *obj, ResetType type);

/**
 * resettable_assert_reset:
 * Put an object @obj into reset. @obj must implement Resettable interface.
 *
 * @resettable_release_reset() must eventually be called after this call.
 * There must be one call to @resettable_release_reset() per call of
 * @resettable_assert_reset(), with the same type argument.
 *
 * NOTE: Until support for migration is added, the @resettable_release_reset()
 * must not be delayed. It must occur just after @resettable_assert_reset() so
 * that migration cannot be triggered in between. Prefer using
 * @resettable_reset() for now.
 */
void resettable_assert_reset(Object *obj, ResetType type);

/**
 * resettable_release_reset:
 * Release the object @obj from reset. @obj must implement Resettable interface.
 *
 * See @resettable_assert_reset() description for details.
 */
void resettable_release_reset(Object *obj, ResetType type);

/**
 * resettable_is_in_reset:
 * Return true if @obj is under reset.
 *
 * @obj must implement Resettable interface.
 */
bool resettable_is_in_reset(Object *obj);

/**
 * resettable_change_parent:
 * Indicate that the parent of Ressettable @obj is changing from @oldp to @newp.
 * All 3 objects must implement resettable interface. @oldp or @newp may be
 * NULL.
 *
 * This function will adapt the reset state of @obj so that it is coherent
 * with the reset state of @newp. It may trigger @resettable_assert_reset()
 * or @resettable_release_reset(). It will do such things only if the reset
 * state of @newp and @oldp are different.
 *
 * When using this function during reset, it must only be called during
 * a hold phase method. Calling this during enter or exit phase is an error.
 */
void resettable_change_parent(Object *obj, Object *newp, Object *oldp);

/**
 * resettable_cold_reset_fn:
 * Helper to call resettable_reset((Object *) opaque, RESET_TYPE_COLD).
 *
 * This function is typically useful to register a reset handler with
 * qemu_register_reset.
 */
void resettable_cold_reset_fn(void *opaque);

/**
 * resettable_class_set_parent_phases:
 *
 * Save @rc current reset phases into @parent_phases and override @rc phases
 * by the given new methods (@enter, @hold and @exit).
 * Each phase is overridden only if the new one is not NULL allowing to
 * override a subset of phases.
 */
void resettable_class_set_parent_phases(ResettableClass *rc,
                                        ResettableEnterPhase enter,
                                        ResettableHoldPhase hold,
                                        ResettableExitPhase exit,
                                        ResettablePhases *parent_phases);

#endif