diff options
-rw-r--r-- | disas/riscv.c | 42 | ||||
-rw-r--r-- | hw/riscv/riscv_hart.c | 6 | ||||
-rw-r--r-- | hw/riscv/sifive_clint.c | 9 | ||||
-rw-r--r-- | hw/riscv/sifive_e.c | 54 | ||||
-rw-r--r-- | hw/riscv/sifive_u.c | 91 | ||||
-rw-r--r-- | hw/riscv/spike.c | 104 | ||||
-rw-r--r-- | hw/riscv/virt.c | 85 | ||||
-rw-r--r-- | include/hw/riscv/sifive_clint.h | 4 | ||||
-rw-r--r-- | include/hw/riscv/sifive_e.h | 5 | ||||
-rw-r--r-- | include/hw/riscv/sifive_u.h | 9 | ||||
-rw-r--r-- | include/hw/riscv/spike.h | 15 | ||||
-rw-r--r-- | include/hw/riscv/virt.h | 17 | ||||
-rw-r--r-- | target/riscv/cpu.c | 2 | ||||
-rw-r--r-- | target/riscv/cpu.h | 8 | ||||
-rw-r--r-- | target/riscv/helper.c | 8 | ||||
-rw-r--r-- | target/riscv/op_helper.c | 143 | ||||
-rw-r--r-- | target/riscv/translate.c | 3 |
17 files changed, 287 insertions, 318 deletions
diff --git a/disas/riscv.c b/disas/riscv.c index 74ad16eacd..7fd1019623 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -1470,8 +1470,9 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) if (isa == rv128) { op = rv_op_c_sqsp; } else { - op = rv_op_c_fsdsp; break; + op = rv_op_c_fsdsp; } + break; case 6: op = rv_op_c_swsp; break; case 7: if (isa == rv32) { @@ -2769,25 +2770,6 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec) char tmp[64]; const char *fmt; - if (dec->op == rv_op_illegal) { - size_t len = inst_length(dec->inst); - switch (len) { - case 2: - snprintf(buf, buflen, "(0x%04" PRIx64 ")", dec->inst); - break; - case 4: - snprintf(buf, buflen, "(0x%08" PRIx64 ")", dec->inst); - break; - case 6: - snprintf(buf, buflen, "(0x%012" PRIx64 ")", dec->inst); - break; - default: - snprintf(buf, buflen, "(0x%016" PRIx64 ")", dec->inst); - break; - } - return; - } - fmt = opcode_data[dec->op].format; while (*fmt) { switch (*fmt) { @@ -3004,6 +2986,11 @@ disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst) format_inst(buf, buflen, 16, &dec); } +#define INST_FMT_2 "%04" PRIx64 " " +#define INST_FMT_4 "%08" PRIx64 " " +#define INST_FMT_6 "%012" PRIx64 " " +#define INST_FMT_8 "%016" PRIx64 " " + static int print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa) { @@ -3031,6 +3018,21 @@ print_insn_riscv(bfd_vma memaddr, struct disassemble_info *info, rv_isa isa) } } + switch (len) { + case 2: + (*info->fprintf_func)(info->stream, INST_FMT_2, inst); + break; + case 4: + (*info->fprintf_func)(info->stream, INST_FMT_4, inst); + break; + case 6: + (*info->fprintf_func)(info->stream, INST_FMT_6, inst); + break; + default: + (*info->fprintf_func)(info->stream, INST_FMT_8, inst); + break; + } + disasm_inst(buf, sizeof(buf), isa, memaddr, inst); (*info->fprintf_func)(info->stream, "%s", buf); diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c index 14e3c186fe..75ba7ed579 100644 --- a/hw/riscv/riscv_hart.c +++ b/hw/riscv/riscv_hart.c @@ -68,16 +68,10 @@ static void riscv_harts_class_init(ObjectClass *klass, void *data) dc->realize = riscv_harts_realize; } -static void riscv_harts_init(Object *obj) -{ - /* RISCVHartArrayState *s = SIFIVE_COREPLEX(obj); */ -} - static const TypeInfo riscv_harts_info = { .name = TYPE_RISCV_HART_ARRAY, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(RISCVHartArrayState), - .instance_init = riscv_harts_init, .class_init = riscv_harts_class_init, }; diff --git a/hw/riscv/sifive_clint.c b/hw/riscv/sifive_clint.c index 4893453b70..7cc606e065 100644 --- a/hw/riscv/sifive_clint.c +++ b/hw/riscv/sifive_clint.c @@ -26,13 +26,10 @@ #include "hw/riscv/sifive_clint.h" #include "qemu/timer.h" -/* See: riscv-pk/machine/sbi_entry.S and arch/riscv/kernel/time.c */ -#define TIMER_FREQ (10 * 1000 * 1000) - static uint64_t cpu_riscv_read_rtc(void) { - return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), TIMER_FREQ, - NANOSECONDS_PER_SECOND); + return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + SIFIVE_CLINT_TIMEBASE_FREQ, NANOSECONDS_PER_SECOND); } /* @@ -59,7 +56,7 @@ static void sifive_clint_write_timecmp(RISCVCPU *cpu, uint64_t value) diff = cpu->env.timecmp - rtc_r; /* back to ns (note args switched in muldiv64) */ next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - muldiv64(diff, NANOSECONDS_PER_SECOND, TIMER_FREQ); + muldiv64(diff, NANOSECONDS_PER_SECOND, SIFIVE_CLINT_TIMEBASE_FREQ); timer_mod(cpu->env.timer, next); } diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 487244890e..e4ecb7aa4b 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -74,26 +74,13 @@ static const struct MemmapEntry { [SIFIVE_E_DTIM] = { 0x80000000, 0x4000 } }; -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len) -{ - int i; - for (i = 0; i < (len >> 2); i++) { - stl_phys(&address_space_memory, pa + (i << 2), rom[i]); - } -} - -static uint64_t identity_translate(void *opaque, uint64_t addr) -{ - return addr; -} - static uint64_t load_kernel(const char *kernel_filename) { uint64_t kernel_entry, kernel_high; - if (load_elf(kernel_filename, identity_translate, NULL, + if (load_elf(kernel_filename, NULL, NULL, &kernel_entry, NULL, &kernel_high, - 0, ELF_MACHINE, 1, 0) < 0) { + 0, EM_RISCV, 1, 0) < 0) { error_report("qemu: could not load kernel '%s'", kernel_filename); exit(1); } @@ -117,6 +104,7 @@ static void riscv_sifive_e_init(MachineState *machine) MemoryRegion *main_mem = g_new(MemoryRegion, 1); MemoryRegion *mask_rom = g_new(MemoryRegion, 1); MemoryRegion *xip_mem = g_new(MemoryRegion, 1); + int i; /* Initialize SOC */ object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY); @@ -136,7 +124,7 @@ static void riscv_sifive_e_init(MachineState *machine) memmap[SIFIVE_E_DTIM].base, main_mem); /* Mask ROM */ - memory_region_init_ram(mask_rom, NULL, "riscv.sifive.e.mrom", + memory_region_init_rom(mask_rom, NULL, "riscv.sifive.e.mrom", memmap[SIFIVE_E_MROM].size, &error_fatal); memory_region_add_subregion(sys_mem, memmap[SIFIVE_E_MROM].base, mask_rom); @@ -190,33 +178,18 @@ static void riscv_sifive_e_init(MachineState *machine) 0x00028067, /* 0x1004: jr t0 */ }; - /* copy in the reset vector */ - copy_le32_to_phys(memmap[SIFIVE_E_MROM].base, reset_vec, sizeof(reset_vec)); - memory_region_set_readonly(mask_rom, true); + /* 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[SIFIVE_E_MROM].base, &address_space_memory); if (machine->kernel_filename) { load_kernel(machine->kernel_filename); } } -static int riscv_sifive_e_sysbus_device_init(SysBusDevice *sysbusdev) -{ - return 0; -} - -static void riscv_sifive_e_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = riscv_sifive_e_sysbus_device_init; -} - -static const TypeInfo riscv_sifive_e_device = { - .name = TYPE_SIFIVE_E, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SiFiveEState), - .class_init = riscv_sifive_e_class_init, -}; - static void riscv_sifive_e_machine_init(MachineClass *mc) { mc->desc = "RISC-V Board compatible with SiFive E SDK"; @@ -225,10 +198,3 @@ static void riscv_sifive_e_machine_init(MachineClass *mc) } DEFINE_MACHINE("sifive_e", riscv_sifive_e_machine_init) - -static void riscv_sifive_e_register_types(void) -{ - type_register_static(&riscv_sifive_e_device); -} - -type_init(riscv_sifive_e_register_types); diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index 66616bacd7..c05dcbba95 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -47,12 +47,14 @@ #include "exec/address-spaces.h" #include "elf.h" +#include <libfdt.h> + static const struct MemmapEntry { hwaddr base; hwaddr size; } sifive_u_memmap[] = { [SIFIVE_U_DEBUG] = { 0x0, 0x100 }, - [SIFIVE_U_MROM] = { 0x1000, 0x2000 }, + [SIFIVE_U_MROM] = { 0x1000, 0x11000 }, [SIFIVE_U_CLINT] = { 0x2000000, 0x10000 }, [SIFIVE_U_PLIC] = { 0xc000000, 0x4000000 }, [SIFIVE_U_UART0] = { 0x10013000, 0x1000 }, @@ -60,26 +62,13 @@ static const struct MemmapEntry { [SIFIVE_U_DRAM] = { 0x80000000, 0x0 }, }; -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len) -{ - int i; - for (i = 0; i < (len >> 2); i++) { - stl_phys(&address_space_memory, pa + (i << 2), rom[i]); - } -} - -static uint64_t identity_translate(void *opaque, uint64_t addr) -{ - return addr; -} - static uint64_t load_kernel(const char *kernel_filename) { uint64_t kernel_entry, kernel_high; - if (load_elf(kernel_filename, identity_translate, NULL, + if (load_elf(kernel_filename, NULL, NULL, &kernel_entry, NULL, &kernel_high, - 0, ELF_MACHINE, 1, 0) < 0) { + 0, EM_RISCV, 1, 0) < 0) { error_report("qemu: could not load kernel '%s'", kernel_filename); exit(1); } @@ -122,7 +111,8 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, g_free(nodename); qemu_fdt_add_subnode(fdt, "/cpus"); - qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 10000000); + qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", + SIFIVE_CLINT_TIMEBASE_FREQ); qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); @@ -131,7 +121,8 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap, 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", 1000000000); + qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", + SIFIVE_U_CLOCK_FREQ); qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa); qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv"); @@ -224,9 +215,10 @@ static void riscv_sifive_u_init(MachineState *machine) const struct MemmapEntry *memmap = sifive_u_memmap; SiFiveUState *s = g_new0(SiFiveUState, 1); - MemoryRegion *sys_memory = get_system_memory(); + MemoryRegion *system_memory = get_system_memory(); MemoryRegion *main_mem = g_new(MemoryRegion, 1); - MemoryRegion *boot_rom = g_new(MemoryRegion, 1); + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); + int i; /* Initialize SOC */ object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY); @@ -242,17 +234,17 @@ static void riscv_sifive_u_init(MachineState *machine) /* register RAM */ memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram", machine->ram_size, &error_fatal); - memory_region_add_subregion(sys_memory, memmap[SIFIVE_U_DRAM].base, + memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DRAM].base, main_mem); /* create device tree */ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); /* boot rom */ - memory_region_init_ram(boot_rom, NULL, "riscv.sifive.u.mrom", - memmap[SIFIVE_U_MROM].base, &error_fatal); - memory_region_set_readonly(boot_rom, true); - memory_region_add_subregion(sys_memory, 0x0, boot_rom); + memory_region_init_rom(mask_rom, NULL, "riscv.sifive.u.mrom", + memmap[SIFIVE_U_MROM].size, &error_fatal); + memory_region_add_subregion(system_memory, memmap[SIFIVE_U_MROM].base, + mask_rom); if (machine->kernel_filename) { load_kernel(machine->kernel_filename); @@ -275,13 +267,23 @@ static void riscv_sifive_u_init(MachineState *machine) /* dtb: */ }; - /* copy in the reset vector */ - copy_le32_to_phys(memmap[SIFIVE_U_MROM].base, reset_vec, sizeof(reset_vec)); + /* 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[SIFIVE_U_MROM].base, &address_space_memory); /* copy in the device tree */ - qemu_fdt_dumpdtb(s->fdt, s->fdt_size); - cpu_physical_memory_write(memmap[SIFIVE_U_MROM].base + - sizeof(reset_vec), s->fdt, s->fdt_size); + if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) > + memmap[SIFIVE_U_MROM].size - sizeof(reset_vec)) { + error_report("not enough space to store device-tree"); + exit(1); + } + qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt)); + rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), + memmap[SIFIVE_U_MROM].base + sizeof(reset_vec), + &address_space_memory); /* MMIO */ s->plic = sifive_plic_create(memmap[SIFIVE_U_PLIC].base, @@ -295,40 +297,15 @@ static void riscv_sifive_u_init(MachineState *machine) SIFIVE_U_PLIC_CONTEXT_BASE, SIFIVE_U_PLIC_CONTEXT_STRIDE, memmap[SIFIVE_U_PLIC].size); - sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART0].base, + sifive_uart_create(system_memory, memmap[SIFIVE_U_UART0].base, serial_hd(0), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART0_IRQ]); - /* sifive_uart_create(sys_memory, memmap[SIFIVE_U_UART1].base, + /* sifive_uart_create(system_memory, memmap[SIFIVE_U_UART1].base, serial_hd(1), SIFIVE_PLIC(s->plic)->irqs[SIFIVE_U_UART1_IRQ]); */ sifive_clint_create(memmap[SIFIVE_U_CLINT].base, memmap[SIFIVE_U_CLINT].size, smp_cpus, SIFIVE_SIP_BASE, SIFIVE_TIMECMP_BASE, SIFIVE_TIME_BASE); } -static int riscv_sifive_u_sysbus_device_init(SysBusDevice *sysbusdev) -{ - return 0; -} - -static void riscv_sifive_u_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = riscv_sifive_u_sysbus_device_init; -} - -static const TypeInfo riscv_sifive_u_device = { - .name = TYPE_SIFIVE_U, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SiFiveUState), - .class_init = riscv_sifive_u_class_init, -}; - -static void riscv_sifive_u_register_types(void) -{ - type_register_static(&riscv_sifive_u_device); -} - -type_init(riscv_sifive_u_register_types); - static void riscv_sifive_u_machine_init(MachineClass *mc) { mc->desc = "RISC-V Board compatible with SiFive U SDK"; diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 62857e4fa0..f94e2b6707 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -42,34 +42,23 @@ #include "exec/address-spaces.h" #include "elf.h" +#include <libfdt.h> + static const struct MemmapEntry { hwaddr base; hwaddr size; } spike_memmap[] = { - [SPIKE_MROM] = { 0x1000, 0x2000 }, + [SPIKE_MROM] = { 0x1000, 0x11000 }, [SPIKE_CLINT] = { 0x2000000, 0x10000 }, [SPIKE_DRAM] = { 0x80000000, 0x0 }, }; -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len) -{ - int i; - for (i = 0; i < (len >> 2); i++) { - stl_phys(&address_space_memory, pa + (i << 2), rom[i]); - } -} - -static uint64_t identity_translate(void *opaque, uint64_t addr) -{ - return addr; -} - static uint64_t load_kernel(const char *kernel_filename) { uint64_t kernel_entry, kernel_high; - if (load_elf_ram_sym(kernel_filename, identity_translate, NULL, - &kernel_entry, NULL, &kernel_high, 0, ELF_MACHINE, 1, 0, + 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("qemu: could not load kernel '%s'", kernel_filename); exit(1); @@ -115,7 +104,8 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap, g_free(nodename); qemu_fdt_add_subnode(fdt, "/cpus"); - qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 10000000); + qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", + SIFIVE_CLINT_TIMEBASE_FREQ); qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); @@ -124,7 +114,8 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap, 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", 1000000000); + qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", + SPIKE_CLOCK_FREQ); qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa); qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv"); @@ -176,7 +167,8 @@ static void spike_v1_10_0_board_init(MachineState *machine) SpikeState *s = g_new0(SpikeState, 1); MemoryRegion *system_memory = get_system_memory(); MemoryRegion *main_mem = g_new(MemoryRegion, 1); - MemoryRegion *boot_rom = g_new(MemoryRegion, 1); + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); + int i; /* Initialize SOC */ object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY); @@ -199,9 +191,10 @@ static void spike_v1_10_0_board_init(MachineState *machine) create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); /* boot rom */ - memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom", - s->fdt_size + 0x2000, &error_fatal); - memory_region_add_subregion(system_memory, 0x0, 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); @@ -224,16 +217,26 @@ static void spike_v1_10_0_board_init(MachineState *machine) /* dtb: */ }; - /* copy in the reset vector */ - copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec, sizeof(reset_vec)); + /* 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 device tree */ - qemu_fdt_dumpdtb(s->fdt, s->fdt_size); - cpu_physical_memory_write(memmap[SPIKE_MROM].base + sizeof(reset_vec), - s->fdt, s->fdt_size); + if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) > + memmap[SPIKE_MROM].size - sizeof(reset_vec)) { + error_report("not enough space to store device-tree"); + exit(1); + } + qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt)); + rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), + memmap[SPIKE_MROM].base + sizeof(reset_vec), + &address_space_memory); /* initialize HTIF using symbols found in load_kernel */ - htif_mm_init(system_memory, boot_rom, &s->soc.harts[0].env, serial_hd(0)); + 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, @@ -247,7 +250,8 @@ static void spike_v1_09_1_board_init(MachineState *machine) SpikeState *s = g_new0(SpikeState, 1); MemoryRegion *system_memory = get_system_memory(); MemoryRegion *main_mem = g_new(MemoryRegion, 1); - MemoryRegion *boot_rom = g_new(MemoryRegion, 1); + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); + int i; /* Initialize SOC */ object_initialize(&s->soc, sizeof(s->soc), TYPE_RISCV_HART_ARRAY); @@ -267,9 +271,10 @@ static void spike_v1_09_1_board_init(MachineState *machine) main_mem); /* boot rom */ - memory_region_init_ram(boot_rom, NULL, "riscv.spike.bootrom", - 0x40000, &error_fatal); - memory_region_add_subregion(system_memory, 0x0, 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); @@ -322,33 +327,26 @@ static void spike_v1_09_1_board_init(MachineState *machine) g_free(isa); size_t config_string_len = strlen(config_string); - /* copy in the reset vector */ - copy_le32_to_phys(memmap[SPIKE_MROM].base, reset_vec, sizeof(reset_vec)); + /* 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 */ - cpu_physical_memory_write(memmap[SPIKE_MROM].base + sizeof(reset_vec), - config_string, config_string_len); + 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, boot_rom, &s->soc.harts[0].env, serial_hd(0)); + 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 const TypeInfo spike_v_1_09_1_device = { - .name = TYPE_RISCV_SPIKE_V1_09_1_BOARD, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SpikeState), -}; - -static const TypeInfo spike_v_1_10_0_device = { - .name = TYPE_RISCV_SPIKE_V1_10_0_BOARD, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(SpikeState), -}; - static void spike_v1_09_1_machine_init(MachineClass *mc) { mc->desc = "RISC-V Spike Board (Privileged ISA v1.9.1)"; @@ -366,11 +364,3 @@ static void spike_v1_10_0_machine_init(MachineClass *mc) DEFINE_MACHINE("spike_v1.9.1", spike_v1_09_1_machine_init) DEFINE_MACHINE("spike_v1.10", spike_v1_10_0_machine_init) - -static void riscv_spike_board_register_types(void) -{ - type_register_static(&spike_v_1_09_1_device); - type_register_static(&spike_v_1_10_0_device); -} - -type_init(riscv_spike_board_register_types); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 4f69eb2cff..ad03113e0f 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -40,13 +40,15 @@ #include "exec/address-spaces.h" #include "elf.h" +#include <libfdt.h> + static const struct MemmapEntry { hwaddr base; hwaddr size; } virt_memmap[] = { [VIRT_DEBUG] = { 0x0, 0x100 }, - [VIRT_MROM] = { 0x1000, 0x2000 }, - [VIRT_TEST] = { 0x4000, 0x1000 }, + [VIRT_MROM] = { 0x1000, 0x11000 }, + [VIRT_TEST] = { 0x100000, 0x1000 }, [VIRT_CLINT] = { 0x2000000, 0x10000 }, [VIRT_PLIC] = { 0xc000000, 0x4000000 }, [VIRT_UART0] = { 0x10000000, 0x100 }, @@ -54,26 +56,13 @@ static const struct MemmapEntry { [VIRT_DRAM] = { 0x80000000, 0x0 }, }; -static void copy_le32_to_phys(hwaddr pa, uint32_t *rom, size_t len) -{ - int i; - for (i = 0; i < (len >> 2); i++) { - stl_phys(&address_space_memory, pa + (i << 2), rom[i]); - } -} - -static uint64_t identity_translate(void *opaque, uint64_t addr) -{ - return addr; -} - static uint64_t load_kernel(const char *kernel_filename) { uint64_t kernel_entry, kernel_high; - if (load_elf(kernel_filename, identity_translate, NULL, + if (load_elf(kernel_filename, NULL, NULL, &kernel_entry, NULL, &kernel_high, - 0, ELF_MACHINE, 1, 0) < 0) { + 0, EM_RISCV, 1, 0) < 0) { error_report("qemu: could not load kernel '%s'", kernel_filename); exit(1); } @@ -145,7 +134,8 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, g_free(nodename); qemu_fdt_add_subnode(fdt, "/cpus"); - qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", 10000000); + qemu_fdt_setprop_cell(fdt, "/cpus", "timebase-frequency", + SIFIVE_CLINT_TIMEBASE_FREQ); qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); @@ -155,7 +145,8 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap, 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", 1000000000); + qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", + VIRT_CLOCK_FREQ); qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa); qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv"); @@ -275,7 +266,7 @@ static void riscv_virt_board_init(MachineState *machine) RISCVVirtState *s = g_new0(RISCVVirtState, 1); MemoryRegion *system_memory = get_system_memory(); MemoryRegion *main_mem = g_new(MemoryRegion, 1); - MemoryRegion *boot_rom = g_new(MemoryRegion, 1); + MemoryRegion *mask_rom = g_new(MemoryRegion, 1); char *plic_hart_config; size_t plic_hart_config_len; int i; @@ -302,9 +293,10 @@ static void riscv_virt_board_init(MachineState *machine) fdt = create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline); /* boot rom */ - memory_region_init_ram(boot_rom, NULL, "riscv_virt_board.bootrom", - s->fdt_size + 0x2000, &error_fatal); - memory_region_add_subregion(system_memory, 0x0, 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); if (machine->kernel_filename) { uint64_t kernel_entry = load_kernel(machine->kernel_filename); @@ -338,13 +330,23 @@ static void riscv_virt_board_init(MachineState *machine) /* dtb: */ }; - /* copy in the reset vector */ - copy_le32_to_phys(ROM_BASE, reset_vec, sizeof(reset_vec)); + /* 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[VIRT_MROM].base, &address_space_memory); /* copy in the device tree */ - qemu_fdt_dumpdtb(s->fdt, s->fdt_size); - cpu_physical_memory_write(ROM_BASE + sizeof(reset_vec), - s->fdt, s->fdt_size); + if (fdt_pack(s->fdt) || fdt_totalsize(s->fdt) > + memmap[VIRT_MROM].size - sizeof(reset_vec)) { + error_report("not enough space to store device-tree"); + exit(1); + } + qemu_fdt_dumpdtb(s->fdt, fdt_totalsize(s->fdt)); + rom_add_blob_fixed_as("mrom.fdt", s->fdt, fdt_totalsize(s->fdt), + memmap[VIRT_MROM].base + sizeof(reset_vec), + &address_space_memory); /* create PLIC hart topology configuration string */ plic_hart_config_len = (strlen(VIRT_PLIC_HART_CONFIG) + 1) * smp_cpus; @@ -385,36 +387,11 @@ static void riscv_virt_board_init(MachineState *machine) serial_hd(0), DEVICE_LITTLE_ENDIAN); } -static int riscv_virt_board_sysbus_device_init(SysBusDevice *sysbusdev) -{ - return 0; -} - -static void riscv_virt_board_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = riscv_virt_board_sysbus_device_init; -} - -static const TypeInfo riscv_virt_board_device = { - .name = TYPE_RISCV_VIRT_BOARD, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(RISCVVirtState), - .class_init = riscv_virt_board_class_init, -}; - static void riscv_virt_board_machine_init(MachineClass *mc) { - mc->desc = "RISC-V VirtIO Board (Privileged spec v1.10)"; + mc->desc = "RISC-V VirtIO Board (Privileged ISA v1.10)"; mc->init = riscv_virt_board_init; mc->max_cpus = 8; /* hardcoded limit in BBL */ } DEFINE_MACHINE("virt", riscv_virt_board_machine_init) - -static void riscv_virt_board_register_types(void) -{ - type_register_static(&riscv_virt_board_device); -} - -type_init(riscv_virt_board_register_types); diff --git a/include/hw/riscv/sifive_clint.h b/include/hw/riscv/sifive_clint.h index aaa2a58c6e..e2865be1d1 100644 --- a/include/hw/riscv/sifive_clint.h +++ b/include/hw/riscv/sifive_clint.h @@ -47,4 +47,8 @@ enum { SIFIVE_TIME_BASE = 0xBFF8 }; +enum { + SIFIVE_CLINT_TIMEBASE_FREQ = 10000000 +}; + #endif diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h index 0aebc576c1..12ad6d2ebb 100644 --- a/include/hw/riscv/sifive_e.h +++ b/include/hw/riscv/sifive_e.h @@ -19,11 +19,6 @@ #ifndef HW_SIFIVE_E_H #define HW_SIFIVE_E_H -#define TYPE_SIFIVE_E "riscv.sifive_e" - -#define SIFIVE_E(obj) \ - OBJECT_CHECK(SiFiveEState, (obj), TYPE_SIFIVE_E) - typedef struct SiFiveEState { /*< private >*/ SysBusDevice parent_obj; diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h index 662e8a1c1a..94a390566e 100644 --- a/include/hw/riscv/sifive_u.h +++ b/include/hw/riscv/sifive_u.h @@ -19,11 +19,6 @@ #ifndef HW_SIFIVE_U_H #define HW_SIFIVE_U_H -#define TYPE_SIFIVE_U "riscv.sifive_u" - -#define SIFIVE_U(obj) \ - OBJECT_CHECK(SiFiveUState, (obj), TYPE_SIFIVE_U) - typedef struct SiFiveUState { /*< private >*/ SysBusDevice parent_obj; @@ -50,6 +45,10 @@ enum { SIFIVE_U_UART1_IRQ = 4 }; +enum { + SIFIVE_U_CLOCK_FREQ = 1000000000 +}; + #define SIFIVE_U_PLIC_HART_CONFIG "MS" #define SIFIVE_U_PLIC_NUM_SOURCES 127 #define SIFIVE_U_PLIC_NUM_PRIORITIES 7 diff --git a/include/hw/riscv/spike.h b/include/hw/riscv/spike.h index cb55a14d30..641b70da67 100644 --- a/include/hw/riscv/spike.h +++ b/include/hw/riscv/spike.h @@ -16,14 +16,8 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef HW_SPIKE_H -#define HW_SPIKE_H - -#define TYPE_RISCV_SPIKE_V1_09_1_BOARD "riscv.spike_v1_9_1" -#define TYPE_RISCV_SPIKE_V1_10_0_BOARD "riscv.spike_v1_10" - -#define SPIKE(obj) \ - OBJECT_CHECK(SpikeState, (obj), TYPE_RISCV_SPIKE_BOARD) +#ifndef HW_RISCV_SPIKE_H +#define HW_RISCV_SPIKE_H typedef struct { /*< private >*/ @@ -35,13 +29,16 @@ typedef struct { int fdt_size; } SpikeState; - enum { SPIKE_MROM, SPIKE_CLINT, SPIKE_DRAM }; +enum { + SPIKE_CLOCK_FREQ = 1000000000 +}; + #if defined(TARGET_RISCV32) #define SPIKE_V1_09_1_CPU TYPE_RISCV_CPU_RV32GCSU_V1_09_1 #define SPIKE_V1_10_0_CPU TYPE_RISCV_CPU_RV32GCSU_V1_10_0 diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index 7525647e63..91163d6cbf 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -1,5 +1,5 @@ /* - * SiFive VirtIO Board + * QEMU RISC-V VirtIO machine interface * * Copyright (c) 2017 SiFive, Inc. * @@ -16,14 +16,8 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef HW_VIRT_H -#define HW_VIRT_H - -#define TYPE_RISCV_VIRT_BOARD "riscv.virt" -#define VIRT(obj) \ - OBJECT_CHECK(RISCVVirtState, (obj), TYPE_RISCV_VIRT_BOARD) - -enum { ROM_BASE = 0x1000 }; +#ifndef HW_RISCV_VIRT_H +#define HW_RISCV_VIRT_H typedef struct { /*< private >*/ @@ -47,7 +41,6 @@ enum { VIRT_DRAM }; - enum { UART0_IRQ = 10, VIRTIO_IRQ = 1, /* 1 to 8 */ @@ -55,6 +48,10 @@ enum { VIRTIO_NDEV = 10 }; +enum { + VIRT_CLOCK_FREQ = 1000000000 +}; + #define VIRT_PLIC_HART_CONFIG "MS" #define VIRT_PLIC_NUM_SOURCES 127 #define VIRT_PLIC_NUM_PRIORITIES 7 diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 5a527fbba0..4e5a56d4e3 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -26,7 +26,7 @@ /* RISC-V CPU definitions */ -static const char riscv_exts[26] = "IMAFDQECLBJTPVNSUHKORWXYZG"; +static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG"; const char * const riscv_int_regnames[] = { "zero", "ra ", "sp ", "gp ", "tp ", "t0 ", "t1 ", "t2 ", diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 41e06ac0f9..34abc383e3 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -34,7 +34,6 @@ #define TCG_GUEST_DEFAULT_MO 0 -#define ELF_MACHINE EM_RISCV #define CPUArchState struct CPURISCVState #include "qemu-common.h" @@ -72,6 +71,7 @@ #define RV(x) ((target_ulong)1 << (x - 'A')) #define RVI RV('I') +#define RVE RV('E') /* E and I are mutually exclusive */ #define RVM RV('M') #define RVA RV('A') #define RVF RV('F') @@ -151,10 +151,8 @@ struct CPURISCVState { target_ulong mcause; target_ulong mtval; /* since: priv-1.10.0 */ - uint32_t mucounteren; - uint32_t mscounteren; - target_ulong scounteren; /* since: priv-1.10.0 */ - target_ulong mcounteren; /* since: priv-1.10.0 */ + target_ulong scounteren; + target_ulong mcounteren; target_ulong sscratch; target_ulong mscratch; diff --git a/target/riscv/helper.c b/target/riscv/helper.c index 02cbcea2b7..95889f23b9 100644 --- a/target/riscv/helper.c +++ b/target/riscv/helper.c @@ -466,6 +466,10 @@ void riscv_cpu_do_interrupt(CPUState *cs) ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr); } env->sbadaddr = env->badaddr; + } else { + /* otherwise we must clear sbadaddr/stval + * todo: support populating stval on illegal instructions */ + env->sbadaddr = 0; } target_ulong s = env->mstatus; @@ -487,6 +491,10 @@ void riscv_cpu_do_interrupt(CPUState *cs) ": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr); } env->mbadaddr = env->badaddr; + } else { + /* otherwise we must clear mbadaddr/mtval + * todo: support populating mtval on illegal instructions */ + env->mbadaddr = 0; } target_ulong s = env->mstatus; diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 7c6068bac9..3abf52453c 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -213,28 +213,41 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, break; } case CSR_MINSTRET: - qemu_log_mask(LOG_UNIMP, "CSR_MINSTRET: write not implemented"); - goto do_illegal; + /* minstret is WARL so unsupported writes are ignored */ + break; case CSR_MCYCLE: - qemu_log_mask(LOG_UNIMP, "CSR_MCYCLE: write not implemented"); - goto do_illegal; + /* mcycle is WARL so unsupported writes are ignored */ + break; +#if defined(TARGET_RISCV32) case CSR_MINSTRETH: - qemu_log_mask(LOG_UNIMP, "CSR_MINSTRETH: write not implemented"); - goto do_illegal; + /* minstreth is WARL so unsupported writes are ignored */ + break; case CSR_MCYCLEH: - qemu_log_mask(LOG_UNIMP, "CSR_MCYCLEH: write not implemented"); - goto do_illegal; - case CSR_MUCOUNTEREN: - env->mucounteren = val_to_write; + /* mcycleh is WARL so unsupported writes are ignored */ break; +#endif + case CSR_MUCOUNTEREN: + if (env->priv_ver <= PRIV_VERSION_1_09_1) { + env->scounteren = val_to_write; + break; + } else { + goto do_illegal; + } case CSR_MSCOUNTEREN: - env->mscounteren = val_to_write; - break; + if (env->priv_ver <= PRIV_VERSION_1_09_1) { + env->mcounteren = val_to_write; + break; + } else { + goto do_illegal; + } case CSR_SSTATUS: { target_ulong ms = env->mstatus; target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS - | SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD; + | SSTATUS_SUM | SSTATUS_SD; + if (env->priv_ver >= PRIV_VERSION_1_10_0) { + mask |= SSTATUS_MXR; + } ms = (ms & ~mask) | (val_to_write & mask); csr_write_helper(env, ms, CSR_MSTATUS); break; @@ -255,7 +268,7 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, } case CSR_SATP: /* CSR_SPTBR */ { if (!riscv_feature(env, RISCV_FEATURE_MMU)) { - goto do_illegal; + break; } if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val_to_write ^ env->sptbr)) { @@ -276,15 +289,20 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, env->sepc = val_to_write; break; case CSR_STVEC: - if (val_to_write & 1) { + /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */ + if ((val_to_write & 3) == 0) { + env->stvec = val_to_write >> 2 << 2; + } else { qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not supported"); - goto do_illegal; } - env->stvec = val_to_write >> 2 << 2; break; case CSR_SCOUNTEREN: - env->scounteren = val_to_write; - break; + if (env->priv_ver >= PRIV_VERSION_1_10_0) { + env->scounteren = val_to_write; + break; + } else { + goto do_illegal; + } case CSR_SSCRATCH: env->sscratch = val_to_write; break; @@ -298,15 +316,20 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, env->mepc = val_to_write; break; case CSR_MTVEC: - if (val_to_write & 1) { + /* bits [1:0] indicate mode; 0 = direct, 1 = vectored, 2 >= reserved */ + if ((val_to_write & 3) == 0) { + env->mtvec = val_to_write >> 2 << 2; + } else { qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not supported"); - goto do_illegal; } - env->mtvec = val_to_write >> 2 << 2; break; case CSR_MCOUNTEREN: - env->mcounteren = val_to_write; - break; + if (env->priv_ver >= PRIV_VERSION_1_10_0) { + env->mcounteren = val_to_write; + break; + } else { + goto do_illegal; + } case CSR_MSCRATCH: env->mscratch = val_to_write; break; @@ -316,10 +339,9 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, case CSR_MBADADDR: env->mbadaddr = val_to_write; break; - case CSR_MISA: { - qemu_log_mask(LOG_UNIMP, "CSR_MISA: misa writes not supported"); - goto do_illegal; - } + case CSR_MISA: + /* misa is WARL so unsupported writes are ignored */ + break; case CSR_PMPCFG0: case CSR_PMPCFG1: case CSR_PMPCFG2: @@ -344,6 +366,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, case CSR_PMPADDR15: pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val_to_write); break; +#endif +#if !defined(CONFIG_USER_ONLY) do_illegal: #endif default: @@ -359,8 +383,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno) { #ifndef CONFIG_USER_ONLY - target_ulong ctr_en = env->priv == PRV_U ? env->mucounteren : - env->priv == PRV_S ? env->mscounteren : -1U; + target_ulong ctr_en = env->priv == PRV_U ? env->scounteren : + env->priv == PRV_S ? env->mcounteren : -1U; #else target_ulong ctr_en = -1; #endif @@ -413,35 +437,67 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno) case CSR_INSTRET: case CSR_CYCLE: if (ctr_ok) { +#if !defined(CONFIG_USER_ONLY) + if (use_icount) { + return cpu_get_icount(); + } else { + return cpu_get_host_ticks(); + } +#else return cpu_get_host_ticks(); +#endif } break; #if defined(TARGET_RISCV32) case CSR_INSTRETH: case CSR_CYCLEH: if (ctr_ok) { +#if !defined(CONFIG_USER_ONLY) + if (use_icount) { + return cpu_get_icount() >> 32; + } else { + return cpu_get_host_ticks() >> 32; + } +#else return cpu_get_host_ticks() >> 32; +#endif } break; #endif #ifndef CONFIG_USER_ONLY case CSR_MINSTRET: case CSR_MCYCLE: - return cpu_get_host_ticks(); + if (use_icount) { + return cpu_get_icount(); + } else { + return cpu_get_host_ticks(); + } case CSR_MINSTRETH: case CSR_MCYCLEH: #if defined(TARGET_RISCV32) - return cpu_get_host_ticks() >> 32; + if (use_icount) { + return cpu_get_icount() >> 32; + } else { + return cpu_get_host_ticks() >> 32; + } #endif break; case CSR_MUCOUNTEREN: - return env->mucounteren; + if (env->priv_ver <= PRIV_VERSION_1_09_1) { + return env->scounteren; + } else { + break; /* illegal instruction */ + } case CSR_MSCOUNTEREN: - return env->mscounteren; + if (env->priv_ver <= PRIV_VERSION_1_09_1) { + return env->mcounteren; + } else { + break; /* illegal instruction */ + } case CSR_SSTATUS: { target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS - | SSTATUS_SUM | SSTATUS_SD; + | SSTATUS_SUM | SSTATUS_SD; if (env->priv_ver >= PRIV_VERSION_1_10_0) { mask |= SSTATUS_MXR; } @@ -462,10 +518,17 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno) case CSR_STVEC: return env->stvec; case CSR_SCOUNTEREN: - return env->scounteren; + if (env->priv_ver >= PRIV_VERSION_1_10_0) { + return env->scounteren; + } else { + break; /* illegal instruction */ + } case CSR_SCAUSE: return env->scause; - case CSR_SPTBR: + case CSR_SATP: /* CSR_SPTBR */ + if (!riscv_feature(env, RISCV_FEATURE_MMU)) { + return 0; + } if (env->priv_ver >= PRIV_VERSION_1_10_0) { return env->satp; } else { @@ -504,7 +567,11 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno) case CSR_MTVEC: return env->mtvec; case CSR_MCOUNTEREN: - return env->mcounteren; + if (env->priv_ver >= PRIV_VERSION_1_10_0) { + return env->mcounteren; + } else { + break; /* illegal instruction */ + } case CSR_MEDELEG: return env->medeleg; case CSR_MIDELEG: diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 808eab7f50..c0e6a044d3 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -280,7 +280,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1, tcg_gen_andi_tl(source2, source2, 0x1F); tcg_gen_sar_tl(source1, source1, source2); break; - /* fall through to SRA */ #endif case OPC_RISC_SRA: tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1); @@ -1391,6 +1390,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc, break; default: tcg_gen_movi_tl(imm_rs1, rs1); + gen_io_start(); switch (opc) { case OPC_RISC_CSRRW: gen_helper_csrrw(dest, cpu_env, source1, csr_store); @@ -1414,6 +1414,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc, gen_exception_illegal(ctx); return; } + gen_io_end(); gen_set_gpr(rd, dest); /* end tb since we may be changing priv modes, to get mmu_index right */ tcg_gen_movi_tl(cpu_pc, ctx->next_pc); |