summaryrefslogtreecommitdiffstats
path: root/hw/core
diff options
context:
space:
mode:
Diffstat (limited to 'hw/core')
-rw-r--r--hw/core/machine-qmp-cmds.c7
-rw-r--r--hw/core/machine.c54
-rw-r--r--hw/core/meson.build2
-rw-r--r--hw/core/qdev.c28
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,