@@ -958,7 +958,6 @@ static void create_fdt_uart(RISCVVirtState *s, const MemMapEntry *memmap,
qemu_fdt_setprop_cells(ms->fdt, name, "interrupts", UART0_IRQ, 0x4);
}
- qemu_fdt_add_subnode(ms->fdt, "/chosen");
qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", name);
g_free(name);
}
@@ -1019,11 +1018,29 @@ static void create_fdt_fw_cfg(RISCVVirtState *s, const MemMapEntry *memmap)
g_free(nodename);
}
-static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap)
+static void finalize_fdt(RISCVVirtState *s)
{
- MachineState *ms = MACHINE(s);
uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1;
uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1;
+
+ create_fdt_sockets(s, virt_memmap, &phandle, &irq_mmio_phandle,
+ &irq_pcie_phandle, &irq_virtio_phandle,
+ &msi_pcie_phandle);
+
+ create_fdt_virtio(s, virt_memmap, irq_virtio_phandle);
+
+ create_fdt_pcie(s, virt_memmap, irq_pcie_phandle, msi_pcie_phandle);
+
+ create_fdt_reset(s, virt_memmap, &phandle);
+
+ create_fdt_uart(s, virt_memmap, irq_mmio_phandle);
+
+ create_fdt_rtc(s, virt_memmap, irq_mmio_phandle);
+}
+
+static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap)
+{
+ MachineState *ms = MACHINE(s);
uint8_t rng_seed[32];
ms->fdt = create_device_tree(&s->fdt_size);
@@ -1043,28 +1060,16 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap)
qemu_fdt_setprop_cell(ms->fdt, "/soc", "#size-cells", 0x2);
qemu_fdt_setprop_cell(ms->fdt, "/soc", "#address-cells", 0x2);
- create_fdt_sockets(s, memmap, &phandle, &irq_mmio_phandle,
- &irq_pcie_phandle, &irq_virtio_phandle,
- &msi_pcie_phandle);
-
- create_fdt_virtio(s, memmap, irq_virtio_phandle);
-
- create_fdt_pcie(s, memmap, irq_pcie_phandle, msi_pcie_phandle);
-
- create_fdt_reset(s, memmap, &phandle);
-
- create_fdt_uart(s, memmap, irq_mmio_phandle);
-
- create_fdt_rtc(s, memmap, irq_mmio_phandle);
-
- create_fdt_flash(s, memmap);
- create_fdt_fw_cfg(s, memmap);
- create_fdt_pmu(s);
+ qemu_fdt_add_subnode(ms->fdt, "/chosen");
/* Pass seed to RNG */
qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
qemu_fdt_setprop(ms->fdt, "/chosen", "rng-seed",
rng_seed, sizeof(rng_seed));
+
+ create_fdt_flash(s, memmap);
+ create_fdt_fw_cfg(s, memmap);
+ create_fdt_pmu(s);
}
static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem,
@@ -1249,15 +1254,12 @@ static void virt_machine_done(Notifier *notifier, void *data)
uint64_t kernel_entry = 0;
BlockBackend *pflash_blk0;
- /* load/create device tree */
- if (machine->dtb) {
- machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
- if (!machine->fdt) {
- error_report("load_device_tree() failed");
- exit(1);
- }
- } else {
- create_fdt(s, memmap);
+ /*
+ * An user provided dtb must include everything, including
+ * dynamic sysbus devices. Our FDT needs to be finalized.
+ */
+ if (machine->dtb == NULL) {
+ finalize_fdt(s);
}
/*
@@ -1525,6 +1527,17 @@ static void virt_machine_init(MachineState *machine)
}
virt_flash_map(s, system_memory);
+ /* load/create device tree */
+ if (machine->dtb) {
+ machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
+ if (!machine->fdt) {
+ error_report("load_device_tree() failed");
+ exit(1);
+ }
+ } else {
+ create_fdt(s, memmap);
+ }
+
s->machine_done.notify = virt_machine_done;
qemu_add_machine_init_done_notifier(&s->machine_done);
}