diff options
Diffstat (limited to 'hw/core')
-rw-r--r-- | hw/core/machine-qmp-cmds.c | 7 | ||||
-rw-r--r-- | hw/core/machine.c | 54 | ||||
-rw-r--r-- | hw/core/meson.build | 2 | ||||
-rw-r--r-- | hw/core/qdev.c | 28 |
4 files changed, 70 insertions, 21 deletions
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c index 5362c80a18..87f14140a3 100644 --- a/hw/core/machine-qmp-cmds.c +++ b/hw/core/machine-qmp-cmds.c @@ -286,10 +286,9 @@ HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp) void qmp_set_numa_node(NumaOptions *cmd, Error **errp) { - if (!runstate_check(RUN_STATE_PRECONFIG)) { - error_setg(errp, "The command is permitted only in '%s' state", - RunState_str(RUN_STATE_PRECONFIG)); - return; + if (phase_check(PHASE_MACHINE_INITIALIZED)) { + error_setg(errp, "The command is permitted only before the machine has been created"); + return; } set_numa_options(MACHINE(qdev_get_machine()), cmd, errp); diff --git a/hw/core/machine.c b/hw/core/machine.c index d7f8fdee45..05dcaf09c9 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -16,16 +16,21 @@ #include "sysemu/replay.h" #include "qemu/units.h" #include "hw/boards.h" +#include "hw/loader.h" #include "qapi/error.h" #include "qapi/qapi-visit-common.h" #include "qapi/visitor.h" #include "hw/sysbus.h" +#include "sysemu/cpus.h" #include "sysemu/sysemu.h" +#include "sysemu/reset.h" +#include "sysemu/runstate.h" #include "sysemu/numa.h" #include "qemu/error-report.h" #include "sysemu/qtest.h" #include "hw/pci/pci.h" #include "hw/mem/nvdimm.h" +#include "migration/global_state.h" #include "migration/vmstate.h" GlobalProperty hw_compat_5_2[] = {}; @@ -216,6 +221,8 @@ GlobalProperty hw_compat_2_1[] = { }; const size_t hw_compat_2_1_len = G_N_ELEMENTS(hw_compat_2_1); +MachineState *current_machine; + static char *machine_get_kernel(Object *obj, Error **errp) { MachineState *ms = MACHINE(obj); @@ -1167,17 +1174,16 @@ void machine_run_board_init(MachineState *machine) } machine_class->init(machine); + phase_advance(PHASE_MACHINE_INITIALIZED); } static NotifierList machine_init_done_notifiers = NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers); -bool machine_init_done; - void qemu_add_machine_init_done_notifier(Notifier *notify) { notifier_list_add(&machine_init_done_notifiers, notify); - if (machine_init_done) { + if (phase_check(PHASE_MACHINE_READY)) { notify->notify(notify, NULL); } } @@ -1187,10 +1193,48 @@ void qemu_remove_machine_init_done_notifier(Notifier *notify) notifier_remove(notify); } -void qemu_run_machine_init_done_notifiers(void) +void qdev_machine_creation_done(void) { - machine_init_done = true; + cpu_synchronize_all_post_init(); + + if (current_machine->boot_once) { + qemu_boot_set(current_machine->boot_once, &error_fatal); + qemu_register_reset(restore_boot_order, g_strdup(current_machine->boot_order)); + } + + /* + * ok, initial machine setup is done, starting from now we can + * only create hotpluggable devices + */ + phase_advance(PHASE_MACHINE_READY); + qdev_assert_realized_properly(); + + /* TODO: once all bus devices are qdevified, this should be done + * when bus is created by qdev.c */ + /* + * TODO: If we had a main 'reset container' that the whole system + * lived in, we could reset that using the multi-phase reset + * APIs. For the moment, we just reset the sysbus, which will cause + * all devices hanging off it (and all their child buses, recursively) + * to be reset. Note that this will *not* reset any Device objects + * which are not attached to some part of the qbus tree! + */ + qemu_register_reset(resettable_cold_reset_fn, sysbus_get_default()); + notifier_list_notify(&machine_init_done_notifiers, NULL); + + if (rom_check_and_register_reset() != 0) { + exit(1); + } + + replay_start(); + + /* This checkpoint is required by replay to separate prior clock + reading from the other reads, because timer polling functions query + clock values from the log. */ + replay_checkpoint(CHECKPOINT_RESET); + qemu_system_reset(SHUTDOWN_CAUSE_NONE); + register_global_state(); } static const TypeInfo machine_info = { diff --git a/hw/core/meson.build b/hw/core/meson.build index 4a744f3b5e..032576f571 100644 --- a/hw/core/meson.build +++ b/hw/core/meson.build @@ -1,7 +1,6 @@ # core qdev-related obj files, also used by *-user and unit tests hwcore_files = files( 'bus.c', - 'fw-path-provider.c', 'hotplug.c', 'qdev-properties.c', 'qdev.c', @@ -25,6 +24,7 @@ common_ss.add(when: 'CONFIG_SPLIT_IRQ', if_true: files('split-irq.c')) common_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('stream.c')) softmmu_ss.add(files( + 'fw-path-provider.c', 'loader.c', 'machine-hmp-cmds.c', 'machine.c', diff --git a/hw/core/qdev.c b/hw/core/qdev.c index d3611e7c03..cefc5eaa0a 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -41,7 +41,6 @@ #include "migration/vmstate.h" #include "trace.h" -bool qdev_hotplug = false; static bool qdev_hot_added = false; bool qdev_hot_removed = false; @@ -404,7 +403,7 @@ void qdev_unrealize(DeviceState *dev) object_property_set_bool(OBJECT(dev), "realized", false, &error_abort); } -static int qdev_assert_realized_properly(Object *obj, void *opaque) +static int qdev_assert_realized_properly_cb(Object *obj, void *opaque) { DeviceState *dev = DEVICE(object_dynamic_cast(obj, TYPE_DEVICE)); DeviceClass *dc; @@ -417,16 +416,10 @@ static int qdev_assert_realized_properly(Object *obj, void *opaque) return 0; } -void qdev_machine_creation_done(void) +void qdev_assert_realized_properly(void) { - /* - * ok, initial machine setup is done, starting from now we can - * only create hotpluggable devices - */ - qdev_hotplug = true; - object_child_foreach_recursive(object_get_root(), - qdev_assert_realized_properly, NULL); + qdev_assert_realized_properly_cb, NULL); } bool qdev_machine_modified(void) @@ -911,7 +904,7 @@ static void device_initfn(Object *obj) { DeviceState *dev = DEVICE(obj); - if (qdev_hotplug) { + if (phase_check(PHASE_MACHINE_READY)) { dev->hotplugged = 1; qdev_hot_added = true; } @@ -1144,6 +1137,19 @@ Object *qdev_get_machine(void) return dev; } +static MachineInitPhase machine_phase; + +bool phase_check(MachineInitPhase phase) +{ + return machine_phase >= phase; +} + +void phase_advance(MachineInitPhase phase) +{ + assert(machine_phase == phase - 1); + machine_phase = phase; +} + static const TypeInfo device_type_info = { .name = TYPE_DEVICE, .parent = TYPE_OBJECT, |