1*5b4beba1SMichael Clark /* 2*5b4beba1SMichael Clark * QEMU RISC-V Spike Board 3*5b4beba1SMichael Clark * 4*5b4beba1SMichael Clark * Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu 5*5b4beba1SMichael Clark * Copyright (c) 2017-2018 SiFive, Inc. 6*5b4beba1SMichael Clark * 7*5b4beba1SMichael Clark * This provides a RISC-V Board with the following devices: 8*5b4beba1SMichael Clark * 9*5b4beba1SMichael Clark * 0) HTIF Console and Poweroff 10*5b4beba1SMichael Clark * 1) CLINT (Timer and IPI) 11*5b4beba1SMichael Clark * 2) PLIC (Platform Level Interrupt Controller) 12*5b4beba1SMichael Clark * 13*5b4beba1SMichael Clark * This program is free software; you can redistribute it and/or modify it 14*5b4beba1SMichael Clark * under the terms and conditions of the GNU General Public License, 15*5b4beba1SMichael Clark * version 2 or later, as published by the Free Software Foundation. 16*5b4beba1SMichael Clark * 17*5b4beba1SMichael Clark * This program is distributed in the hope it will be useful, but WITHOUT 18*5b4beba1SMichael Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19*5b4beba1SMichael Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 20*5b4beba1SMichael Clark * more details. 21*5b4beba1SMichael Clark * 22*5b4beba1SMichael Clark * You should have received a copy of the GNU General Public License along with 23*5b4beba1SMichael Clark * this program. If not, see <http://www.gnu.org/licenses/>. 24*5b4beba1SMichael Clark */ 25*5b4beba1SMichael Clark 26*5b4beba1SMichael Clark #include "qemu/osdep.h" 27*5b4beba1SMichael Clark #include "qemu/log.h" 28*5b4beba1SMichael Clark #include "qemu/error-report.h" 29*5b4beba1SMichael Clark #include "qapi/error.h" 30*5b4beba1SMichael Clark #include "hw/hw.h" 31*5b4beba1SMichael Clark #include "hw/boards.h" 32*5b4beba1SMichael Clark #include "hw/loader.h" 33*5b4beba1SMichael Clark #include "hw/sysbus.h" 34*5b4beba1SMichael Clark #include "target/riscv/cpu.h" 35*5b4beba1SMichael Clark #include "hw/riscv/riscv_htif.h" 36*5b4beba1SMichael Clark #include "hw/riscv/riscv_hart.h" 37*5b4beba1SMichael Clark #include "hw/riscv/sifive_clint.h" 38*5b4beba1SMichael Clark #include "hw/riscv/spike.h" 39*5b4beba1SMichael Clark #include "chardev/char.h" 40*5b4beba1SMichael Clark #include "sysemu/arch_init.h" 41*5b4beba1SMichael Clark #include "sysemu/device_tree.h" 42*5b4beba1SMichael Clark #include "exec/address-spaces.h" 43*5b4beba1SMichael Clark #include "elf.h" 44*5b4beba1SMichael Clark 45*5b4beba1SMichael Clark static const struct MemmapEntry { 46*5b4beba1SMichael Clark hwaddr base; 47*5b4beba1SMichael Clark hwaddr size; 48*5b4beba1SMichael Clark } spike_memmap[] = { 49*5b4beba1SMichael Clark [SPIKE_MROM] = { 0x1000, 0x2000 }, 50*5b4beba1SMichael Clark [SPIKE_CLINT] = { 0x2000000, 0x10000 }, 51*5b4beba1SMichael Clark [SPIKE_DRAM] = { 0x80000000, 0x0 }, 52*5b4beba1SMichael Clark }; 53*5b4beba1SMichael Clark 54*5b4beba1SMichael Clark static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len) 55*5b4beba1SMichael Clark { 56*5b4beba1SMichael Clark int i; 57*5b4beba1SMichael Clark for (i = 0; i < (len >> 2); i++) { 58*5b4beba1SMichael Clark stl_phys(&address_space_memory, pa + (i << 2), rom[i]); 59*5b4beba1SMichael Clark } 60*5b4beba1SMichael Clark } 61*5b4beba1SMichael Clark 62*5b4beba1SMichael Clark static uint64_t identity_translate(void *opaque, uint64_t addr) 63*5b4beba1SMichael Clark { 64*5b4beba1SMichael Clark return addr; 65*5b4beba1SMichael Clark } 66*5b4beba1SMichael Clark 67*5b4beba1SMichael Clark static uint64_t load_kernel(const char *kernel_filename) 68*5b4beba1SMichael Clark { 69*5b4beba1SMichael Clark uint64_t kernel_entry, kernel_high; 70*5b4beba1SMichael Clark 71*5b4beba1SMichael Clark if (load_elf_ram_sym(kernel_filename, identity_translate, NULL, 72*5b4beba1SMichael Clark &kernel_entry, NULL, &kernel_high, 0, ELF_MACHINE, 1, 0, 73*5b4beba1SMichael Clark NULL, true, htif_symbol_callback) < 0) { 74*5b4beba1SMichael Clark error_report("qemu: could not load kernel '%s'", kernel_filename); 75*5b4beba1SMichael Clark exit(1); 76*5b4beba1SMichael Clark } 77*5b4beba1SMichael Clark return kernel_entry; 78*5b4beba1SMichael Clark } 79*5b4beba1SMichael Clark 80*5b4beba1SMichael Clark static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap, 81*5b4beba1SMichael Clark uint64_t mem_size, const char *cmdline) 82*5b4beba1SMichael Clark { 83*5b4beba1SMichael Clark void *fdt; 84*5b4beba1SMichael Clark int cpu; 85*5b4beba1SMichael Clark uint32_t *cells; 86*5b4beba1SMichael Clark char *nodename; 87*5b4beba1SMichael Clark 88*5b4beba1SMichael Clark fdt = s->fdt = create_device_tree(&s->fdt_size); 89*5b4beba1SMichael Clark if (!fdt) { 90*5b4beba1SMichael Clark error_report("create_device_tree() failed"); 91*5b4beba1SMichael Clark exit(1); 92*5b4beba1SMichael Clark } 93*5b4beba1SMichael Clark 94*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, "/", "model", "ucbbar,spike-bare,qemu"); 95*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, "/", "compatible", "ucbbar,spike-bare-dev"); 96*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2); 97*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2); 98*5b4beba1SMichael Clark 99*5b4beba1SMichael Clark qemu_fdt_add_subnode(fdt, "/htif"); 100*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, "/htif", "compatible", "ucb,htif0"); 101*5b4beba1SMichael Clark 102*5b4beba1SMichael Clark qemu_fdt_add_subnode(fdt, "/soc"); 103*5b4beba1SMichael Clark qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0); 104*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, "/soc", "compatible", "ucbbar,spike-bare-soc"); 105*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x2); 106*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x2); 107*5b4beba1SMichael Clark 108*5b4beba1SMichael Clark nodename = g_strdup_printf("/memory@%lx", 109*5b4beba1SMichael Clark (long)memmap[SPIKE_DRAM].base); 110*5b4beba1SMichael Clark qemu_fdt_add_subnode(fdt, nodename); 111*5b4beba1SMichael Clark qemu_fdt_setprop_cells(fdt, nodename, "reg", 112*5b4beba1SMichael Clark memmap[SPIKE_DRAM].base >> 32, memmap[SPIKE_DRAM].base, 113*5b4beba1SMichael Clark mem_size >> 32, mem_size); 114*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory"); 115*5b4beba1SMichael Clark g_free(nodename); 116*5b4beba1SMichael Clark 117*5b4beba1SMichael Clark qemu_fdt_add_subnode(fdt, "/cpus"); 118*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 10000000); 119*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); 120*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); 121*5b4beba1SMichael Clark 122*5b4beba1SMichael Clark for (cpu = s->soc.num_harts - 1; cpu >= 0; cpu--) { 123*5b4beba1SMichael Clark nodename = g_strdup_printf("/cpus/cpu@%d", cpu); 124*5b4beba1SMichael Clark char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); 125*5b4beba1SMichael Clark char *isa = riscv_isa_string(&s->soc.harts[cpu]); 126*5b4beba1SMichael Clark qemu_fdt_add_subnode(fdt, nodename); 127*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", 1000000000); 128*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); 129*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa); 130*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv"); 131*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, nodename, "status", "okay"); 132*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, nodename, "reg", cpu); 133*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, nodename, "device_type", "cpu"); 134*5b4beba1SMichael Clark qemu_fdt_add_subnode(fdt, intc); 135*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, intc, "phandle", 1); 136*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, intc, "linux,phandle", 1); 137*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, intc, "compatible", "riscv,cpu-intc"); 138*5b4beba1SMichael Clark qemu_fdt_setprop(fdt, intc, "interrupt-controller", NULL, 0); 139*5b4beba1SMichael Clark qemu_fdt_setprop_cell(fdt, intc, "#interrupt-cells", 1); 140*5b4beba1SMichael Clark g_free(isa); 141*5b4beba1SMichael Clark g_free(intc); 142*5b4beba1SMichael Clark g_free(nodename); 143*5b4beba1SMichael Clark } 144*5b4beba1SMichael Clark 145*5b4beba1SMichael Clark cells = g_new0(uint32_t, s->soc.num_harts * 4); 146*5b4beba1SMichael Clark for (cpu = 0; cpu < s->soc.num_harts; cpu++) { 147*5b4beba1SMichael Clark nodename = 148*5b4beba1SMichael Clark g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu); 149*5b4beba1SMichael Clark uint32_t intc_phandle = qemu_fdt_get_phandle(fdt, nodename); 150*5b4beba1SMichael Clark cells[cpu * 4 + 0] = cpu_to_be32(intc_phandle); 151*5b4beba1SMichael Clark cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_SOFT); 152*5b4beba1SMichael Clark cells[cpu * 4 + 2] = cpu_to_be32(intc_phandle); 153*5b4beba1SMichael Clark cells[cpu * 4 + 3] = cpu_to_be32(IRQ_M_TIMER); 154*5b4beba1SMichael Clark g_free(nodename); 155*5b4beba1SMichael Clark } 156*5b4beba1SMichael Clark nodename = g_strdup_printf("/soc/clint@%lx", 157*5b4beba1SMichael Clark (long)memmap[SPIKE_CLINT].base); 158*5b4beba1SMichael Clark qemu_fdt_add_subnode(fdt, nodename); 159*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv,clint0"); 160*5b4beba1SMichael Clark qemu_fdt_setprop_cells(fdt, nodename, "reg", 161*5b4beba1SMichael Clark 0x0, memmap[SPIKE_CLINT].base, 162*5b4beba1SMichael Clark 0x0, memmap[SPIKE_CLINT].size); 163*5b4beba1SMichael Clark qemu_fdt_setprop(fdt, nodename, "interrupts-extended", 164*5b4beba1SMichael Clark cells, s->soc.num_harts * sizeof(uint32_t) * 4); 165*5b4beba1SMichael Clark g_free(cells); 166*5b4beba1SMichael Clark g_free(nodename); 167*5b4beba1SMichael Clark 168*5b4beba1SMichael Clark qemu_fdt_add_subnode(fdt, "/chosen"); 169*5b4beba1SMichael Clark qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); 170*5b4beba1SMichael Clark } 171*5b4beba1SMichael Clark 172*5b4beba1SMichael Clark static void spike_v1_10_0_board_init(MachineState *machine) 173*5b4beba1SMichael Clark { 174*5b4beba1SMichael Clark const struct MemmapEntry *memmap = spike_memmap; 175*5b4beba1SMichael Clark 176*5b4beba1SMichael Clark SpikeState *s = g_new0(SpikeState, 1); 177*5b4beba1SMichael Clark MemoryRegion *system_memory = get_system_memory(); 178*5b4beba1SMichael Clark MemoryRegion *main_mem = g_new(MemoryRegion, 1); 179*5b4beba1SMichael Clark MemoryRegion *boot_rom = g_new(MemoryRegion, 1); 180*5b4beba1SMichael Clark 181*5b4beba1SMichael Clark /* Initialize SOC */ 182*5b4beba1SMichael Clark object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY); 183*5b4beba1SMichael Clark object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), 184*5b4beba1SMichael Clark &error_abort); 185*5b4beba1SMichael Clark object_property_set_str(OBJECT(&s->soc), SPIKE_V1_10_0_CPU, "cpu-type", 186*5b4beba1SMichael Clark &error_abort); 187*5b4beba1SMichael Clark object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", 188*5b4beba1SMichael Clark &error_abort); 189*5b4beba1SMichael Clark object_property_set_bool(OBJECT(&s->soc), true, "realized", 190*5b4beba1SMichael Clark &error_abort); 191*5b4beba1SMichael Clark 192*5b4beba1SMichael Clark /* register system main memory (actual RAM) */ 193*5b4beba1SMichael Clark memory_region_init_ram(main_mem, NULL, "riscv.spike.ram", 194*5b4beba1SMichael Clark machine->ram_size, &error_fatal); 195*5b4beba1SMichael Clark memory_region_add_subregion(system_memory, memmap[SPIKE_DRAM].base, 196*5b4beba1SMichael Clark main_mem); 197*5b4beba1SMichael Clark 198*5b4beba1SMichael Clark /* create device tree */ 199*5b4beba1SMichael Clark create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); 200*5b4beba1SMichael Clark 201*5b4beba1SMichael Clark /* boot rom */ 202*5b4beba1SMichael Clark memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom", 203*5b4beba1SMichael Clark s->fdt_size + 0x2000, &error_fatal); 204*5b4beba1SMichael Clark memory_region_add_subregion(system_memory, 0x0, boot_rom); 205*5b4beba1SMichael Clark 206*5b4beba1SMichael Clark if (machine->kernel_filename) { 207*5b4beba1SMichael Clark load_kernel(machine->kernel_filename); 208*5b4beba1SMichael Clark } 209*5b4beba1SMichael Clark 210*5b4beba1SMichael Clark /* reset vector */ 211*5b4beba1SMichael Clark uint32_t reset_vec[8] = { 212*5b4beba1SMichael Clark 0x00000297, /* 1: auipc t0, %pcrel_hi(dtb) */ 213*5b4beba1SMichael Clark 0x02028593, /* addi a1, t0, %pcrel_lo(1b) */ 214*5b4beba1SMichael Clark 0xf1402573, /* csrr a0, mhartid */ 215*5b4beba1SMichael Clark #if defined(TARGET_RISCV32) 216*5b4beba1SMichael Clark 0x0182a283, /* lw t0, 24(t0) */ 217*5b4beba1SMichael Clark #elif defined(TARGET_RISCV64) 218*5b4beba1SMichael Clark 0x0182b283, /* ld t0, 24(t0) */ 219*5b4beba1SMichael Clark #endif 220*5b4beba1SMichael Clark 0x00028067, /* jr t0 */ 221*5b4beba1SMichael Clark 0x00000000, 222*5b4beba1SMichael Clark memmap[SPIKE_DRAM].base, /* start: .dword DRAM_BASE */ 223*5b4beba1SMichael Clark 0x00000000, 224*5b4beba1SMichael Clark /* dtb: */ 225*5b4beba1SMichael Clark }; 226*5b4beba1SMichael Clark 227*5b4beba1SMichael Clark /* copy in the reset vector */ 228*5b4beba1SMichael Clark copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec, sizeof(reset_vec)); 229*5b4beba1SMichael Clark 230*5b4beba1SMichael Clark /* copy in the device tree */ 231*5b4beba1SMichael Clark qemu_fdt_dumpdtb(s->fdt, s->fdt_size); 232*5b4beba1SMichael Clark cpu_physical_memory_write(memmap[SPIKE_MROM].base + sizeof(reset_vec), 233*5b4beba1SMichael Clark s->fdt, s->fdt_size); 234*5b4beba1SMichael Clark 235*5b4beba1SMichael Clark /* initialize HTIF using symbols found in load_kernel */ 236*5b4beba1SMichael Clark htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env, serial_hds[0]); 237*5b4beba1SMichael Clark 238*5b4beba1SMichael Clark /* Core Local Interruptor (timer and IPI) */ 239*5b4beba1SMichael Clark sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size, 240*5b4beba1SMichael Clark smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE); 241*5b4beba1SMichael Clark } 242*5b4beba1SMichael Clark 243*5b4beba1SMichael Clark static void spike_v1_09_1_board_init(MachineState *machine) 244*5b4beba1SMichael Clark { 245*5b4beba1SMichael Clark const struct MemmapEntry *memmap = spike_memmap; 246*5b4beba1SMichael Clark 247*5b4beba1SMichael Clark SpikeState *s = g_new0(SpikeState, 1); 248*5b4beba1SMichael Clark MemoryRegion *system_memory = get_system_memory(); 249*5b4beba1SMichael Clark MemoryRegion *main_mem = g_new(MemoryRegion, 1); 250*5b4beba1SMichael Clark MemoryRegion *boot_rom = g_new(MemoryRegion, 1); 251*5b4beba1SMichael Clark 252*5b4beba1SMichael Clark /* Initialize SOC */ 253*5b4beba1SMichael Clark object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY); 254*5b4beba1SMichael Clark object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc), 255*5b4beba1SMichael Clark &error_abort); 256*5b4beba1SMichael Clark object_property_set_str(OBJECT(&s->soc), SPIKE_V1_09_1_CPU, "cpu-type", 257*5b4beba1SMichael Clark &error_abort); 258*5b4beba1SMichael Clark object_property_set_int(OBJECT(&s->soc), smp_cpus, "num-harts", 259*5b4beba1SMichael Clark &error_abort); 260*5b4beba1SMichael Clark object_property_set_bool(OBJECT(&s->soc), true, "realized", 261*5b4beba1SMichael Clark &error_abort); 262*5b4beba1SMichael Clark 263*5b4beba1SMichael Clark /* register system main memory (actual RAM) */ 264*5b4beba1SMichael Clark memory_region_init_ram(main_mem, NULL, "riscv.spike.ram", 265*5b4beba1SMichael Clark machine->ram_size, &error_fatal); 266*5b4beba1SMichael Clark memory_region_add_subregion(system_memory, memmap[SPIKE_DRAM].base, 267*5b4beba1SMichael Clark main_mem); 268*5b4beba1SMichael Clark 269*5b4beba1SMichael Clark /* boot rom */ 270*5b4beba1SMichael Clark memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom", 271*5b4beba1SMichael Clark 0x40000, &error_fatal); 272*5b4beba1SMichael Clark memory_region_add_subregion(system_memory, 0x0, boot_rom); 273*5b4beba1SMichael Clark 274*5b4beba1SMichael Clark if (machine->kernel_filename) { 275*5b4beba1SMichael Clark load_kernel(machine->kernel_filename); 276*5b4beba1SMichael Clark } 277*5b4beba1SMichael Clark 278*5b4beba1SMichael Clark /* reset vector */ 279*5b4beba1SMichael Clark uint32_t reset_vec[8] = { 280*5b4beba1SMichael Clark 0x297 + memmap[SPIKE_DRAM].base - memmap[SPIKE_MROM].base, /* lui */ 281*5b4beba1SMichael Clark 0x00028067, /* jump to DRAM_BASE */ 282*5b4beba1SMichael Clark 0x00000000, /* reserved */ 283*5b4beba1SMichael Clark memmap[SPIKE_MROM].base + sizeof(reset_vec), /* config string pointer */ 284*5b4beba1SMichael Clark 0, 0, 0, 0 /* trap vector */ 285*5b4beba1SMichael Clark }; 286*5b4beba1SMichael Clark 287*5b4beba1SMichael Clark /* part one of config string - before memory size specified */ 288*5b4beba1SMichael Clark const char *config_string_tmpl = 289*5b4beba1SMichael Clark "platform {\n" 290*5b4beba1SMichael Clark " vendor ucb;\n" 291*5b4beba1SMichael Clark " arch spike;\n" 292*5b4beba1SMichael Clark "};\n" 293*5b4beba1SMichael Clark "rtc {\n" 294*5b4beba1SMichael Clark " addr 0x%" PRIx64 "x;\n" 295*5b4beba1SMichael Clark "};\n" 296*5b4beba1SMichael Clark "ram {\n" 297*5b4beba1SMichael Clark " 0 {\n" 298*5b4beba1SMichael Clark " addr 0x%" PRIx64 "x;\n" 299*5b4beba1SMichael Clark " size 0x%" PRIx64 "x;\n" 300*5b4beba1SMichael Clark " };\n" 301*5b4beba1SMichael Clark "};\n" 302*5b4beba1SMichael Clark "core {\n" 303*5b4beba1SMichael Clark " 0" " {\n" 304*5b4beba1SMichael Clark " " "0 {\n" 305*5b4beba1SMichael Clark " isa %s;\n" 306*5b4beba1SMichael Clark " timecmp 0x%" PRIx64 "x;\n" 307*5b4beba1SMichael Clark " ipi 0x%" PRIx64 "x;\n" 308*5b4beba1SMichael Clark " };\n" 309*5b4beba1SMichael Clark " };\n" 310*5b4beba1SMichael Clark "};\n"; 311*5b4beba1SMichael Clark 312*5b4beba1SMichael Clark /* build config string with supplied memory size */ 313*5b4beba1SMichael Clark char *isa = riscv_isa_string(&s->soc.harts[0]); 314*5b4beba1SMichael Clark size_t config_string_size = strlen(config_string_tmpl) + 48; 315*5b4beba1SMichael Clark char *config_string = malloc(config_string_size); 316*5b4beba1SMichael Clark snprintf(config_string, config_string_size, config_string_tmpl, 317*5b4beba1SMichael Clark (uint64_t)memmap[SPIKE_CLINT].base + SIFIVE_TIME_BASE, 318*5b4beba1SMichael Clark (uint64_t)memmap[SPIKE_DRAM].base, 319*5b4beba1SMichael Clark (uint64_t)ram_size, isa, 320*5b4beba1SMichael Clark (uint64_t)memmap[SPIKE_CLINT].base + SIFIVE_TIMECMP_BASE, 321*5b4beba1SMichael Clark (uint64_t)memmap[SPIKE_CLINT].base + SIFIVE_SIP_BASE); 322*5b4beba1SMichael Clark g_free(isa); 323*5b4beba1SMichael Clark size_t config_string_len = strlen(config_string); 324*5b4beba1SMichael Clark 325*5b4beba1SMichael Clark /* copy in the reset vector */ 326*5b4beba1SMichael Clark copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec, sizeof(reset_vec)); 327*5b4beba1SMichael Clark 328*5b4beba1SMichael Clark /* copy in the config string */ 329*5b4beba1SMichael Clark cpu_physical_memory_write(memmap[SPIKE_MROM].base + sizeof(reset_vec), 330*5b4beba1SMichael Clark config_string, config_string_len); 331*5b4beba1SMichael Clark 332*5b4beba1SMichael Clark /* initialize HTIF using symbols found in load_kernel */ 333*5b4beba1SMichael Clark htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env, serial_hds[0]); 334*5b4beba1SMichael Clark 335*5b4beba1SMichael Clark /* Core Local Interruptor (timer and IPI) */ 336*5b4beba1SMichael Clark sifive_clint_create(memmap[SPIKE_CLINT].base, memmap[SPIKE_CLINT].size, 337*5b4beba1SMichael Clark smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE); 338*5b4beba1SMichael Clark } 339*5b4beba1SMichael Clark 340*5b4beba1SMichael Clark static const TypeInfo spike_v_1_09_1_device = { 341*5b4beba1SMichael Clark .name = TYPE_RISCV_SPIKE_V1_09_1_BOARD, 342*5b4beba1SMichael Clark .parent = TYPE_SYS_BUS_DEVICE, 343*5b4beba1SMichael Clark .instance_size = sizeof(SpikeState), 344*5b4beba1SMichael Clark }; 345*5b4beba1SMichael Clark 346*5b4beba1SMichael Clark static const TypeInfo spike_v_1_10_0_device = { 347*5b4beba1SMichael Clark .name = TYPE_RISCV_SPIKE_V1_10_0_BOARD, 348*5b4beba1SMichael Clark .parent = TYPE_SYS_BUS_DEVICE, 349*5b4beba1SMichael Clark .instance_size = sizeof(SpikeState), 350*5b4beba1SMichael Clark }; 351*5b4beba1SMichael Clark 352*5b4beba1SMichael Clark static void spike_v1_09_1_machine_init(MachineClass *mc) 353*5b4beba1SMichael Clark { 354*5b4beba1SMichael Clark mc->desc = "RISC-V Spike Board (Privileged ISA v1.9.1)"; 355*5b4beba1SMichael Clark mc->init = spike_v1_09_1_board_init; 356*5b4beba1SMichael Clark mc->max_cpus = 1; 357*5b4beba1SMichael Clark } 358*5b4beba1SMichael Clark 359*5b4beba1SMichael Clark static void spike_v1_10_0_machine_init(MachineClass *mc) 360*5b4beba1SMichael Clark { 361*5b4beba1SMichael Clark mc->desc = "RISC-V Spike Board (Privileged ISA v1.10)"; 362*5b4beba1SMichael Clark mc->init = spike_v1_10_0_board_init; 363*5b4beba1SMichael Clark mc->max_cpus = 1; 364*5b4beba1SMichael Clark mc->is_default = 1; 365*5b4beba1SMichael Clark } 366*5b4beba1SMichael Clark 367*5b4beba1SMichael Clark DEFINE_MACHINE("spike_v1.9.1", spike_v1_09_1_machine_init) 368*5b4beba1SMichael Clark DEFINE_MACHINE("spike_v1.10", spike_v1_10_0_machine_init) 369*5b4beba1SMichael Clark 370*5b4beba1SMichael Clark static void riscv_spike_board_register_types(void) 371*5b4beba1SMichael Clark { 372*5b4beba1SMichael Clark type_register_static(&spike_v_1_09_1_device); 373*5b4beba1SMichael Clark type_register_static(&spike_v_1_10_0_device); 374*5b4beba1SMichael Clark } 375*5b4beba1SMichael Clark 376*5b4beba1SMichael Clark type_init(riscv_spike_board_register_types); 377