phase_until() is implemented in vl.c and is meant to be used to make startup progress up to a specified phase being reached(). At this point, no behavior change is introduced: phase_until() only supports a single double transition corresponding to the functionality of qmp_exit_preconfig(): + accel-created -> machine-initialized -> machine-ready
As a result qmp_exit_preconfig() now uses phase_until(). This commit is a preparation to support cold plugging a device using qapi command (which will be introduced in a following commit). For this we need fine grain control of the phase. Signed-off-by: Damien Hedde <damien.he...@greensocs.com> --- v5: + refactor to avoid indentation change --- include/hw/qdev-core.h | 14 +++++++++++++ softmmu/vl.c | 46 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index e29c705b74..5f73d06408 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -909,4 +909,18 @@ extern bool phase_check(MachineInitPhase phase); */ extern void phase_advance(MachineInitPhase phase); +/** + * @phase_until: + * @phase: the target phase + * @errp: error report + * + * Make the machine init progress until the target phase is reached. + * + * Its is a no-op is the target phase is the current or an earlier + * phase. + * + * Returns true in case of success. + */ +extern bool phase_until(MachineInitPhase phase, Error **errp); + #endif diff --git a/softmmu/vl.c b/softmmu/vl.c index 84a31eba76..7f8d15b5b8 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2702,11 +2702,17 @@ void qmp_x_exit_preconfig(Error **errp) error_setg(errp, "The command is permitted only before machine initialization"); return; } + phase_until(PHASE_MACHINE_READY, errp); +} +static void qemu_phase_ready(Error **errp) +{ qemu_init_board(); + /* phase is now PHASE_MACHINE_INITIALIZED. */ qemu_create_cli_devices(); cxl_fixed_memory_window_link_targets(errp); qemu_machine_creation_done(); + /* Phase is now PHASE_MACHINE_READY. */ if (loadvm) { load_snapshot(loadvm, NULL, false, NULL, &error_fatal); @@ -2729,6 +2735,46 @@ void qmp_x_exit_preconfig(Error **errp) } } +bool phase_until(MachineInitPhase phase, Error **errp) +{ + ERRP_GUARD(); + if (!phase_check(PHASE_ACCEL_CREATED)) { + error_setg(errp, "Phase transition is not supported until accelerator" + " is created"); + return false; + } + + while (!phase_check(phase)) { + MachineInitPhase cur_phase = phase_get(); + + switch (cur_phase) { + case PHASE_ACCEL_CREATED: + qemu_phase_ready(errp); + break; + + default: + /* + * If we end up here, it is because we miss a case above. + */ + error_setg(&error_abort, "Requested phase transition is not" + " implemented"); + return false; + } + + if (*errp) { + return false; + } + + /* + * Ensure we made some progress. + * With the default case above, it should be enough to prevent + * any infinite loop. + */ + assert(cur_phase < phase_get()); + } + return true; +} + void qemu_init(int argc, char **argv, char **envp) { QemuOpts *opts; -- 2.36.1