aboutsummaryrefslogtreecommitdiff
path: root/hw/riscv
diff options
context:
space:
mode:
Diffstat (limited to 'hw/riscv')
-rw-r--r--hw/riscv/virt.c191
1 files changed, 101 insertions, 90 deletions
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 643fee2..f849052 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1162,6 +1162,100 @@ static DeviceState *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
return aplic_m;
}
+static void virt_machine_done(Notifier *notifier, void *data)
+{
+ RISCVVirtState *s = container_of(notifier, RISCVVirtState,
+ machine_done);
+ const MemMapEntry *memmap = virt_memmap;
+ MachineState *machine = MACHINE(s);
+ target_ulong start_addr = memmap[VIRT_DRAM].base;
+ target_ulong firmware_end_addr, kernel_start_addr;
+ uint32_t fdt_load_addr;
+ uint64_t kernel_entry;
+
+ /*
+ * Only direct boot kernel is currently supported for KVM VM,
+ * so the "-bios" parameter is not supported when KVM is enabled.
+ */
+ if (kvm_enabled()) {
+ if (machine->firmware) {
+ if (strcmp(machine->firmware, "none")) {
+ error_report("Machine mode firmware is not supported in "
+ "combination with KVM.");
+ exit(1);
+ }
+ } else {
+ machine->firmware = g_strdup("none");
+ }
+ }
+
+ if (riscv_is_32bit(&s->soc[0])) {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ RISCV32_BIOS_BIN, start_addr, NULL);
+ } else {
+ firmware_end_addr = riscv_find_and_load_firmware(machine,
+ RISCV64_BIOS_BIN, start_addr, NULL);
+ }
+
+ if (machine->kernel_filename) {
+ kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0],
+ firmware_end_addr);
+
+ kernel_entry = riscv_load_kernel(machine->kernel_filename,
+ kernel_start_addr, NULL);
+
+ if (machine->initrd_filename) {
+ hwaddr start;
+ hwaddr end = riscv_load_initrd(machine->initrd_filename,
+ machine->ram_size, kernel_entry,
+ &start);
+ qemu_fdt_setprop_cell(machine->fdt, "/chosen",
+ "linux,initrd-start", start);
+ qemu_fdt_setprop_cell(machine->fdt, "/chosen", "linux,initrd-end",
+ end);
+ }
+ } else {
+ /*
+ * If dynamic firmware is used, it doesn't know where is the next mode
+ * if kernel argument is not set.
+ */
+ kernel_entry = 0;
+ }
+
+ if (drive_get(IF_PFLASH, 0, 0)) {
+ /*
+ * Pflash was supplied, let's overwrite the address we jump to after
+ * reset to the base of the flash.
+ */
+ start_addr = virt_memmap[VIRT_FLASH].base;
+ }
+
+ /*
+ * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the device
+ * tree cannot be altered and we get FDT_ERR_NOSPACE.
+ */
+ s->fw_cfg = create_fw_cfg(machine);
+ rom_set_fw(s->fw_cfg);
+
+ /* Compute the fdt load address in dram */
+ fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
+ machine->ram_size, machine->fdt);
+ /* load the reset vector */
+ riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr,
+ virt_memmap[VIRT_MROM].base,
+ virt_memmap[VIRT_MROM].size, kernel_entry,
+ fdt_load_addr, machine->fdt);
+
+ /*
+ * Only direct boot kernel is currently supported for KVM VM,
+ * So here setup kernel start address and fdt address.
+ * TODO:Support firmware loading and integrate to TCG start
+ */
+ if (kvm_enabled()) {
+ riscv_setup_direct_kernel(kernel_entry, fdt_load_addr);
+ }
+}
+
static void virt_machine_init(MachineState *machine)
{
const MemMapEntry *memmap = virt_memmap;
@@ -1169,10 +1263,6 @@ static void virt_machine_init(MachineState *machine)
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
char *soc_name;
- target_ulong start_addr = memmap[VIRT_DRAM].base;
- target_ulong firmware_end_addr, kernel_start_addr;
- uint32_t fdt_load_addr;
- uint64_t kernel_entry;
DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip;
int i, base_hartid, hart_count;
@@ -1302,98 +1392,12 @@ static void virt_machine_init(MachineState *machine)
memory_region_add_subregion(system_memory, memmap[VIRT_DRAM].base,
machine->ram);
- /* create device tree */
- create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
- riscv_is_32bit(&s->soc[0]));
-
/* boot rom */
memory_region_init_rom(mask_rom, NULL, "riscv_virt_board.mrom",
memmap[VIRT_MROM].size, &error_fatal);
memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
mask_rom);
- /*
- * Only direct boot kernel is currently supported for KVM VM,
- * so the "-bios" parameter is not supported when KVM is enabled.
- */
- if (kvm_enabled()) {
- if (machine->firmware) {
- if (strcmp(machine->firmware, "none")) {
- error_report("Machine mode firmware is not supported in "
- "combination with KVM.");
- exit(1);
- }
- } else {
- machine->firmware = g_strdup("none");
- }
- }
-
- if (riscv_is_32bit(&s->soc[0])) {
- firmware_end_addr = riscv_find_and_load_firmware(machine,
- RISCV32_BIOS_BIN, start_addr, NULL);
- } else {
- firmware_end_addr = riscv_find_and_load_firmware(machine,
- RISCV64_BIOS_BIN, start_addr, NULL);
- }
-
- if (machine->kernel_filename) {
- kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc[0],
- firmware_end_addr);
-
- kernel_entry = riscv_load_kernel(machine->kernel_filename,
- kernel_start_addr, NULL);
-
- if (machine->initrd_filename) {
- hwaddr start;
- hwaddr end = riscv_load_initrd(machine->initrd_filename,
- machine->ram_size, kernel_entry,
- &start);
- qemu_fdt_setprop_cell(machine->fdt, "/chosen",
- "linux,initrd-start", start);
- qemu_fdt_setprop_cell(machine->fdt, "/chosen", "linux,initrd-end",
- end);
- }
- } else {
- /*
- * If dynamic firmware is used, it doesn't know where is the next mode
- * if kernel argument is not set.
- */
- kernel_entry = 0;
- }
-
- if (drive_get(IF_PFLASH, 0, 0)) {
- /*
- * Pflash was supplied, let's overwrite the address we jump to after
- * reset to the base of the flash.
- */
- start_addr = virt_memmap[VIRT_FLASH].base;
- }
-
- /*
- * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the device
- * tree cannot be altered and we get FDT_ERR_NOSPACE.
- */
- s->fw_cfg = create_fw_cfg(machine);
- rom_set_fw(s->fw_cfg);
-
- /* Compute the fdt load address in dram */
- fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
- machine->ram_size, machine->fdt);
- /* load the reset vector */
- riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr,
- virt_memmap[VIRT_MROM].base,
- virt_memmap[VIRT_MROM].size, kernel_entry,
- fdt_load_addr, machine->fdt);
-
- /*
- * Only direct boot kernel is currently supported for KVM VM,
- * So here setup kernel start address and fdt address.
- * TODO:Support firmware loading and integrate to TCG start
- */
- if (kvm_enabled()) {
- riscv_setup_direct_kernel(kernel_entry, fdt_load_addr);
- }
-
/* SiFive Test MMIO device */
sifive_test_create(memmap[VIRT_TEST].base);
@@ -1429,6 +1433,13 @@ static void virt_machine_init(MachineState *machine)
drive_get(IF_PFLASH, 0, i));
}
virt_flash_map(s, system_memory);
+
+ /* create device tree */
+ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
+ riscv_is_32bit(&s->soc[0]));
+
+ s->machine_done.notify = virt_machine_done;
+ qemu_add_machine_init_done_notifier(&s->machine_done);
}
static void virt_machine_instance_init(Object *obj)