mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 04:13:53 -06:00

We pass a ResetType argument to the Resettable class enter phase method, but we don't pass it to hold and exit, even though the callsites have it readily available. This means that if a device cared about the ResetType it would need to record it in the enter phase method to use later on. Pass the type to all three of the phase methods to avoid having to do that. Commit created with for dir in hw target include; do \ spatch --macro-file scripts/cocci-macro-file.h \ --sp-file scripts/coccinelle/reset-type.cocci \ --keep-comments --smpl-spacing --in-place \ --include-headers --dir $dir; done and no manual edits. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@amd.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Luc Michel <luc.michel@amd.com> Message-id: 20240412160809.1260625-5-peter.maydell@linaro.org
187 lines
5.3 KiB
C
187 lines
5.3 KiB
C
/*
|
|
* Reset handlers.
|
|
*
|
|
* Copyright (c) 2003-2008 Fabrice Bellard
|
|
* Copyright (c) 2016 Red Hat, Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
* THE SOFTWARE.
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "sysemu/reset.h"
|
|
#include "hw/resettable.h"
|
|
#include "hw/core/resetcontainer.h"
|
|
|
|
/*
|
|
* Return a pointer to the singleton container that holds all the Resettable
|
|
* items that will be reset when qemu_devices_reset() is called.
|
|
*/
|
|
static ResettableContainer *get_root_reset_container(void)
|
|
{
|
|
static ResettableContainer *root_reset_container;
|
|
|
|
if (!root_reset_container) {
|
|
root_reset_container =
|
|
RESETTABLE_CONTAINER(object_new(TYPE_RESETTABLE_CONTAINER));
|
|
}
|
|
return root_reset_container;
|
|
}
|
|
|
|
/*
|
|
* Reason why the currently in-progress qemu_devices_reset() was called.
|
|
* If we made at least SHUTDOWN_CAUSE_SNAPSHOT_LOAD have a corresponding
|
|
* ResetType we could perhaps avoid the need for this global.
|
|
*/
|
|
static ShutdownCause device_reset_reason;
|
|
|
|
/*
|
|
* This is an Object which implements Resettable simply to call the
|
|
* callback function in the hold phase.
|
|
*/
|
|
#define TYPE_LEGACY_RESET "legacy-reset"
|
|
OBJECT_DECLARE_SIMPLE_TYPE(LegacyReset, LEGACY_RESET)
|
|
|
|
struct LegacyReset {
|
|
Object parent;
|
|
ResettableState reset_state;
|
|
QEMUResetHandler *func;
|
|
void *opaque;
|
|
bool skip_on_snapshot_load;
|
|
};
|
|
|
|
OBJECT_DEFINE_SIMPLE_TYPE_WITH_INTERFACES(LegacyReset, legacy_reset, LEGACY_RESET, OBJECT, { TYPE_RESETTABLE_INTERFACE }, { })
|
|
|
|
static ResettableState *legacy_reset_get_state(Object *obj)
|
|
{
|
|
LegacyReset *lr = LEGACY_RESET(obj);
|
|
return &lr->reset_state;
|
|
}
|
|
|
|
static void legacy_reset_hold(Object *obj, ResetType type)
|
|
{
|
|
LegacyReset *lr = LEGACY_RESET(obj);
|
|
|
|
if (device_reset_reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD &&
|
|
lr->skip_on_snapshot_load) {
|
|
return;
|
|
}
|
|
lr->func(lr->opaque);
|
|
}
|
|
|
|
static void legacy_reset_init(Object *obj)
|
|
{
|
|
}
|
|
|
|
static void legacy_reset_finalize(Object *obj)
|
|
{
|
|
}
|
|
|
|
static void legacy_reset_class_init(ObjectClass *klass, void *data)
|
|
{
|
|
ResettableClass *rc = RESETTABLE_CLASS(klass);
|
|
|
|
rc->get_state = legacy_reset_get_state;
|
|
rc->phases.hold = legacy_reset_hold;
|
|
}
|
|
|
|
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
|
|
{
|
|
Object *obj = object_new(TYPE_LEGACY_RESET);
|
|
LegacyReset *lr = LEGACY_RESET(obj);
|
|
|
|
lr->func = func;
|
|
lr->opaque = opaque;
|
|
qemu_register_resettable(obj);
|
|
}
|
|
|
|
void qemu_register_reset_nosnapshotload(QEMUResetHandler *func, void *opaque)
|
|
{
|
|
Object *obj = object_new(TYPE_LEGACY_RESET);
|
|
LegacyReset *lr = LEGACY_RESET(obj);
|
|
|
|
lr->func = func;
|
|
lr->opaque = opaque;
|
|
lr->skip_on_snapshot_load = true;
|
|
qemu_register_resettable(obj);
|
|
}
|
|
|
|
typedef struct FindLegacyInfo {
|
|
QEMUResetHandler *func;
|
|
void *opaque;
|
|
LegacyReset *lr;
|
|
} FindLegacyInfo;
|
|
|
|
static void find_legacy_reset_cb(Object *obj, void *opaque, ResetType type)
|
|
{
|
|
LegacyReset *lr;
|
|
FindLegacyInfo *fli = opaque;
|
|
|
|
/* Not everything in the ResettableContainer will be a LegacyReset */
|
|
lr = LEGACY_RESET(object_dynamic_cast(obj, TYPE_LEGACY_RESET));
|
|
if (lr && lr->func == fli->func && lr->opaque == fli->opaque) {
|
|
fli->lr = lr;
|
|
}
|
|
}
|
|
|
|
static LegacyReset *find_legacy_reset(QEMUResetHandler *func, void *opaque)
|
|
{
|
|
/*
|
|
* Find the LegacyReset with the specified func and opaque,
|
|
* by getting the ResettableContainer to call our callback for
|
|
* every item in it.
|
|
*/
|
|
ResettableContainer *rootcon = get_root_reset_container();
|
|
ResettableClass *rc = RESETTABLE_GET_CLASS(rootcon);
|
|
FindLegacyInfo fli;
|
|
|
|
fli.func = func;
|
|
fli.opaque = opaque;
|
|
fli.lr = NULL;
|
|
rc->child_foreach(OBJECT(rootcon), find_legacy_reset_cb,
|
|
&fli, RESET_TYPE_COLD);
|
|
return fli.lr;
|
|
}
|
|
|
|
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque)
|
|
{
|
|
Object *obj = OBJECT(find_legacy_reset(func, opaque));
|
|
|
|
if (obj) {
|
|
qemu_unregister_resettable(obj);
|
|
object_unref(obj);
|
|
}
|
|
}
|
|
|
|
void qemu_register_resettable(Object *obj)
|
|
{
|
|
resettable_container_add(get_root_reset_container(), obj);
|
|
}
|
|
|
|
void qemu_unregister_resettable(Object *obj)
|
|
{
|
|
resettable_container_remove(get_root_reset_container(), obj);
|
|
}
|
|
|
|
void qemu_devices_reset(ShutdownCause reason)
|
|
{
|
|
device_reset_reason = reason;
|
|
|
|
/* Reset the simulation */
|
|
resettable_reset(OBJECT(get_root_reset_container()), RESET_TYPE_COLD);
|
|
}
|