#include "qemu/log.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
-#include "hw/hw.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "hw/sysbus.h"
#include "hw/riscv/riscv_hart.h"
#include "hw/riscv/sifive_clint.h"
#include "hw/riscv/spike.h"
+#include "hw/riscv/boot.h"
#include "chardev/char.h"
#include "sysemu/arch_init.h"
#include "sysemu/device_tree.h"
+#include "sysemu/qtest.h"
+#include "sysemu/sysemu.h"
#include "exec/address-spaces.h"
-#include "elf.h"
#include <libfdt.h>
+#if defined(TARGET_RISCV32)
+# define BIOS_FILENAME "opensbi-riscv32-spike-fw_jump.elf"
+#else
+# define BIOS_FILENAME "opensbi-riscv64-spike-fw_jump.elf"
+#endif
+
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
[SPIKE_DRAM] = { 0x80000000, 0x0 },
};
-static uint64_t load_kernel(const char *kernel_filename)
-{
- uint64_t kernel_entry, kernel_high;
-
- if (load_elf_ram_sym(kernel_filename, NULL, NULL,
- &kernel_entry, NULL, &kernel_high, 0, EM_RISCV, 1, 0,
- NULL, true, htif_symbol_callback) < 0) {
- error_report("could not load kernel '%s'", kernel_filename);
- exit(1);
- }
- return kernel_entry;
-}
-
static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap,
uint64_t mem_size, const char *cmdline)
{
char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
char *isa = riscv_isa_string(&s->soc.harts[cpu]);
qemu_fdt_add_subnode(fdt, nodename);
- qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency",
- SPIKE_CLOCK_FREQ);
+#if defined(TARGET_RISCV32)
+ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32");
+#else
qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
+#endif
qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa);
qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv");
qemu_fdt_setprop_string(fdt, nodename, "status", "okay");
qemu_fdt_setprop_string(fdt, nodename, "device_type", "cpu");
qemu_fdt_add_subnode(fdt, intc);
qemu_fdt_setprop_cell(fdt, intc, "phandle", 1);
- qemu_fdt_setprop_cell(fdt, intc, "linux,phandle", 1);
qemu_fdt_setprop_string(fdt, intc, "compatible", "riscv,cpu-intc");
qemu_fdt_setprop(fdt, intc, "interrupt-controller", NULL, 0);
qemu_fdt_setprop_cell(fdt, intc, "#interrupt-cells", 1);
qemu_fdt_add_subnode(fdt, "/chosen");
qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline);
}
- }
+}
-static void spike_v1_10_0_board_init(MachineState *machine)
+static void spike_board_init(MachineState *machine)
{
const struct MemmapEntry *memmap = spike_memmap;
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
int i;
+ unsigned int smp_cpus = machine->smp.cpus;
/* Initialize SOC */
- object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
- TYPE_RISCV_HART_ARRAY, &error_abort, NULL);
- object_property_set_str(OBJECT(&s->soc), SPIKE_V1_10_0_CPU, "cpu-type",
+ object_initialize_child(OBJECT(machine), "soc", &s->soc,
+ TYPE_RISCV_HART_ARRAY);
+ object_property_set_str(OBJECT(&s->soc), machine->cpu_type, "cpu-type",
&error_abort);
object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts",
&error_abort);
- object_property_set_bool(OBJECT(&s->soc), true, "realized",
- &error_abort);
+ sysbus_realize(SYS_BUS_DEVICE(&s->soc), &error_abort);
/* register system main memory (actual RAM) */
memory_region_init_ram(main_mem, NULL, "riscv.spike.ram",
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
mask_rom);
+ riscv_find_and_load_firmware(machine, BIOS_FILENAME,
+ memmap[SPIKE_DRAM].base,
+ htif_symbol_callback);
+
if (machine->kernel_filename) {
- load_kernel(machine->kernel_filename);
+ uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename,
+ htif_symbol_callback);
+
+ if (machine->initrd_filename) {
+ hwaddr start;
+ hwaddr end = riscv_load_initrd(machine->initrd_filename,
+ machine->ram_size, kernel_entry,
+ &start);
+ qemu_fdt_setprop_cell(s->fdt, "/chosen",
+ "linux,initrd-start", start);
+ qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end",
+ end);
+ }
}
/* reset vector */
/* Core Local Interruptor (timer and IPI) */
sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size,
- smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
-}
-
-static void spike_v1_09_1_board_init(MachineState *machine)
-{
- const struct MemmapEntry *memmap = spike_memmap;
-
- SpikeState *s = g_new0(SpikeState, 1);
- MemoryRegion *system_memory = get_system_memory();
- MemoryRegion *main_mem = g_new(MemoryRegion, 1);
- MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
- int i;
-
- /* Initialize SOC */
- object_initialize_child(OBJECT(machine), "soc", &s->soc, sizeof(s->soc),
- TYPE_RISCV_HART_ARRAY, &error_abort, NULL);
- object_property_set_str(OBJECT(&s->soc), SPIKE_V1_09_1_CPU, "cpu-type",
- &error_abort);
- object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts",
- &error_abort);
- object_property_set_bool(OBJECT(&s->soc), true, "realized",
- &error_abort);
-
- /* register system main memory (actual RAM) */
- memory_region_init_ram(main_mem, NULL, "riscv.spike.ram",
- machine->ram_size, &error_fatal);
- memory_region_add_subregion(system_memory, memmap[SPIKE_DRAM].base,
- main_mem);
-
- /* boot rom */
- memory_region_init_rom(mask_rom, NULL, "riscv.spike.mrom",
- memmap[SPIKE_MROM].size, &error_fatal);
- memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
- mask_rom);
-
- if (machine->kernel_filename) {
- load_kernel(machine->kernel_filename);
- }
-
- /* reset vector */
- uint32_t reset_vec[8] = {
- 0x297 + memmap[SPIKE_DRAM].base - memmap[SPIKE_MROM].base, /* lui */
- 0x00028067, /* jump to DRAM_BASE */
- 0x00000000, /* reserved */
- memmap[SPIKE_MROM].base + sizeof(reset_vec), /* config string pointer */
- 0, 0, 0, 0 /* trap vector */
- };
-
- /* part one of config string - before memory size specified */
- const char *config_string_tmpl =
- "platform {\n"
- " vendor ucb;\n"
- " arch spike;\n"
- "};\n"
- "rtc {\n"
- " addr 0x%" PRIx64 "x;\n"
- "};\n"
- "ram {\n"
- " 0 {\n"
- " addr 0x%" PRIx64 "x;\n"
- " size 0x%" PRIx64 "x;\n"
- " };\n"
- "};\n"
- "core {\n"
- " 0" " {\n"
- " " "0 {\n"
- " isa %s;\n"
- " timecmp 0x%" PRIx64 "x;\n"
- " ipi 0x%" PRIx64 "x;\n"
- " };\n"
- " };\n"
- "};\n";
-
- /* build config string with supplied memory size */
- char *isa = riscv_isa_string(&s->soc.harts[0]);
- size_t config_string_size = strlen(config_string_tmpl) + 48;
- char *config_string = malloc(config_string_size);
- snprintf(config_string, config_string_size, config_string_tmpl,
- (uint64_t)memmap[SPIKE_CLINT].base + SIFIVE_TIME_BASE,
- (uint64_t)memmap[SPIKE_DRAM].base,
- (uint64_t)ram_size, isa,
- (uint64_t)memmap[SPIKE_CLINT].base + SIFIVE_TIMECMP_BASE,
- (uint64_t)memmap[SPIKE_CLINT].base + SIFIVE_SIP_BASE);
- g_free(isa);
- size_t config_string_len = strlen(config_string);
-
- /* copy in the reset vector in little_endian byte order */
- for (i = 0; i < sizeof(reset_vec) >> 2; i++) {
- reset_vec[i] = cpu_to_le32(reset_vec[i]);
- }
- rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
- memmap[SPIKE_MROM].base, &address_space_memory);
-
- /* copy in the config string */
- rom_add_blob_fixed_as("mrom.reset", config_string, config_string_len,
- memmap[SPIKE_MROM].base + sizeof(reset_vec),
- &address_space_memory);
-
- /* initialize HTIF using symbols found in load_kernel */
- htif_mm_init(system_memory, mask_rom, &s->soc.harts[0].env, serial_hd(0));
-
- /* Core Local Interruptor (timer and IPI) */
- sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size,
- smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE);
-}
-
-static void spike_v1_09_1_machine_init(MachineClass *mc)
-{
- mc->desc = "RISC-V Spike Board (Privileged ISA v1.9.1)";
- mc->init = spike_v1_09_1_board_init;
- mc->max_cpus = 1;
+ smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE,
+ false);
}
-static void spike_v1_10_0_machine_init(MachineClass *mc)
+static void spike_machine_init(MachineClass *mc)
{
- mc->desc = "RISC-V Spike Board (Privileged ISA v1.10)";
- mc->init = spike_v1_10_0_board_init;
- mc->max_cpus = 1;
- mc->is_default = 1;
+ mc->desc = "RISC-V Spike Board";
+ mc->init = spike_board_init;
+ mc->max_cpus = 8;
+ mc->is_default = true;
+ mc->default_cpu_type = SPIKE_V1_10_0_CPU;
}
-DEFINE_MACHINE("spike_v1.9.1", spike_v1_09_1_machine_init)
-DEFINE_MACHINE("spike_v1.10", spike_v1_10_0_machine_init)
+DEFINE_MACHINE("spike", spike_machine_init)