aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/arm/boot.c2
-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
-rw-r--r--hw/microblaze/boot.c9
-rw-r--r--hw/nios2/boot.c9
-rw-r--r--hw/pci/msix.c3
-rw-r--r--hw/pci/pci.c2
-rw-r--r--hw/ppc/e500.c5
-rw-r--r--hw/ppc/spapr.c13
-rw-r--r--hw/ppc/spapr_nvdimm.c14
-rw-r--r--hw/ppc/virtex_ml507.c2
-rw-r--r--hw/riscv/sifive_u.c6
-rw-r--r--hw/riscv/virt.c6
-rw-r--r--hw/scsi/scsi-bus.c4
-rw-r--r--hw/usb/core.c2
-rw-r--r--hw/virtio/virtio-iommu.c2
-rw-r--r--hw/xtensa/xtfpga.c9
19 files changed, 114 insertions, 65 deletions
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 4d9d47ba1c..e56c42ac22 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -1299,7 +1299,7 @@ void arm_load_kernel(ARMCPU *cpu, MachineState *ms, struct arm_boot_info *info)
info->kernel_filename = ms->kernel_filename;
info->kernel_cmdline = ms->kernel_cmdline;
info->initrd_filename = ms->initrd_filename;
- info->dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
+ info->dtb_filename = ms->dtb;
info->dtb_limit = 0;
/* Load the kernel. */
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,
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 6715ba2ff9..caaba1aa4c 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -34,6 +34,7 @@
#include "sysemu/device_tree.h"
#include "sysemu/reset.h"
#include "sysemu/sysemu.h"
+#include "hw/boards.h"
#include "hw/loader.h"
#include "elf.h"
#include "qemu/cutils.h"
@@ -116,16 +117,14 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
const char *dtb_filename,
void (*machine_cpu_reset)(MicroBlazeCPU *))
{
- QemuOpts *machine_opts;
const char *kernel_filename;
const char *kernel_cmdline;
const char *dtb_arg;
char *filename = NULL;
- machine_opts = qemu_get_machine_opts();
- kernel_filename = qemu_opt_get(machine_opts, "kernel");
- kernel_cmdline = qemu_opt_get(machine_opts, "append");
- dtb_arg = qemu_opt_get(machine_opts, "dtb");
+ kernel_filename = current_machine->kernel_filename;
+ kernel_cmdline = current_machine->kernel_cmdline;
+ dtb_arg = current_machine->dtb;
/* default to pcbios dtb as passed by machine_init */
if (!dtb_arg && dtb_filename) {
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
diff --git a/hw/nios2/boot.c b/hw/nios2/boot.c
index 95a8697906..d9969ac148 100644
--- a/hw/nios2/boot.c
+++ b/hw/nios2/boot.c
@@ -39,6 +39,7 @@
#include "sysemu/device_tree.h"
#include "sysemu/reset.h"
#include "sysemu/sysemu.h"
+#include "hw/boards.h"
#include "hw/loader.h"
#include "elf.h"
@@ -120,16 +121,14 @@ void nios2_load_kernel(Nios2CPU *cpu, hwaddr ddr_base,
const char *dtb_filename,
void (*machine_cpu_reset)(Nios2CPU *))
{
- QemuOpts *machine_opts;
const char *kernel_filename;
const char *kernel_cmdline;
const char *dtb_arg;
char *filename = NULL;
- machine_opts = qemu_get_machine_opts();
- kernel_filename = qemu_opt_get(machine_opts, "kernel");
- kernel_cmdline = qemu_opt_get(machine_opts, "append");
- dtb_arg = qemu_opt_get(machine_opts, "dtb");
+ kernel_filename = current_machine->kernel_filename;
+ kernel_cmdline = current_machine->kernel_cmdline;
+ dtb_arg = current_machine->dtb;
/* default to pcbios dtb as passed by machine_init */
if (!dtb_arg) {
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, dtb_filename);
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index 67e34f34d6..36491ee52b 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -179,6 +179,7 @@ static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr,
{
PCIDevice *dev = opaque;
+ assert(addr + size <= dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
return pci_get_long(dev->msix_table + addr);
}
@@ -189,6 +190,8 @@ static void msix_table_mmio_write(void *opaque, hwaddr addr,
int vector = addr / PCI_MSIX_ENTRY_SIZE;
bool was_masked;
+ assert(addr + size <= dev->msix_entries_nr * PCI_MSIX_ENTRY_SIZE);
+
was_masked = msix_is_masked(dev, vector);
pci_set_long(dev->msix_table + addr, val);
msix_handle_mask_update(dev, vector, was_masked);
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 9424231542..d4349ea577 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1062,7 +1062,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev,
address_space_init(&pci_dev->bus_master_as,
&pci_dev->bus_master_container_region, pci_dev->name);
- if (qdev_hotplug) {
+ if (phase_check(PHASE_MACHINE_READY)) {
pci_init_bus_master(pci_dev);
}
pci_dev->irq_state = 0;
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 072e558c2d..c64b5d08bd 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -343,9 +343,8 @@ static int ppce500_load_device_tree(PPCE500MachineState *pms,
pmc->pci_pio_base >> 32, pmc->pci_pio_base,
0x0, 0x10000,
};
- QemuOpts *machine_opts = qemu_get_machine_opts();
- const char *dtb_file = qemu_opt_get(machine_opts, "dtb");
- const char *toplevel_compat = qemu_opt_get(machine_opts, "dt_compatible");
+ const char *dtb_file = machine->dtb;
+ const char *toplevel_compat = machine->dt_compatible;
if (dtb_file) {
char *filename;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index dee48a0043..489cefcb81 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -3275,6 +3275,19 @@ static void spapr_instance_init(Object *obj)
{
SpaprMachineState *spapr = SPAPR_MACHINE(obj);
SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+ MachineState *ms = MACHINE(spapr);
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
+
+ /*
+ * NVDIMM support went live in 5.1 without considering that, in
+ * other archs, the user needs to enable NVDIMM support with the
+ * 'nvdimm' machine option and the default behavior is NVDIMM
+ * support disabled. It is too late to roll back to the standard
+ * behavior without breaking 5.1 guests.
+ */
+ if (mc->nvdimm_supported) {
+ ms->nvdimms_state->is_enabled = true;
+ }
spapr->htab_fd = -1;
spapr->use_hotplug_event_source = true;
diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c
index 73ee006541..b46c36917c 100644
--- a/hw/ppc/spapr_nvdimm.c
+++ b/hw/ppc/spapr_nvdimm.c
@@ -27,10 +27,8 @@
#include "hw/ppc/spapr_nvdimm.h"
#include "hw/mem/nvdimm.h"
#include "qemu/nvdimm-utils.h"
-#include "qemu/option.h"
#include "hw/ppc/fdt.h"
#include "qemu/range.h"
-#include "sysemu/sysemu.h"
#include "hw/ppc/spapr_numa.h"
bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
@@ -38,7 +36,6 @@ bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
{
const MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
const MachineState *ms = MACHINE(hotplug_dev);
- const char *nvdimm_opt = qemu_opt_get(qemu_get_machine_opts(), "nvdimm");
g_autofree char *uuidstr = NULL;
QemuUUID uuid;
int ret;
@@ -48,16 +45,7 @@ bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm,
return false;
}
- /*
- * NVDIMM support went live in 5.1 without considering that, in
- * other archs, the user needs to enable NVDIMM support with the
- * 'nvdimm' machine option and the default behavior is NVDIMM
- * support disabled. It is too late to roll back to the standard
- * behavior without breaking 5.1 guests. What we can do is to
- * ensure that, if the user sets nvdimm=off, we error out
- * regardless of being 5.1 or newer.
- */
- if (!ms->nvdimms_state->is_enabled && nvdimm_opt) {
+ if (!ms->nvdimms_state->is_enabled) {
error_setg(errp, "nvdimm device found but 'nvdimm=off' was set");
return false;
}
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index 7f1bca928c..07fe49da0d 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -152,7 +152,7 @@ static int xilinx_load_device_tree(hwaddr addr,
int r;
const char *dtb_filename;
- dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
+ dtb_filename = current_machine->dtb;
if (dtb_filename) {
fdt = load_device_tree(dtb_filename, &fdt_size);
if (!fdt) {
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 2f19a9cda2..e7f6dc5fb3 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -100,14 +100,12 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
int cpu;
uint32_t *cells;
char *nodename;
- const char *dtb_filename;
char ethclk_names[] = "pclk\0hclk";
uint32_t plic_phandle, prci_phandle, gpio_phandle, phandle = 1;
uint32_t hfclk_phandle, rtcclk_phandle, phy_phandle;
- dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
- if (dtb_filename) {
- fdt = s->fdt = load_device_tree(dtb_filename, &s->fdt_size);
+ if (ms->dtb) {
+ fdt = s->fdt = load_device_tree(ms->dtb, &s->fdt_size);
if (!fdt) {
error_report("load_device_tree() failed");
exit(1);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 25cea7aa67..3cc18a76e7 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -181,7 +181,6 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
{
void *fdt;
int i, cpu, socket;
- const char *dtb_filename;
MachineState *mc = MACHINE(s);
uint64_t addr, size;
uint32_t *clint_cells, *plic_cells;
@@ -195,9 +194,8 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
- dtb_filename = qemu_opt_get(qemu_get_machine_opts(), "dtb");
- if (dtb_filename) {
- fdt = s->fdt = load_device_tree(dtb_filename, &s->fdt_size);
+ if (mc->dtb) {
+ fdt = s->fdt = load_device_tree(mc->dtb, &s->fdt_size);
if (!fdt) {
error_report("load_device_tree() failed");
exit(1);
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index b901e701f0..edb5c3492a 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -170,6 +170,8 @@ static void scsi_dma_restart_bh(void *opaque)
scsi_req_unref(req);
}
aio_context_release(blk_get_aio_context(s->conf.blk));
+ /* Drop the reference that was acquired in scsi_dma_restart_cb */
+ object_unref(OBJECT(s));
}
void scsi_req_retry(SCSIRequest *req)
@@ -188,6 +190,8 @@ static void scsi_dma_restart_cb(void *opaque, int running, RunState state)
}
if (!s->bh) {
AioContext *ctx = blk_get_aio_context(s->conf.blk);
+ /* The reference is dropped in scsi_dma_restart_bh.*/
+ object_ref(OBJECT(s));
s->bh = aio_bh_new(ctx, scsi_dma_restart_bh, s);
qemu_bh_schedule(s->bh);
}
diff --git a/hw/usb/core.c b/hw/usb/core.c
index 5234dcc73f..e960036f4d 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -97,7 +97,7 @@ void usb_wakeup(USBEndpoint *ep, unsigned int stream)
USBDevice *dev = ep->dev;
USBBus *bus = usb_bus_from_device(dev);
- if (!qdev_hotplug) {
+ if (!phase_check(PHASE_MACHINE_READY)) {
/*
* This is machine init cold plug. No need to wakeup anyone,
* all devices will be reset anyway. And trying to wakeup can
diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c
index cea8811295..6b9ef7f6b2 100644
--- a/hw/virtio/virtio-iommu.c
+++ b/hw/virtio/virtio-iommu.c
@@ -930,7 +930,7 @@ static int virtio_iommu_set_page_size_mask(IOMMUMemoryRegion *mr,
* accept it. Having a different masks is possible but the guest will use
* sub-optimal block sizes, so warn about it.
*/
- if (qdev_hotplug) {
+ if (phase_check(PHASE_MACHINE_READY)) {
int new_granule = ctz64(new_mask);
int cur_granule = ctz64(cur_mask);
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index b1470b88e6..7be53f1895 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -233,11 +233,10 @@ static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine)
qemu_irq *extints;
DriveInfo *dinfo;
PFlashCFI01 *flash = NULL;
- QemuOpts *machine_opts = qemu_get_machine_opts();
- const char *kernel_filename = qemu_opt_get(machine_opts, "kernel");
- const char *kernel_cmdline = qemu_opt_get(machine_opts, "append");
- const char *dtb_filename = qemu_opt_get(machine_opts, "dtb");
- const char *initrd_filename = qemu_opt_get(machine_opts, "initrd");
+ const char *kernel_filename = machine->kernel_filename;
+ const char *kernel_cmdline = machine->kernel_cmdline;
+ const char *dtb_filename = machine->dtb;
+ const char *initrd_filename = machine->initrd_filename;
const unsigned system_io_size = 224 * MiB;
uint32_t freq = 10000000;
int n;