From c672f19f328922eff4963b0b61fbdcfa661e1c06 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Thu, 7 Oct 2021 16:17:41 +0800 Subject: [PATCH 01/33] target/riscv: Pass the same value to oprsz and maxsz for vmv.v.v oprsz and maxsz are passed with the same value in commit: eee2d61e202. However, vmv.v.v was missed in that commit and should pass the same value as well in its tcg_gen_gvec_2_ptr() call. Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Message-id: 20211007081803.1705656-1-frank.chang@sifive.com Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 081a5ca34d..45be491ed4 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -1619,7 +1619,8 @@ static bool trans_vmv_v_v(DisasContext *s, arg_vmv_v_v *a) tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs1), - cpu_env, 0, s->vlen / 8, data, fns[s->sew]); + cpu_env, s->vlen / 8, s->vlen / 8, data, + fns[s->sew]); gen_set_label(over); } return true; From e573a7f325e4d66d1005f7bb80d51ce95f307951 Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Fri, 8 Oct 2021 22:50:19 -0700 Subject: [PATCH 02/33] target/riscv: line up all of the registers in the info register dump Ensure the columns for all of the register names and values line up. No functional change, just a minor tweak to the output. Signed-off-by: Travis Geiselbrecht Reviewed-by: Alistair Francis Message-id: 20211009055019.545153-1-travisg@gmail.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 1d69d1887e..660f9ce131 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -258,7 +258,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) } if (riscv_has_ext(env, RVH)) { qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ", + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus", (target_ulong)env->vsstatus); } qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", env->mip); @@ -289,8 +289,8 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval ", env->mtval); qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval ", env->stval); if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval ", env->htval); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2 ", env->mtval2); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval ", env->htval); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2 ", env->mtval2); } qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mscratch", env->mscratch); qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sscratch", env->sscratch); @@ -298,7 +298,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) #endif for (i = 0; i < 32; i++) { - qemu_fprintf(f, " %s " TARGET_FMT_lx, + qemu_fprintf(f, " %-8s " TARGET_FMT_lx, riscv_int_regnames[i], env->gpr[i]); if ((i & 3) == 3) { qemu_fprintf(f, "\n"); @@ -306,7 +306,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) } if (flags & CPU_DUMP_FPU) { for (i = 0; i < 32; i++) { - qemu_fprintf(f, " %s %016" PRIx64, + qemu_fprintf(f, " %-8s %016" PRIx64, riscv_fpr_regnames[i], env->fpr[i]); if ((i & 3) == 3) { qemu_fprintf(f, "\n"); From 54c17609372bb119575f3bb7309ea57fc1a58d1d Mon Sep 17 00:00:00 2001 From: Philipp Tomsich Date: Wed, 13 Oct 2021 20:41:25 +0200 Subject: [PATCH 03/33] target/riscv: Fix orc.b implementation The earlier implementation fell into a corner case for bytes that were 0x01, giving a wrong result (but not affecting our application test cases for strings, as an ASCII value 0x01 is rare in those...). This changes the algorithm to: 1. Mask out the high-bit of each bytes (so that each byte is <= 127). 2. Add 127 to each byte (i.e. if the low 7 bits are not 0, this will overflow into the highest bit of each byte). 3. Bitwise-or the original value back in (to cover those cases where the source byte was exactly 128) to saturate the high-bit. 4. Shift-and-mask (implemented as a mask-and-shift) to extract the MSB of each byte into its LSB. 5. Multiply with 0xff to fan out the LSB to all bits of each byte. Fixes: d7a4fcb034 ("target/riscv: Add orc.b instruction for Zbb, removing gorc/gorci") Signed-off-by: Philipp Tomsich Reported-by: Vincent Palatin Tested-by: Vincent Palatin Reviewed-by: Richard Henderson Message-id: 20211013184125.2010897-1-philipp.tomsich@vrull.eu Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 185c3e9a60..3095624f32 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -249,13 +249,16 @@ static bool trans_rev8_64(DisasContext *ctx, arg_rev8_64 *a) static void gen_orc_b(TCGv ret, TCGv source1) { TCGv tmp = tcg_temp_new(); - TCGv ones = tcg_constant_tl(dup_const_tl(MO_8, 0x01)); + TCGv low7 = tcg_constant_tl(dup_const_tl(MO_8, 0x7f)); - /* Set lsb in each byte if the byte was zero. */ - tcg_gen_sub_tl(tmp, source1, ones); - tcg_gen_andc_tl(tmp, tmp, source1); + /* Set msb in each byte if the byte was non-zero. */ + tcg_gen_and_tl(tmp, source1, low7); + tcg_gen_add_tl(tmp, tmp, low7); + tcg_gen_or_tl(tmp, tmp, source1); + + /* Extract the msb to the lsb in each byte */ + tcg_gen_andc_tl(tmp, tmp, low7); tcg_gen_shri_tl(tmp, tmp, 7); - tcg_gen_andc_tl(tmp, ones, tmp); /* Replicate the lsb of each byte across the byte. */ tcg_gen_muli_tl(ret, tmp, 0xff); From 03fd0c5fe98f5617076527e9783d030294b64d6d Mon Sep 17 00:00:00 2001 From: Mingwang Li Date: Sat, 16 Oct 2021 11:09:08 +0800 Subject: [PATCH 04/33] hw/riscv: virt: Use machine->ram as the system memory If default main_mem is used to be registered as the system memory, other memory cannot be initialized. Therefore, the system memory should be initialized to the machine->ram, which consists of the default main_mem and other possible memory required by applications, such as shared hugepage memory in DPDK. Also, the mc->defaul_ram_id should be set to the default main_mem, such as "riscv_virt_board.ram" for the virt machine. Signed-off-by: Mingwang Li Signed-off-by: Yifei Jiang Reviewed-by: Alistair Francis Message-id: 20211016030908.40480-1-limingwang@huawei.com Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index ec0cb69b8c..b3b431c847 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -771,7 +771,6 @@ static void virt_machine_init(MachineState *machine) const MemMapEntry *memmap = virt_memmap; RISCVVirtState *s = RISCV_VIRT_MACHINE(machine); MemoryRegion *system_memory = get_system_memory(); - MemoryRegion *main_mem = g_new(MemoryRegion, 1); MemoryRegion *mask_rom = g_new(MemoryRegion, 1); char *plic_hart_config, *soc_name; target_ulong start_addr = memmap[VIRT_DRAM].base; @@ -890,10 +889,8 @@ static void virt_machine_init(MachineState *machine) } /* register system main memory (actual RAM) */ - memory_region_init_ram(main_mem, NULL, "riscv_virt_board.ram", - machine->ram_size, &error_fatal); memory_region_add_subregion(system_memory, memmap[VIRT_DRAM].base, - main_mem); + machine->ram); /* create device tree */ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline, @@ -1032,6 +1029,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props; mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id; mc->numa_mem_supported = true; + mc->default_ram_id = "riscv_virt_board.ram"; machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); From 61d56494884b0d4bbf78d0561258b3548dea3390 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Fri, 15 Oct 2021 15:45:02 +0800 Subject: [PATCH 05/33] target/riscv: fix TB_FLAGS bits overlapping bug for rvv/rvh TB_FLAGS mem_idx bits was extended from 2 bits to 3 bits in commit: c445593, but other TB_FLAGS bits for rvv and rvh were not shift as well so these bits may overlap with each other when rvv is enabled. Signed-off-by: Frank Chang Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-Id: <20211015074627.3957162-2-frank.chang@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 14 +++++++------- target/riscv/translate.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 9e55b2f5b1..ce42c83bda 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -378,7 +378,6 @@ void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env, target_ulong riscv_cpu_get_fflags(CPURISCVState *env); void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong); -#define TB_FLAGS_MMU_MASK 7 #define TB_FLAGS_PRIV_MMU_MASK 3 #define TB_FLAGS_PRIV_HYP_ACCESS_MASK (1 << 2) #define TB_FLAGS_MSTATUS_FS MSTATUS_FS @@ -387,13 +386,14 @@ typedef CPURISCVState CPUArchState; typedef RISCVCPU ArchCPU; #include "exec/cpu-all.h" -FIELD(TB_FLAGS, VL_EQ_VLMAX, 2, 1) -FIELD(TB_FLAGS, LMUL, 3, 2) -FIELD(TB_FLAGS, SEW, 5, 3) -FIELD(TB_FLAGS, VILL, 8, 1) +FIELD(TB_FLAGS, MEM_IDX, 0, 3) +FIELD(TB_FLAGS, VL_EQ_VLMAX, 3, 1) +FIELD(TB_FLAGS, LMUL, 4, 2) +FIELD(TB_FLAGS, SEW, 6, 3) +FIELD(TB_FLAGS, VILL, 9, 1) /* Is a Hypervisor instruction load/store allowed? */ -FIELD(TB_FLAGS, HLSX, 9, 1) -FIELD(TB_FLAGS, MSTATUS_HS_FS, 10, 2) +FIELD(TB_FLAGS, HLSX, 10, 1) +FIELD(TB_FLAGS, MSTATUS_HS_FS, 11, 2) bool riscv_cpu_is_32bit(CPURISCVState *env); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 6d7fbca1fa..62214e97fa 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -501,7 +501,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) uint32_t tb_flags = ctx->base.tb->flags; ctx->pc_succ_insn = ctx->base.pc_first; - ctx->mem_idx = tb_flags & TB_FLAGS_MMU_MASK; + ctx->mem_idx = FIELD_EX32(tb_flags, TB_FLAGS, MEM_IDX); ctx->mstatus_fs = tb_flags & TB_FLAGS_MSTATUS_FS; ctx->priv_ver = env->priv_ver; #if !defined(CONFIG_USER_ONLY) From 31dbcff713aa297033a008b5188fbb37abf85f36 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 18 Oct 2021 14:32:00 +1000 Subject: [PATCH 06/33] target/riscv: Remove some unused macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 1a9540d1f1a ("target/riscv: Drop support for ISA spec version 1.09.1") these definitions are unused, remove them. Signed-off-by: Alistair Francis Reviewed-by: Frank Chang Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Bin Meng Message-id: f4d8a7a035f39c0a35d44c1e371c5c99cc2fa15a.1634531504.git.alistair.francis@wdc.com --- target/riscv/cpu_bits.h | 8 -------- 1 file changed, 8 deletions(-) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 999187a9ee..3aa2512d13 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -427,14 +427,6 @@ #define SATP64_ASID 0x0FFFF00000000000ULL #define SATP64_PPN 0x00000FFFFFFFFFFFULL -/* VM modes (mstatus.vm) privileged ISA 1.9.1 */ -#define VM_1_09_MBARE 0 -#define VM_1_09_MBB 1 -#define VM_1_09_MBBID 2 -#define VM_1_09_SV32 8 -#define VM_1_09_SV39 9 -#define VM_1_09_SV48 10 - /* VM modes (satp.mode) privileged ISA 1.10 */ #define VM_1_10_MBARE 0 #define VM_1_10_SV32 1 From 9d3d60b704f48217cf9b38b883cc15c40f76f286 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 18 Oct 2021 14:32:15 +1000 Subject: [PATCH 07/33] target/riscv: Organise the CPU properties Organise the CPU properties so that standard extensions come first then followed by experimental extensions. Signed-off-by: Alistair Francis Reviewed-by: Frank Chang Reviewed-by: Bin Meng Message-id: b6598570f60c5ee7f402be56d837bb44b289cc4d.1634531504.git.alistair.francis@wdc.com --- target/riscv/cpu.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 660f9ce131..11bb59ac6d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -581,6 +581,7 @@ static void riscv_cpu_init(Object *obj) } static Property riscv_cpu_properties[] = { + /* Defaults for standard extensions */ DEFINE_PROP_BOOL("i", RISCVCPU, cfg.ext_i, true), DEFINE_PROP_BOOL("e", RISCVCPU, cfg.ext_e, false), DEFINE_PROP_BOOL("g", RISCVCPU, cfg.ext_g, true), @@ -591,22 +592,24 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("c", RISCVCPU, cfg.ext_c, true), DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true), DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true), - /* This is experimental so mark with 'x-' */ + DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true), + DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), + DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), + DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), + DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), + + DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), + + /* These are experimental so mark with 'x-' */ DEFINE_PROP_BOOL("x-zba", RISCVCPU, cfg.ext_zba, false), DEFINE_PROP_BOOL("x-zbb", RISCVCPU, cfg.ext_zbb, false), DEFINE_PROP_BOOL("x-zbc", RISCVCPU, cfg.ext_zbc, false), DEFINE_PROP_BOOL("x-zbs", RISCVCPU, cfg.ext_zbs, false), DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false), DEFINE_PROP_BOOL("x-v", RISCVCPU, cfg.ext_v, false), - DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true), - DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), - DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), - DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec), DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128), DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), - DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), - DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), /* ePMP 0.9.3 */ DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false), From 53677acf25afa8e529d7f81a6ae9a03d15c72713 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:16:55 -0700 Subject: [PATCH 08/33] target/riscv: Move cpu_get_tb_cpu_state out of line Move the function to cpu_helper.c, as it is large and growing. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-2-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 47 ++------------------------------------- target/riscv/cpu_helper.c | 46 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index ce42c83bda..f543364d51 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -413,51 +413,8 @@ static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, target_ulong vtype) return cpu->cfg.vlen >> (sew + 3 - lmul); } -static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, - target_ulong *cs_base, uint32_t *pflags) -{ - uint32_t flags = 0; - - *pc = env->pc; - *cs_base = 0; - - if (riscv_has_ext(env, RVV)) { - uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype); - bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl); - flags = FIELD_DP32(flags, TB_FLAGS, VILL, - FIELD_EX64(env->vtype, VTYPE, VILL)); - flags = FIELD_DP32(flags, TB_FLAGS, SEW, - FIELD_EX64(env->vtype, VTYPE, VSEW)); - flags = FIELD_DP32(flags, TB_FLAGS, LMUL, - FIELD_EX64(env->vtype, VTYPE, VLMUL)); - flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax); - } else { - flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1); - } - -#ifdef CONFIG_USER_ONLY - flags |= TB_FLAGS_MSTATUS_FS; -#else - flags |= cpu_mmu_index(env, 0); - if (riscv_cpu_fp_enabled(env)) { - flags |= env->mstatus & MSTATUS_FS; - } - - if (riscv_has_ext(env, RVH)) { - if (env->priv == PRV_M || - (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || - (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && - get_field(env->hstatus, HSTATUS_HU))) { - flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1); - } - - flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS, - get_field(env->mstatus_hs, MSTATUS_FS)); - } -#endif - - *pflags = flags; -} +void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, + target_ulong *cs_base, uint32_t *pflags); RISCVException riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index d41d5cd27c..14d1d3cb72 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -35,6 +35,52 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) #endif } +void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, + target_ulong *cs_base, uint32_t *pflags) +{ + uint32_t flags = 0; + + *pc = env->pc; + *cs_base = 0; + + if (riscv_has_ext(env, RVV)) { + uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype); + bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl); + flags = FIELD_DP32(flags, TB_FLAGS, VILL, + FIELD_EX64(env->vtype, VTYPE, VILL)); + flags = FIELD_DP32(flags, TB_FLAGS, SEW, + FIELD_EX64(env->vtype, VTYPE, VSEW)); + flags = FIELD_DP32(flags, TB_FLAGS, LMUL, + FIELD_EX64(env->vtype, VTYPE, VLMUL)); + flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax); + } else { + flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1); + } + +#ifdef CONFIG_USER_ONLY + flags |= TB_FLAGS_MSTATUS_FS; +#else + flags |= cpu_mmu_index(env, 0); + if (riscv_cpu_fp_enabled(env)) { + flags |= env->mstatus & MSTATUS_FS; + } + + if (riscv_has_ext(env, RVH)) { + if (env->priv == PRV_M || + (env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || + (env->priv == PRV_U && !riscv_cpu_virt_enabled(env) && + get_field(env->hstatus, HSTATUS_HU))) { + flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1); + } + + flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS, + get_field(env->mstatus_hs, MSTATUS_FS)); + } +#endif + + *pflags = flags; +} + #ifndef CONFIG_USER_ONLY static int riscv_cpu_local_irq_pending(CPURISCVState *env) { From 99bc874fb3a0709c36ae4e594a1262ce1660e698 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:16:56 -0700 Subject: [PATCH 09/33] target/riscv: Create RISCVMXL enumeration Move the MXL_RV* defines to enumerators. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-3-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/cpu_bits.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 3aa2512d13..cffcd3a5df 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -364,9 +364,11 @@ #define MISA32_MXL 0xC0000000 #define MISA64_MXL 0xC000000000000000ULL -#define MXL_RV32 1 -#define MXL_RV64 2 -#define MXL_RV128 3 +typedef enum { + MXL_RV32 = 1, + MXL_RV64 = 2, + MXL_RV128 = 3, +} RISCVMXL; /* sstatus CSR bits */ #define SSTATUS_UIE 0x00000001 From e91a7227cb802ea62ffa14707ebc2f588b01213d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:16:57 -0700 Subject: [PATCH 10/33] target/riscv: Split misa.mxl and misa.ext The hw representation of misa.mxl is at the high bits of the misa csr. Representing this in the same way inside QEMU results in overly complex code trying to check that field. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-4-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- linux-user/elfload.c | 2 +- linux-user/riscv/cpu_loop.c | 2 +- target/riscv/cpu.c | 78 +++++++++++++++++++++---------------- target/riscv/cpu.h | 15 +++---- target/riscv/csr.c | 44 ++++++++++++++------- target/riscv/gdbstub.c | 8 ++-- target/riscv/machine.c | 10 +++-- target/riscv/translate.c | 10 +++-- 8 files changed, 100 insertions(+), 69 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index eb32f3e2cb..f9b8261692 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1448,7 +1448,7 @@ static uint32_t get_elf_hwcap(void) uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A') | MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C'); - return cpu->env.misa & mask; + return cpu->env.misa_ext & mask; #undef MISA_BIT } diff --git a/linux-user/riscv/cpu_loop.c b/linux-user/riscv/cpu_loop.c index 9859a366e4..e5bb6d908a 100644 --- a/linux-user/riscv/cpu_loop.c +++ b/linux-user/riscv/cpu_loop.c @@ -133,7 +133,7 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) env->gpr[xSP] = regs->sp; env->elf_flags = info->elf_flags; - if ((env->misa & RVE) && !(env->elf_flags & EF_RISCV_RVE)) { + if ((env->misa_ext & RVE) && !(env->elf_flags & EF_RISCV_RVE)) { error_report("Incompatible ELF: RVE cpu requires RVE ABI binary"); exit(EXIT_FAILURE); } diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 11bb59ac6d..f18bb4b21e 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -110,16 +110,13 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, bool async) bool riscv_cpu_is_32bit(CPURISCVState *env) { - if (env->misa & RV64) { - return false; - } - - return true; + return env->misa_mxl == MXL_RV32; } -static void set_misa(CPURISCVState *env, target_ulong misa) +static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext) { - env->misa_mask = env->misa = misa; + env->misa_mxl_max = env->misa_mxl = mxl; + env->misa_ext_mask = env->misa_ext = ext; } static void set_priv_version(CPURISCVState *env, int priv_ver) @@ -148,9 +145,9 @@ static void riscv_any_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; #if defined(TARGET_RISCV32) - set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVU); + set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU); #elif defined(TARGET_RISCV64) - set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVU); + set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU); #endif set_priv_version(env, PRIV_VERSION_1_11_0); } @@ -160,20 +157,20 @@ static void rv64_base_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; /* We set this in the realise function */ - set_misa(env, RV64); + set_misa(env, MXL_RV64, 0); } static void rv64_sifive_u_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); + set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); } static void rv64_sifive_e_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU); + set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); qdev_prop_set_bit(DEVICE(obj), "mmu", false); } @@ -182,20 +179,20 @@ static void rv32_base_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; /* We set this in the realise function */ - set_misa(env, RV32); + set_misa(env, MXL_RV32, 0); } static void rv32_sifive_u_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); + set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); } static void rv32_sifive_e_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV32 | RVI | RVM | RVA | RVC | RVU); + set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); qdev_prop_set_bit(DEVICE(obj), "mmu", false); } @@ -203,7 +200,7 @@ static void rv32_sifive_e_cpu_init(Object *obj) static void rv32_ibex_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV32 | RVI | RVM | RVC | RVU); + set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); qdev_prop_set_bit(DEVICE(obj), "mmu", false); qdev_prop_set_bit(DEVICE(obj), "x-epmp", true); @@ -212,7 +209,7 @@ static void rv32_ibex_cpu_init(Object *obj) static void rv32_imafcu_nommu_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVC | RVU); + set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); set_resetvec(env, DEFAULT_RSTVEC); qdev_prop_set_bit(DEVICE(obj), "mmu", false); @@ -360,6 +357,7 @@ static void riscv_cpu_reset(DeviceState *dev) mcc->parent_reset(dev); #ifndef CONFIG_USER_ONLY + env->misa_mxl = env->misa_mxl_max; env->priv = PRV_M; env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV); env->mcause = 0; @@ -388,7 +386,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) CPURISCVState *env = &cpu->env; RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); int priv_version = 0; - target_ulong target_misa = env->misa; Error *local_err = NULL; cpu_exec_realizefn(cs, &local_err); @@ -434,8 +431,23 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) set_resetvec(env, cpu->cfg.resetvec); - /* If only XLEN is set for misa, then set misa from properties */ - if (env->misa == RV32 || env->misa == RV64) { + /* Validate that MISA_MXL is set properly. */ + switch (env->misa_mxl_max) { +#ifdef TARGET_RISCV64 + case MXL_RV64: + break; +#endif + case MXL_RV32: + break; + default: + g_assert_not_reached(); + } + assert(env->misa_mxl_max == env->misa_mxl); + + /* If only MISA_EXT is unset for misa, then set it from properties */ + if (env->misa_ext == 0) { + uint32_t ext = 0; + /* Do some ISA extension error checking */ if (cpu->cfg.ext_i && cpu->cfg.ext_e) { error_setg(errp, @@ -462,38 +474,38 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) /* Set the ISA extensions, checks should have happened above */ if (cpu->cfg.ext_i) { - target_misa |= RVI; + ext |= RVI; } if (cpu->cfg.ext_e) { - target_misa |= RVE; + ext |= RVE; } if (cpu->cfg.ext_m) { - target_misa |= RVM; + ext |= RVM; } if (cpu->cfg.ext_a) { - target_misa |= RVA; + ext |= RVA; } if (cpu->cfg.ext_f) { - target_misa |= RVF; + ext |= RVF; } if (cpu->cfg.ext_d) { - target_misa |= RVD; + ext |= RVD; } if (cpu->cfg.ext_c) { - target_misa |= RVC; + ext |= RVC; } if (cpu->cfg.ext_s) { - target_misa |= RVS; + ext |= RVS; } if (cpu->cfg.ext_u) { - target_misa |= RVU; + ext |= RVU; } if (cpu->cfg.ext_h) { - target_misa |= RVH; + ext |= RVH; } if (cpu->cfg.ext_v) { int vext_version = VEXT_VERSION_0_07_1; - target_misa |= RVV; + ext |= RVV; if (!is_power_of_2(cpu->cfg.vlen)) { error_setg(errp, "Vector extension VLEN must be power of 2"); @@ -532,7 +544,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) set_vext_version(env, vext_version); } - set_misa(env, target_misa); + set_misa(env, env->misa_mxl, ext); } riscv_cpu_register_gdb_regs_for_features(cs); @@ -708,7 +720,7 @@ char *riscv_isa_string(RISCVCPU *cpu) char *isa_str = g_new(char, maxlen); char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS); for (i = 0; i < sizeof(riscv_exts); i++) { - if (cpu->env.misa & RV(riscv_exts[i])) { + if (cpu->env.misa_ext & RV(riscv_exts[i])) { *p++ = qemu_tolower(riscv_exts[i]); } } diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index f543364d51..90d11e3c2a 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -25,6 +25,7 @@ #include "exec/cpu-defs.h" #include "fpu/softfloat-types.h" #include "qom/object.h" +#include "cpu_bits.h" #define TCG_GUEST_DEFAULT_MO 0 @@ -51,9 +52,6 @@ # define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE64 #endif -#define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2)) -#define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2)) - #define RV(x) ((target_ulong)1 << (x - 'A')) #define RVI RV('I') @@ -133,8 +131,12 @@ struct CPURISCVState { target_ulong priv_ver; target_ulong bext_ver; target_ulong vext_ver; - target_ulong misa; - target_ulong misa_mask; + + /* RISCVMXL, but uint32_t for vmstate migration */ + uint32_t misa_mxl; /* current mxl */ + uint32_t misa_mxl_max; /* max mxl for this cpu */ + uint32_t misa_ext; /* current extensions */ + uint32_t misa_ext_mask; /* max ext for this cpu */ uint32_t features; @@ -313,7 +315,7 @@ struct RISCVCPU { static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext) { - return (env->misa & ext) != 0; + return (env->misa_ext & ext) != 0; } static inline bool riscv_feature(CPURISCVState *env, int feature) @@ -322,7 +324,6 @@ static inline bool riscv_feature(CPURISCVState *env, int feature) } #include "cpu_user.h" -#include "cpu_bits.h" extern const char * const riscv_int_regnames[]; extern const char * const riscv_fpr_regnames[]; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 23fbbd3216..d0c86a300d 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -39,7 +39,7 @@ static RISCVException fs(CPURISCVState *env, int csrno) { #if !defined(CONFIG_USER_ONLY) /* loose check condition for fcsr in vector extension */ - if ((csrno == CSR_FCSR) && (env->misa & RVV)) { + if ((csrno == CSR_FCSR) && (env->misa_ext & RVV)) { return RISCV_EXCP_NONE; } if (!env->debugger && !riscv_cpu_fp_enabled(env)) { @@ -51,7 +51,7 @@ static RISCVException fs(CPURISCVState *env, int csrno) static RISCVException vs(CPURISCVState *env, int csrno) { - if (env->misa & RVV) { + if (env->misa_ext & RVV) { return RISCV_EXCP_NONE; } return RISCV_EXCP_ILLEGAL_INST; @@ -557,7 +557,22 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno, static RISCVException read_misa(CPURISCVState *env, int csrno, target_ulong *val) { - *val = env->misa; + target_ulong misa; + + switch (env->misa_mxl) { + case MXL_RV32: + misa = (target_ulong)MXL_RV32 << 30; + break; +#ifdef TARGET_RISCV64 + case MXL_RV64: + misa = (target_ulong)MXL_RV64 << 62; + break; +#endif + default: + g_assert_not_reached(); + } + + *val = misa | env->misa_ext; return RISCV_EXCP_NONE; } @@ -583,8 +598,13 @@ static RISCVException write_misa(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } + /* + * misa.MXL writes are not supported by QEMU. + * Drop writes to those bits. + */ + /* Mask extensions that are not supported by this hart */ - val &= env->misa_mask; + val &= env->misa_ext_mask; /* Mask extensions that are not supported by QEMU */ val &= (RVI | RVE | RVM | RVA | RVF | RVD | RVC | RVS | RVU); @@ -601,20 +621,14 @@ static RISCVException write_misa(CPURISCVState *env, int csrno, val &= ~RVC; } - /* misa.MXL writes are not supported by QEMU */ - if (riscv_cpu_is_32bit(env)) { - val = (env->misa & MISA32_MXL) | (val & ~MISA32_MXL); - } else { - val = (env->misa & MISA64_MXL) | (val & ~MISA64_MXL); + /* If nothing changed, do nothing. */ + if (val == env->misa_ext) { + return RISCV_EXCP_NONE; } /* flush translation cache */ - if (val != env->misa) { - tb_flush(env_cpu(env)); - } - - env->misa = val; - + tb_flush(env_cpu(env)); + env->misa_ext = val; return RISCV_EXCP_NONE; } diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index a7a9c0b1fe..5257df0217 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -54,10 +54,10 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n) { if (n < 32) { - if (env->misa & RVD) { + if (env->misa_ext & RVD) { return gdb_get_reg64(buf, env->fpr[n]); } - if (env->misa & RVF) { + if (env->misa_ext & RVF) { return gdb_get_reg32(buf, env->fpr[n]); } /* there is hole between ft11 and fflags in fpu.xml */ @@ -191,10 +191,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; - if (env->misa & RVD) { + if (env->misa_ext & RVD) { gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, 36, "riscv-64bit-fpu.xml", 0); - } else if (env->misa & RVF) { + } else if (env->misa_ext & RVF) { gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, 36, "riscv-32bit-fpu.xml", 0); } diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 16a08302da..f64b2a96c1 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -140,8 +140,8 @@ static const VMStateDescription vmstate_hyper = { const VMStateDescription vmstate_riscv_cpu = { .name = "cpu", - .version_id = 2, - .minimum_version_id = 2, + .version_id = 3, + .minimum_version_id = 3, .fields = (VMStateField[]) { VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), @@ -153,8 +153,10 @@ const VMStateDescription vmstate_riscv_cpu = { VMSTATE_UINTTL(env.guest_phys_fault_addr, RISCVCPU), VMSTATE_UINTTL(env.priv_ver, RISCVCPU), VMSTATE_UINTTL(env.vext_ver, RISCVCPU), - VMSTATE_UINTTL(env.misa, RISCVCPU), - VMSTATE_UINTTL(env.misa_mask, RISCVCPU), + VMSTATE_UINT32(env.misa_mxl, RISCVCPU), + VMSTATE_UINT32(env.misa_ext, RISCVCPU), + VMSTATE_UINT32(env.misa_mxl_max, RISCVCPU), + VMSTATE_UINT32(env.misa_ext_mask, RISCVCPU), VMSTATE_UINT32(env.features, RISCVCPU), VMSTATE_UINTTL(env.priv, RISCVCPU), VMSTATE_UINTTL(env.virt, RISCVCPU), diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 62214e97fa..0aa2122529 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -55,7 +55,8 @@ typedef struct DisasContext { /* pc_succ_insn points to the instruction following base.pc_next */ target_ulong pc_succ_insn; target_ulong priv_ver; - target_ulong misa; + RISCVMXL xl; + uint32_t misa_ext; uint32_t opcode; uint32_t mstatus_fs; uint32_t mstatus_hs_fs; @@ -86,7 +87,7 @@ typedef struct DisasContext { static inline bool has_ext(DisasContext *ctx, uint32_t ext) { - return ctx->misa & ext; + return ctx->misa_ext & ext; } #ifdef TARGET_RISCV32 @@ -96,7 +97,7 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext) #else static inline bool is_32bit(DisasContext *ctx) { - return (ctx->misa & RV32) == RV32; + return ctx->xl == MXL_RV32; } #endif @@ -513,7 +514,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) #else ctx->virt_enabled = false; #endif - ctx->misa = env->misa; + ctx->xl = env->misa_mxl; + ctx->misa_ext = env->misa_ext; ctx->frm = -1; /* unknown rounding mode */ ctx->ext_ifencei = cpu->cfg.ext_ifencei; ctx->vlen = cpu->cfg.vlen; From db23e5d981ab22da0bfe1150f4828d08484b1fba Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:16:58 -0700 Subject: [PATCH 11/33] target/riscv: Replace riscv_cpu_is_32bit with riscv_cpu_mxl Shortly, the set of supported XL will not be just 32 and 64, and representing that properly using the enumeration will be imperative. Two places, booting and gdb, intentionally use misa_mxl_max to emphasize the use of the reset value of misa.mxl, and not the current cpu state. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-5-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- hw/riscv/boot.c | 2 +- semihosting/arm-compat-semi.c | 2 +- target/riscv/cpu.c | 24 ++++++++++++++---------- target/riscv/cpu.h | 9 ++++++++- target/riscv/cpu_helper.c | 12 ++++++------ target/riscv/csr.c | 24 ++++++++++++------------ target/riscv/gdbstub.c | 2 +- target/riscv/monitor.c | 4 ++-- 8 files changed, 45 insertions(+), 34 deletions(-) diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 993bf89064..d1ffc7b56c 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -35,7 +35,7 @@ bool riscv_is_32bit(RISCVHartArrayState *harts) { - return riscv_cpu_is_32bit(&harts->harts[0].env); + return harts->harts[0].env.misa_mxl_max == MXL_RV32; } target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState *harts, diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c index 01badea99c..37963becae 100644 --- a/semihosting/arm-compat-semi.c +++ b/semihosting/arm-compat-semi.c @@ -775,7 +775,7 @@ static inline bool is_64bit_semihosting(CPUArchState *env) #if defined(TARGET_ARM) return is_a64(env); #elif defined(TARGET_RISCV) - return !riscv_cpu_is_32bit(env); + return riscv_cpu_mxl(env) != MXL_RV32; #else #error un-handled architecture #endif diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index f18bb4b21e..3d144af1ab 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -108,11 +108,6 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, bool async) } } -bool riscv_cpu_is_32bit(CPURISCVState *env) -{ - return env->misa_mxl == MXL_RV32; -} - static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext) { env->misa_mxl_max = env->misa_mxl = mxl; @@ -249,7 +244,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) #ifndef CONFIG_USER_ONLY qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid); qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", (target_ulong)env->mstatus); - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ", (target_ulong)(env->mstatus >> 32)); } @@ -372,10 +367,16 @@ static void riscv_cpu_reset(DeviceState *dev) static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) { RISCVCPU *cpu = RISCV_CPU(s); - if (riscv_cpu_is_32bit(&cpu->env)) { + + switch (riscv_cpu_mxl(&cpu->env)) { + case MXL_RV32: info->print_insn = print_insn_riscv32; - } else { + break; + case MXL_RV64: info->print_insn = print_insn_riscv64; + break; + default: + g_assert_not_reached(); } } @@ -634,10 +635,13 @@ static gchar *riscv_gdb_arch_name(CPUState *cs) RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; - if (riscv_cpu_is_32bit(env)) { + switch (riscv_cpu_mxl(env)) { + case MXL_RV32: return g_strdup("riscv:rv32"); - } else { + case MXL_RV64: return g_strdup("riscv:rv64"); + default: + g_assert_not_reached(); } } diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 90d11e3c2a..e23157b05c 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -396,7 +396,14 @@ FIELD(TB_FLAGS, VILL, 9, 1) FIELD(TB_FLAGS, HLSX, 10, 1) FIELD(TB_FLAGS, MSTATUS_HS_FS, 11, 2) -bool riscv_cpu_is_32bit(CPURISCVState *env); +#ifdef TARGET_RISCV32 +#define riscv_cpu_mxl(env) ((void)(env), MXL_RV32) +#else +static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env) +{ + return env->misa_mxl; +} +#endif /* * A simplification for VLMAX diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 14d1d3cb72..403f54171d 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -152,7 +152,7 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env) void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env) { - uint64_t sd = riscv_cpu_is_32bit(env) ? MSTATUS32_SD : MSTATUS64_SD; + uint64_t sd = riscv_cpu_mxl(env) == MXL_RV32 ? MSTATUS32_SD : MSTATUS64_SD; uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS | MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE | MSTATUS64_UXL | sd; @@ -447,7 +447,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, if (first_stage == true) { if (use_background) { - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { base = (hwaddr)get_field(env->vsatp, SATP32_PPN) << PGSHIFT; vm = get_field(env->vsatp, SATP32_MODE); } else { @@ -455,7 +455,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, vm = get_field(env->vsatp, SATP64_MODE); } } else { - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { base = (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHIFT; vm = get_field(env->satp, SATP32_MODE); } else { @@ -465,7 +465,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, } widened = 0; } else { - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { base = (hwaddr)get_field(env->hgatp, SATP32_PPN) << PGSHIFT; vm = get_field(env->hgatp, SATP32_MODE); } else { @@ -558,7 +558,7 @@ restart: } target_ulong pte; - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { pte = address_space_ldl(cs->as, pte_addr, attrs, &res); } else { pte = address_space_ldq(cs->as, pte_addr, attrs, &res); @@ -678,7 +678,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, int page_fault_exceptions, vm; uint64_t stap_mode; - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { stap_mode = SATP32_MODE; } else { stap_mode = SATP64_MODE; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index d0c86a300d..9c0753bc8b 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -95,7 +95,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno) } break; } - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { switch (csrno) { case CSR_CYCLEH: if (!get_field(env->hcounteren, COUNTEREN_CY) && @@ -130,7 +130,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno) static RISCVException ctr32(CPURISCVState *env, int csrno) { - if (!riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) != MXL_RV32) { return RISCV_EXCP_ILLEGAL_INST; } @@ -145,7 +145,7 @@ static RISCVException any(CPURISCVState *env, int csrno) static RISCVException any32(CPURISCVState *env, int csrno) { - if (!riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) != MXL_RV32) { return RISCV_EXCP_ILLEGAL_INST; } @@ -180,7 +180,7 @@ static RISCVException hmode(CPURISCVState *env, int csrno) static RISCVException hmode32(CPURISCVState *env, int csrno) { - if (!riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) != MXL_RV32) { if (riscv_cpu_virt_enabled(env)) { return RISCV_EXCP_ILLEGAL_INST; } else { @@ -486,7 +486,7 @@ static RISCVException read_mstatus(CPURISCVState *env, int csrno, static int validate_vm(CPURISCVState *env, target_ulong vm) { - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { return valid_vm_1_10_32[vm & 0xf]; } else { return valid_vm_1_10_64[vm & 0xf]; @@ -510,7 +510,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR | MSTATUS_TW; - if (!riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) != MXL_RV32) { /* * RV32: MPV and GVA are not in mstatus. The current plan is to * add them to mstatush. For now, we just don't support it. @@ -522,7 +522,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) | ((mstatus & MSTATUS_XS) == MSTATUS_XS); - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { mstatus = set_field(mstatus, MSTATUS32_SD, dirty); } else { mstatus = set_field(mstatus, MSTATUS64_SD, dirty); @@ -795,7 +795,7 @@ static RISCVException read_sstatus(CPURISCVState *env, int csrno, { target_ulong mask = (sstatus_v1_10_mask); - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { mask |= SSTATUS32_SD; } else { mask |= SSTATUS64_SD; @@ -1006,7 +1006,7 @@ static RISCVException write_satp(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { vm = validate_vm(env, get_field(val, SATP32_MODE)); mask = (val ^ env->satp) & (SATP32_MODE | SATP32_ASID | SATP32_PPN); asid = (val ^ env->satp) & SATP32_ASID; @@ -1034,7 +1034,7 @@ static RISCVException read_hstatus(CPURISCVState *env, int csrno, target_ulong *val) { *val = env->hstatus; - if (!riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) != MXL_RV32) { /* We only support 64-bit VSXL */ *val = set_field(*val, HSTATUS_VSXL, 2); } @@ -1047,7 +1047,7 @@ static RISCVException write_hstatus(CPURISCVState *env, int csrno, target_ulong val) { env->hstatus = val; - if (!riscv_cpu_is_32bit(env) && get_field(val, HSTATUS_VSXL) != 2) { + if (riscv_cpu_mxl(env) != MXL_RV32 && get_field(val, HSTATUS_VSXL) != 2) { qemu_log_mask(LOG_UNIMP, "QEMU does not support mixed HSXLEN options."); } if (get_field(val, HSTATUS_VSBE) != 0) { @@ -1215,7 +1215,7 @@ static RISCVException write_htimedelta(CPURISCVState *env, int csrno, return RISCV_EXCP_ILLEGAL_INST; } - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { env->htimedelta = deposit64(env->htimedelta, 0, 32, (uint64_t)val); } else { env->htimedelta = val; diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 5257df0217..23429179e2 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -161,7 +161,7 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg) CPURISCVState *env = &cpu->env; GString *s = g_string_new(NULL); riscv_csr_predicate_fn predicate; - int bitsize = riscv_cpu_is_32bit(env) ? 32 : 64; + int bitsize = 16 << env->misa_mxl_max; int i; g_string_printf(s, ""); diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c index f7e6ea72b3..7efb4b62c1 100644 --- a/target/riscv/monitor.c +++ b/target/riscv/monitor.c @@ -150,7 +150,7 @@ static void mem_info_svxx(Monitor *mon, CPUArchState *env) target_ulong last_size; int last_attr; - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { base = (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHIFT; vm = get_field(env->satp, SATP32_MODE); } else { @@ -220,7 +220,7 @@ void hmp_info_mem(Monitor *mon, const QDict *qdict) return; } - if (riscv_cpu_is_32bit(env)) { + if (riscv_cpu_mxl(env) == MXL_RV32) { if (!(env->satp & SATP32_MODE)) { monitor_printf(mon, "No translation or protection\n"); return; From 92371bd9033e5a50a7541d96ff8ad067930a4f93 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:16:59 -0700 Subject: [PATCH 12/33] target/riscv: Add MXL/SXL/UXL to TB_FLAGS Begin adding support for switching XLEN at runtime. Extract the effective XLEN from MISA and MSTATUS and store for use during translation. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-6-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 8 ++++++++ target/riscv/cpu.h | 2 ++ target/riscv/cpu_helper.c | 33 +++++++++++++++++++++++++++++++++ target/riscv/csr.c | 3 +++ target/riscv/translate.c | 2 +- 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 3d144af1ab..dd9eccd68e 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -355,6 +355,14 @@ static void riscv_cpu_reset(DeviceState *dev) env->misa_mxl = env->misa_mxl_max; env->priv = PRV_M; env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV); + if (env->misa_mxl > MXL_RV32) { + /* + * The reset status of SXL/UXL is undefined, but mstatus is WARL + * and we must ensure that the value after init is valid for read. + */ + env->mstatus = set_field(env->mstatus, MSTATUS64_SXL, env->misa_mxl); + env->mstatus = set_field(env->mstatus, MSTATUS64_UXL, env->misa_mxl); + } env->mcause = 0; env->pc = env->resetvec; env->two_stage_lookup = false; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index e23157b05c..a33dc30be8 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -395,6 +395,8 @@ FIELD(TB_FLAGS, VILL, 9, 1) /* Is a Hypervisor instruction load/store allowed? */ FIELD(TB_FLAGS, HLSX, 10, 1) FIELD(TB_FLAGS, MSTATUS_HS_FS, 11, 2) +/* The combination of MXL/SXL/UXL that applies to the current cpu mode. */ +FIELD(TB_FLAGS, XL, 13, 2) #ifdef TARGET_RISCV32 #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 403f54171d..429afd1f48 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -35,6 +35,37 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) #endif } +static RISCVMXL cpu_get_xl(CPURISCVState *env) +{ +#if defined(TARGET_RISCV32) + return MXL_RV32; +#elif defined(CONFIG_USER_ONLY) + return MXL_RV64; +#else + RISCVMXL xl = riscv_cpu_mxl(env); + + /* + * When emulating a 32-bit-only cpu, use RV32. + * When emulating a 64-bit cpu, and MXL has been reduced to RV32, + * MSTATUSH doesn't have UXL/SXL, therefore XLEN cannot be widened + * back to RV64 for lower privs. + */ + if (xl != MXL_RV32) { + switch (env->priv) { + case PRV_M: + break; + case PRV_U: + xl = get_field(env->mstatus, MSTATUS64_UXL); + break; + default: /* PRV_S | PRV_H */ + xl = get_field(env->mstatus, MSTATUS64_SXL); + break; + } + } + return xl; +#endif +} + void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, target_ulong *cs_base, uint32_t *pflags) { @@ -78,6 +109,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, } #endif + flags = FIELD_DP32(flags, TB_FLAGS, XL, cpu_get_xl(env)); + *pflags = flags; } diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 9c0753bc8b..c4a479ddd2 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -526,6 +526,9 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, mstatus = set_field(mstatus, MSTATUS32_SD, dirty); } else { mstatus = set_field(mstatus, MSTATUS64_SD, dirty); + /* SXL and UXL fields are for now read only */ + mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64); + mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64); } env->mstatus = mstatus; diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 0aa2122529..77cad9bc45 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -514,7 +514,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) #else ctx->virt_enabled = false; #endif - ctx->xl = env->misa_mxl; ctx->misa_ext = env->misa_ext; ctx->frm = -1; /* unknown rounding mode */ ctx->ext_ifencei = cpu->cfg.ext_ifencei; @@ -526,6 +525,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL); ctx->mlen = 1 << (ctx->sew + 3 - ctx->lmul); ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX); + ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL); ctx->cs = cs; ctx->w = false; ctx->ntemp = 0; From fbb48032e46976cfc94a90a4233a2060fdc36a4e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:17:00 -0700 Subject: [PATCH 13/33] target/riscv: Use REQUIRE_64BIT in amo_check64 Use the same REQUIRE_64BIT check that we use elsewhere, rather than open-coding the use of is_32bit. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-7-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 45be491ed4..233131bae1 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -743,7 +743,8 @@ static bool amo_check(DisasContext *s, arg_rwdvm* a) static bool amo_check64(DisasContext *s, arg_rwdvm* a) { - return !is_32bit(s) && amo_check(s, a); + REQUIRE_64BIT(s); + return amo_check(s, a); } GEN_VEXT_TRANS(vamoswapw_v, 0, rwdvm, amo_op, amo_check) From 4e97d459a0f2b92815c2c2c6eb96b75e2235b42e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:17:01 -0700 Subject: [PATCH 14/33] target/riscv: Properly check SEW in amo_op We're currently assuming SEW <= 3, and the "else" from the SEW == 3 must be less. Use a switch and explicitly bound both SEW and SEQ for all cases. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-8-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 26 +++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 233131bae1..17ee3babef 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -704,18 +704,20 @@ static bool amo_op(DisasContext *s, arg_rwdvm *a, uint8_t seq) gen_helper_exit_atomic(cpu_env); s->base.is_jmp = DISAS_NORETURN; return true; - } else { - if (s->sew == 3) { - if (!is_32bit(s)) { - fn = fnsd[seq]; - } else { - /* Check done in amo_check(). */ - g_assert_not_reached(); - } - } else { - assert(seq < ARRAY_SIZE(fnsw)); - fn = fnsw[seq]; - } + } + + switch (s->sew) { + case 0 ... 2: + assert(seq < ARRAY_SIZE(fnsw)); + fn = fnsw[seq]; + break; + case 3: + /* XLEN check done in amo_check(). */ + assert(seq < ARRAY_SIZE(fnsd)); + fn = fnsd[seq]; + break; + default: + g_assert_not_reached(); } data = FIELD_DP32(data, VDATA, MLEN, s->mlen); From 905b9fcde1fb84d718d95369c5d886bc81bbdd8e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:17:02 -0700 Subject: [PATCH 15/33] target/riscv: Replace is_32bit with get_xl/get_xlen In preparation for RV128, replace a simple predicate with a more versatile test. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-9-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/translate.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 77cad9bc45..d0ba54091e 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -91,16 +91,19 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext) } #ifdef TARGET_RISCV32 -# define is_32bit(ctx) true +#define get_xl(ctx) MXL_RV32 #elif defined(CONFIG_USER_ONLY) -# define is_32bit(ctx) false +#define get_xl(ctx) MXL_RV64 #else -static inline bool is_32bit(DisasContext *ctx) -{ - return ctx->xl == MXL_RV32; -} +#define get_xl(ctx) ((ctx)->xl) #endif +/* The word size for this machine mode. */ +static inline int __attribute__((unused)) get_xlen(DisasContext *ctx) +{ + return 16 << get_xl(ctx); +} + /* The word size for this operation. */ static inline int oper_len(DisasContext *ctx) { @@ -257,7 +260,7 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) static void mark_fs_dirty(DisasContext *ctx) { TCGv tmp; - target_ulong sd = is_32bit(ctx) ? MSTATUS32_SD : MSTATUS64_SD; + target_ulong sd = get_xl(ctx) == MXL_RV32 ? MSTATUS32_SD : MSTATUS64_SD; if (ctx->mstatus_fs != MSTATUS_FS) { /* Remember the state change for the rest of the TB. */ @@ -316,16 +319,16 @@ EX_SH(12) } \ } while (0) -#define REQUIRE_32BIT(ctx) do { \ - if (!is_32bit(ctx)) { \ - return false; \ - } \ +#define REQUIRE_32BIT(ctx) do { \ + if (get_xl(ctx) != MXL_RV32) { \ + return false; \ + } \ } while (0) -#define REQUIRE_64BIT(ctx) do { \ - if (is_32bit(ctx)) { \ - return false; \ - } \ +#define REQUIRE_64BIT(ctx) do { \ + if (get_xl(ctx) < MXL_RV64) { \ + return false; \ + } \ } while (0) static int ex_rvc_register(DisasContext *ctx, int reg) From 7667cafd5a0d173d1853b4d8414d4a98df1374dc Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:17:03 -0700 Subject: [PATCH 16/33] target/riscv: Replace DisasContext.w with DisasContext.ol In preparation for RV128, consider more than just "w" for operand size modification. This will be used for the "d" insns from RV128 as well. Rename oper_len to get_olen to better match get_xlen. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-10-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 8 +-- target/riscv/insn_trans/trans_rvi.c.inc | 18 +++---- target/riscv/insn_trans/trans_rvm.c.inc | 10 ++-- target/riscv/translate.c | 71 ++++++++++++++++--------- 4 files changed, 63 insertions(+), 44 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 3095624f32..9ef8ab94ad 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -344,7 +344,7 @@ static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a) { REQUIRE_64BIT(ctx); REQUIRE_ZBB(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl); } @@ -370,7 +370,7 @@ static bool trans_rorw(DisasContext *ctx, arg_rorw *a) { REQUIRE_64BIT(ctx); REQUIRE_ZBB(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_shift(ctx, a, EXT_NONE, gen_rorw); } @@ -378,7 +378,7 @@ static bool trans_roriw(DisasContext *ctx, arg_roriw *a) { REQUIRE_64BIT(ctx); REQUIRE_ZBB(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_rorw); } @@ -404,7 +404,7 @@ static bool trans_rolw(DisasContext *ctx, arg_rolw *a) { REQUIRE_64BIT(ctx); REQUIRE_ZBB(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_shift(ctx, a, EXT_NONE, gen_rolw); } diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index a6a57c94bb..9cf0383cfb 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -331,14 +331,14 @@ static bool trans_and(DisasContext *ctx, arg_and *a) static bool trans_addiw(DisasContext *ctx, arg_addiw *a) { REQUIRE_64BIT(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_arith_imm_fn(ctx, a, EXT_NONE, tcg_gen_addi_tl); } static bool trans_slliw(DisasContext *ctx, arg_slliw *a) { REQUIRE_64BIT(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl); } @@ -350,7 +350,7 @@ static void gen_srliw(TCGv dst, TCGv src, target_long shamt) static bool trans_srliw(DisasContext *ctx, arg_srliw *a) { REQUIRE_64BIT(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_srliw); } @@ -362,42 +362,42 @@ static void gen_sraiw(TCGv dst, TCGv src, target_long shamt) static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a) { REQUIRE_64BIT(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_sraiw); } static bool trans_addw(DisasContext *ctx, arg_addw *a) { REQUIRE_64BIT(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_NONE, tcg_gen_add_tl); } static bool trans_subw(DisasContext *ctx, arg_subw *a) { REQUIRE_64BIT(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_NONE, tcg_gen_sub_tl); } static bool trans_sllw(DisasContext *ctx, arg_sllw *a) { REQUIRE_64BIT(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_shift(ctx, a, EXT_NONE, tcg_gen_shl_tl); } static bool trans_srlw(DisasContext *ctx, arg_srlw *a) { REQUIRE_64BIT(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_shift(ctx, a, EXT_ZERO, tcg_gen_shr_tl); } static bool trans_sraw(DisasContext *ctx, arg_sraw *a) { REQUIRE_64BIT(ctx); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl); } diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index b89a85ad3a..9a1fe3c799 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -214,7 +214,7 @@ static bool trans_mulw(DisasContext *ctx, arg_mulw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_NONE, tcg_gen_mul_tl); } @@ -222,7 +222,7 @@ static bool trans_divw(DisasContext *ctx, arg_divw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_SIGN, gen_div); } @@ -230,7 +230,7 @@ static bool trans_divuw(DisasContext *ctx, arg_divuw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_ZERO, gen_divu); } @@ -238,7 +238,7 @@ static bool trans_remw(DisasContext *ctx, arg_remw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_SIGN, gen_rem); } @@ -246,6 +246,6 @@ static bool trans_remuw(DisasContext *ctx, arg_remuw *a) { REQUIRE_64BIT(ctx); REQUIRE_EXT(ctx, RVM); - ctx->w = true; + ctx->ol = MXL_RV32; return gen_arith(ctx, a, EXT_ZERO, gen_remu); } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index d0ba54091e..afd59ef690 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -67,7 +67,7 @@ typedef struct DisasContext { to any system register, which includes CSR_FRM, so we do not have to reset this known value. */ int frm; - bool w; + RISCVMXL ol; bool virt_enabled; bool ext_ifencei; bool hlsx; @@ -104,12 +104,17 @@ static inline int __attribute__((unused)) get_xlen(DisasContext *ctx) return 16 << get_xl(ctx); } -/* The word size for this operation. */ -static inline int oper_len(DisasContext *ctx) -{ - return ctx->w ? 32 : TARGET_LONG_BITS; -} +/* The operation length, as opposed to the xlen. */ +#ifdef TARGET_RISCV32 +#define get_ol(ctx) MXL_RV32 +#else +#define get_ol(ctx) ((ctx)->ol) +#endif +static inline int get_olen(DisasContext *ctx) +{ + return 16 << get_ol(ctx); +} /* * RISC-V requires NaN-boxing of narrower width floating point values. @@ -197,24 +202,34 @@ static TCGv get_gpr(DisasContext *ctx, int reg_num, DisasExtend ext) return ctx->zero; } - switch (ctx->w ? ext : EXT_NONE) { - case EXT_NONE: - return cpu_gpr[reg_num]; - case EXT_SIGN: - t = temp_new(ctx); - tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]); - return t; - case EXT_ZERO: - t = temp_new(ctx); - tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]); - return t; + switch (get_ol(ctx)) { + case MXL_RV32: + switch (ext) { + case EXT_NONE: + break; + case EXT_SIGN: + t = temp_new(ctx); + tcg_gen_ext32s_tl(t, cpu_gpr[reg_num]); + return t; + case EXT_ZERO: + t = temp_new(ctx); + tcg_gen_ext32u_tl(t, cpu_gpr[reg_num]); + return t; + default: + g_assert_not_reached(); + } + break; + case MXL_RV64: + break; + default: + g_assert_not_reached(); } - g_assert_not_reached(); + return cpu_gpr[reg_num]; } static TCGv dest_gpr(DisasContext *ctx, int reg_num) { - if (reg_num == 0 || ctx->w) { + if (reg_num == 0 || get_olen(ctx) < TARGET_LONG_BITS) { return temp_new(ctx); } return cpu_gpr[reg_num]; @@ -223,10 +238,15 @@ static TCGv dest_gpr(DisasContext *ctx, int reg_num) static void gen_set_gpr(DisasContext *ctx, int reg_num, TCGv t) { if (reg_num != 0) { - if (ctx->w) { + switch (get_ol(ctx)) { + case MXL_RV32: tcg_gen_ext32s_tl(cpu_gpr[reg_num], t); - } else { + break; + case MXL_RV64: tcg_gen_mov_tl(cpu_gpr[reg_num], t); + break; + default: + g_assert_not_reached(); } } } @@ -387,7 +407,7 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext, void (*func)(TCGv, TCGv, target_long)) { TCGv dest, src1; - int max_len = oper_len(ctx); + int max_len = get_olen(ctx); if (a->shamt >= max_len) { return false; @@ -406,7 +426,7 @@ static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext, void (*func)(TCGv, TCGv, TCGv)) { TCGv dest, src1, src2; - int max_len = oper_len(ctx); + int max_len = get_olen(ctx); if (a->shamt >= max_len) { return false; @@ -430,7 +450,7 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext, TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); TCGv ext2 = tcg_temp_new(); - tcg_gen_andi_tl(ext2, src2, oper_len(ctx) - 1); + tcg_gen_andi_tl(ext2, src2, get_olen(ctx) - 1); func(dest, src1, ext2); gen_set_gpr(ctx, a->rd, dest); @@ -530,7 +550,6 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX); ctx->xl = FIELD_EX32(tb_flags, TB_FLAGS, XL); ctx->cs = cs; - ctx->w = false; ctx->ntemp = 0; memset(ctx->temp, 0, sizeof(ctx->temp)); @@ -554,9 +573,9 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) CPURISCVState *env = cpu->env_ptr; uint16_t opcode16 = translator_lduw(env, &ctx->base, ctx->base.pc_next); + ctx->ol = ctx->xl; decode_opc(env, ctx, opcode16); ctx->base.pc_next = ctx->pc_succ_insn; - ctx->w = false; for (int i = ctx->ntemp - 1; i >= 0; --i) { tcg_temp_free(ctx->temp[i]); From 80347ae9f26dfafbd358d7d8d9ad175a2a624365 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:17:04 -0700 Subject: [PATCH 17/33] target/riscv: Use gen_arith_per_ol for RVM The multiply high-part instructions require a separate implementation for RV32 when TARGET_LONG_BITS == 64. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-11-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvm.c.inc | 26 ++++++++++++++++++++++--- target/riscv/translate.c | 16 +++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index 9a1fe3c799..2af0e5c139 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -33,10 +33,16 @@ static void gen_mulh(TCGv ret, TCGv s1, TCGv s2) tcg_temp_free(discard); } +static void gen_mulh_w(TCGv ret, TCGv s1, TCGv s2) +{ + tcg_gen_mul_tl(ret, s1, s2); + tcg_gen_sari_tl(ret, ret, 32); +} + static bool trans_mulh(DisasContext *ctx, arg_mulh *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_NONE, gen_mulh); + return gen_arith_per_ol(ctx, a, EXT_SIGN, gen_mulh, gen_mulh_w); } static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2) @@ -54,10 +60,23 @@ static void gen_mulhsu(TCGv ret, TCGv arg1, TCGv arg2) tcg_temp_free(rh); } +static void gen_mulhsu_w(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv t1 = tcg_temp_new(); + TCGv t2 = tcg_temp_new(); + + tcg_gen_ext32s_tl(t1, arg1); + tcg_gen_ext32u_tl(t2, arg2); + tcg_gen_mul_tl(ret, t1, t2); + tcg_temp_free(t1); + tcg_temp_free(t2); + tcg_gen_sari_tl(ret, ret, 32); +} + static bool trans_mulhsu(DisasContext *ctx, arg_mulhsu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_NONE, gen_mulhsu); + return gen_arith_per_ol(ctx, a, EXT_NONE, gen_mulhsu, gen_mulhsu_w); } static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2) @@ -71,7 +90,8 @@ static void gen_mulhu(TCGv ret, TCGv s1, TCGv s2) static bool trans_mulhu(DisasContext *ctx, arg_mulhu *a) { REQUIRE_EXT(ctx, RVM); - return gen_arith(ctx, a, EXT_NONE, gen_mulhu); + /* gen_mulh_w works for either sign as input. */ + return gen_arith_per_ol(ctx, a, EXT_ZERO, gen_mulhu, gen_mulh_w); } static void gen_div(TCGv ret, TCGv source1, TCGv source2) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index afd59ef690..cb515e2a3c 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -403,6 +403,22 @@ static bool gen_arith(DisasContext *ctx, arg_r *a, DisasExtend ext, return true; } +static bool gen_arith_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext, + void (*f_tl)(TCGv, TCGv, TCGv), + void (*f_32)(TCGv, TCGv, TCGv)) +{ + int olen = get_olen(ctx); + + if (olen != TARGET_LONG_BITS) { + if (olen == 32) { + f_tl = f_32; + } else { + g_assert_not_reached(); + } + } + return gen_arith(ctx, a, ext, f_tl); +} + static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext, void (*func)(TCGv, TCGv, target_long)) { From 673be37163cb44d2e1699503ccd065e9d13d4db7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:17:05 -0700 Subject: [PATCH 18/33] target/riscv: Adjust trans_rev8_32 for riscv64 When target_long is 64-bit, we still want a 32-bit bswap for rev8. Since this opcode is specific to RV32, we need not conditionalize. Acked-by: Alistair Francis Reviewed-by: LIU Zhiwei Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-12-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 9ef8ab94ad..d6f9e9fc83 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -232,11 +232,16 @@ static bool trans_rol(DisasContext *ctx, arg_rol *a) return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotl_tl); } +static void gen_rev8_32(TCGv ret, TCGv src1) +{ + tcg_gen_bswap32_tl(ret, src1, TCG_BSWAP_OS); +} + static bool trans_rev8_32(DisasContext *ctx, arg_rev8_32 *a) { REQUIRE_32BIT(ctx); REQUIRE_ZBB(ctx); - return gen_unary(ctx, a, EXT_NONE, tcg_gen_bswap_tl); + return gen_unary(ctx, a, EXT_NONE, gen_rev8_32); } static bool trans_rev8_64(DisasContext *ctx, arg_rev8_64 *a) From fdab665f6e9d0919bbbab88b16ae2c4be1bf61c6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:17:06 -0700 Subject: [PATCH 19/33] target/riscv: Use gen_unary_per_ol for RVB The count zeros instructions require a separate implementation for RV32 when TARGET_LONG_BITS == 64. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-13-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 33 ++++++++++++------------- target/riscv/translate.c | 16 ++++++++++++ 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index d6f9e9fc83..4eb41756fa 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -47,10 +47,18 @@ static void gen_clz(TCGv ret, TCGv arg1) tcg_gen_clzi_tl(ret, arg1, TARGET_LONG_BITS); } +static void gen_clzw(TCGv ret, TCGv arg1) +{ + TCGv t = tcg_temp_new(); + tcg_gen_shli_tl(t, arg1, 32); + tcg_gen_clzi_tl(ret, t, 32); + tcg_temp_free(t); +} + static bool trans_clz(DisasContext *ctx, arg_clz *a) { REQUIRE_ZBB(ctx); - return gen_unary(ctx, a, EXT_ZERO, gen_clz); + return gen_unary_per_ol(ctx, a, EXT_NONE, gen_clz, gen_clzw); } static void gen_ctz(TCGv ret, TCGv arg1) @@ -58,10 +66,15 @@ static void gen_ctz(TCGv ret, TCGv arg1) tcg_gen_ctzi_tl(ret, arg1, TARGET_LONG_BITS); } +static void gen_ctzw(TCGv ret, TCGv arg1) +{ + tcg_gen_ctzi_tl(ret, arg1, 32); +} + static bool trans_ctz(DisasContext *ctx, arg_ctz *a) { REQUIRE_ZBB(ctx); - return gen_unary(ctx, a, EXT_ZERO, gen_ctz); + return gen_unary_per_ol(ctx, a, EXT_ZERO, gen_ctz, gen_ctzw); } static bool trans_cpop(DisasContext *ctx, arg_cpop *a) @@ -317,14 +330,6 @@ static bool trans_zext_h_64(DisasContext *ctx, arg_zext_h_64 *a) return gen_unary(ctx, a, EXT_NONE, tcg_gen_ext16u_tl); } -static void gen_clzw(TCGv ret, TCGv arg1) -{ - TCGv t = tcg_temp_new(); - tcg_gen_shli_tl(t, arg1, 32); - tcg_gen_clzi_tl(ret, t, 32); - tcg_temp_free(t); -} - static bool trans_clzw(DisasContext *ctx, arg_clzw *a) { REQUIRE_64BIT(ctx); @@ -332,17 +337,11 @@ static bool trans_clzw(DisasContext *ctx, arg_clzw *a) return gen_unary(ctx, a, EXT_NONE, gen_clzw); } -static void gen_ctzw(TCGv ret, TCGv arg1) -{ - tcg_gen_ori_tl(ret, arg1, (target_ulong)MAKE_64BIT_MASK(32, 32)); - tcg_gen_ctzi_tl(ret, ret, 64); -} - static bool trans_ctzw(DisasContext *ctx, arg_ctzw *a) { REQUIRE_64BIT(ctx); REQUIRE_ZBB(ctx); - return gen_unary(ctx, a, EXT_NONE, gen_ctzw); + return gen_unary(ctx, a, EXT_ZERO, gen_ctzw); } static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index cb515e2a3c..f3a5870ad0 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -486,6 +486,22 @@ static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext, return true; } +static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 *a, DisasExtend ext, + void (*f_tl)(TCGv, TCGv), + void (*f_32)(TCGv, TCGv)) +{ + int olen = get_olen(ctx); + + if (olen != TARGET_LONG_BITS) { + if (olen == 32) { + f_tl = f_32; + } else { + g_assert_not_reached(); + } + } + return gen_unary(ctx, a, ext, f_tl); +} + static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) { DisasContext *ctx = container_of(dcbase, DisasContext, base); From a0245d91dd1ca33ecde8c430ac6986dbd90a84db Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:17:07 -0700 Subject: [PATCH 20/33] target/riscv: Use gen_shift*_per_ol for RVB, RVI Most shift instructions require a separate implementation for RV32 when TARGET_LONG_BITS == 64. Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-14-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvb.c.inc | 92 ++++++++++++++----------- target/riscv/insn_trans/trans_rvi.c.inc | 26 +++---- target/riscv/translate.c | 31 +++++++++ 3 files changed, 97 insertions(+), 52 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index 4eb41756fa..c8d31907c5 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -227,22 +227,70 @@ static bool trans_bexti(DisasContext *ctx, arg_bexti *a) return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_bext); } +static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + /* truncate to 32-bits */ + tcg_gen_trunc_tl_i32(t1, arg1); + tcg_gen_trunc_tl_i32(t2, arg2); + + tcg_gen_rotr_i32(t1, t1, t2); + + /* sign-extend 64-bits */ + tcg_gen_ext_i32_tl(ret, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); +} + static bool trans_ror(DisasContext *ctx, arg_ror *a) { REQUIRE_ZBB(ctx); - return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotr_tl); + return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotr_tl, gen_rorw); +} + +static void gen_roriw(TCGv ret, TCGv arg1, target_long shamt) +{ + TCGv_i32 t1 = tcg_temp_new_i32(); + + tcg_gen_trunc_tl_i32(t1, arg1); + tcg_gen_rotri_i32(t1, t1, shamt); + tcg_gen_ext_i32_tl(ret, t1); + + tcg_temp_free_i32(t1); } static bool trans_rori(DisasContext *ctx, arg_rori *a) { REQUIRE_ZBB(ctx); - return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_rotri_tl); + return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE, + tcg_gen_rotri_tl, gen_roriw); +} + +static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) +{ + TCGv_i32 t1 = tcg_temp_new_i32(); + TCGv_i32 t2 = tcg_temp_new_i32(); + + /* truncate to 32-bits */ + tcg_gen_trunc_tl_i32(t1, arg1); + tcg_gen_trunc_tl_i32(t2, arg2); + + tcg_gen_rotl_i32(t1, t1, t2); + + /* sign-extend 64-bits */ + tcg_gen_ext_i32_tl(ret, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t2); } static bool trans_rol(DisasContext *ctx, arg_rol *a) { REQUIRE_ZBB(ctx); - return gen_shift(ctx, a, EXT_NONE, tcg_gen_rotl_tl); + return gen_shift_per_ol(ctx, a, EXT_NONE, tcg_gen_rotl_tl, gen_rolw); } static void gen_rev8_32(TCGv ret, TCGv src1) @@ -352,24 +400,6 @@ static bool trans_cpopw(DisasContext *ctx, arg_cpopw *a) return gen_unary(ctx, a, EXT_ZERO, tcg_gen_ctpop_tl); } -static void gen_rorw(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_temp_new_i32(); - - /* truncate to 32-bits */ - tcg_gen_trunc_tl_i32(t1, arg1); - tcg_gen_trunc_tl_i32(t2, arg2); - - tcg_gen_rotr_i32(t1, t1, t2); - - /* sign-extend 64-bits */ - tcg_gen_ext_i32_tl(ret, t1); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); -} - static bool trans_rorw(DisasContext *ctx, arg_rorw *a) { REQUIRE_64BIT(ctx); @@ -383,25 +413,7 @@ static bool trans_roriw(DisasContext *ctx, arg_roriw *a) REQUIRE_64BIT(ctx); REQUIRE_ZBB(ctx); ctx->ol = MXL_RV32; - return gen_shift_imm_tl(ctx, a, EXT_NONE, gen_rorw); -} - -static void gen_rolw(TCGv ret, TCGv arg1, TCGv arg2) -{ - TCGv_i32 t1 = tcg_temp_new_i32(); - TCGv_i32 t2 = tcg_temp_new_i32(); - - /* truncate to 32-bits */ - tcg_gen_trunc_tl_i32(t1, arg1); - tcg_gen_trunc_tl_i32(t2, arg2); - - tcg_gen_rotl_i32(t1, t1, t2); - - /* sign-extend 64-bits */ - tcg_gen_ext_i32_tl(ret, t1); - - tcg_temp_free_i32(t1); - tcg_temp_free_i32(t2); + return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_roriw); } static bool trans_rolw(DisasContext *ctx, arg_rolw *a) diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 9cf0383cfb..91dc438a3a 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -268,14 +268,26 @@ static bool trans_slli(DisasContext *ctx, arg_slli *a) return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl); } +static void gen_srliw(TCGv dst, TCGv src, target_long shamt) +{ + tcg_gen_extract_tl(dst, src, shamt, 32 - shamt); +} + static bool trans_srli(DisasContext *ctx, arg_srli *a) { - return gen_shift_imm_fn(ctx, a, EXT_ZERO, tcg_gen_shri_tl); + return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE, + tcg_gen_shri_tl, gen_srliw); +} + +static void gen_sraiw(TCGv dst, TCGv src, target_long shamt) +{ + tcg_gen_sextract_tl(dst, src, shamt, 32 - shamt); } static bool trans_srai(DisasContext *ctx, arg_srai *a) { - return gen_shift_imm_fn(ctx, a, EXT_SIGN, tcg_gen_sari_tl); + return gen_shift_imm_fn_per_ol(ctx, a, EXT_NONE, + tcg_gen_sari_tl, gen_sraiw); } static bool trans_add(DisasContext *ctx, arg_add *a) @@ -342,11 +354,6 @@ static bool trans_slliw(DisasContext *ctx, arg_slliw *a) return gen_shift_imm_fn(ctx, a, EXT_NONE, tcg_gen_shli_tl); } -static void gen_srliw(TCGv dst, TCGv src, target_long shamt) -{ - tcg_gen_extract_tl(dst, src, shamt, 32 - shamt); -} - static bool trans_srliw(DisasContext *ctx, arg_srliw *a) { REQUIRE_64BIT(ctx); @@ -354,11 +361,6 @@ static bool trans_srliw(DisasContext *ctx, arg_srliw *a) return gen_shift_imm_fn(ctx, a, EXT_NONE, gen_srliw); } -static void gen_sraiw(TCGv dst, TCGv src, target_long shamt) -{ - tcg_gen_sextract_tl(dst, src, shamt, 32 - shamt); -} - static bool trans_sraiw(DisasContext *ctx, arg_sraiw *a) { REQUIRE_64BIT(ctx); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index f3a5870ad0..bed1c2174e 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -438,6 +438,22 @@ static bool gen_shift_imm_fn(DisasContext *ctx, arg_shift *a, DisasExtend ext, return true; } +static bool gen_shift_imm_fn_per_ol(DisasContext *ctx, arg_shift *a, + DisasExtend ext, + void (*f_tl)(TCGv, TCGv, target_long), + void (*f_32)(TCGv, TCGv, target_long)) +{ + int olen = get_olen(ctx); + if (olen != TARGET_LONG_BITS) { + if (olen == 32) { + f_tl = f_32; + } else { + g_assert_not_reached(); + } + } + return gen_shift_imm_fn(ctx, a, ext, f_tl); +} + static bool gen_shift_imm_tl(DisasContext *ctx, arg_shift *a, DisasExtend ext, void (*func)(TCGv, TCGv, TCGv)) { @@ -474,6 +490,21 @@ static bool gen_shift(DisasContext *ctx, arg_r *a, DisasExtend ext, return true; } +static bool gen_shift_per_ol(DisasContext *ctx, arg_r *a, DisasExtend ext, + void (*f_tl)(TCGv, TCGv, TCGv), + void (*f_32)(TCGv, TCGv, TCGv)) +{ + int olen = get_olen(ctx); + if (olen != TARGET_LONG_BITS) { + if (olen == 32) { + f_tl = f_32; + } else { + g_assert_not_reached(); + } + } + return gen_shift(ctx, a, ext, f_tl); +} + static bool gen_unary(DisasContext *ctx, arg_r2 *a, DisasExtend ext, void (*func)(TCGv, TCGv)) { From 665b90d8a4aa7d90bbeee9ff279e37edcd573635 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:17:08 -0700 Subject: [PATCH 21/33] target/riscv: Use riscv_csrrw_debug for cpu_dump Use the official debug read interface to the csrs, rather than referencing the env slots directly. Put the list of csrs to dump into a table. Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-15-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 89 +++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 44 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index dd9eccd68e..788fa0b11c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -242,51 +242,52 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) #endif qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc ", env->pc); #ifndef CONFIG_USER_ONLY - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", (target_ulong)env->mstatus); - if (riscv_cpu_mxl(env) == MXL_RV32) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ", - (target_ulong)(env->mstatus >> 32)); + { + static const int dump_csrs[] = { + CSR_MHARTID, + CSR_MSTATUS, + CSR_MSTATUSH, + CSR_HSTATUS, + CSR_VSSTATUS, + CSR_MIP, + CSR_MIE, + CSR_MIDELEG, + CSR_HIDELEG, + CSR_MEDELEG, + CSR_HEDELEG, + CSR_MTVEC, + CSR_STVEC, + CSR_VSTVEC, + CSR_MEPC, + CSR_SEPC, + CSR_VSEPC, + CSR_MCAUSE, + CSR_SCAUSE, + CSR_VSCAUSE, + CSR_MTVAL, + CSR_STVAL, + CSR_HTVAL, + CSR_MTVAL2, + CSR_MSCRATCH, + CSR_SSCRATCH, + CSR_SATP, + }; + + for (int i = 0; i < ARRAY_SIZE(dump_csrs); ++i) { + int csrno = dump_csrs[i]; + target_ulong val = 0; + RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0); + + /* + * Rely on the smode, hmode, etc, predicates within csr.c + * to do the filtering of the registers that are present. + */ + if (res == RISCV_EXCP_NONE) { + qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n", + csr_ops[csrno].name, val); + } + } } - if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus", - (target_ulong)env->vsstatus); - } - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", env->mip); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg); - if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hideleg ", env->hideleg); - } - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg); - if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hedeleg ", env->hedeleg); - } - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec ", env->mtvec); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stvec ", env->stvec); - if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vstvec ", env->vstvec); - } - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc ", env->mepc); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sepc ", env->sepc); - if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsepc ", env->vsepc); - } - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause ", env->mcause); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "scause ", env->scause); - if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vscause ", env->vscause); - } - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval ", env->mtval); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval ", env->stval); - if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval ", env->htval); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2 ", env->mtval2); - } - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mscratch", env->mscratch); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sscratch", env->sscratch); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "satp ", env->satp); #endif for (i = 0; i < 32; i++) { From b550f89457ef5022231f8255ae1a6ba496c492b1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 19 Oct 2021 20:17:09 -0700 Subject: [PATCH 22/33] target/riscv: Compute mstatus.sd on demand The position of this read-only field is dependent on the current xlen. Rather than having to compute that difference in many places, compute it only on read. Reviewed-by: Alistair Francis Signed-off-by: Richard Henderson Message-id: 20211020031709.359469-16-richard.henderson@linaro.org Signed-off-by: Alistair Francis --- target/riscv/cpu_helper.c | 3 +-- target/riscv/csr.c | 37 ++++++++++++++++++++++--------------- target/riscv/translate.c | 5 ++--- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 429afd1f48..0d1132f39d 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -185,10 +185,9 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env) void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env) { - uint64_t sd = riscv_cpu_mxl(env) == MXL_RV32 ? MSTATUS32_SD : MSTATUS64_SD; uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS | MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE | - MSTATUS64_UXL | sd; + MSTATUS64_UXL; bool current_virt = riscv_cpu_virt_enabled(env); g_assert(riscv_has_ext(env, RVH)); diff --git a/target/riscv/csr.c b/target/riscv/csr.c index c4a479ddd2..69e4d65fcd 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -477,10 +477,28 @@ static RISCVException read_mhartid(CPURISCVState *env, int csrno, } /* Machine Trap Setup */ + +/* We do not store SD explicitly, only compute it on demand. */ +static uint64_t add_status_sd(RISCVMXL xl, uint64_t status) +{ + if ((status & MSTATUS_FS) == MSTATUS_FS || + (status & MSTATUS_XS) == MSTATUS_XS) { + switch (xl) { + case MXL_RV32: + return status | MSTATUS32_SD; + case MXL_RV64: + return status | MSTATUS64_SD; + default: + g_assert_not_reached(); + } + } + return status; +} + static RISCVException read_mstatus(CPURISCVState *env, int csrno, target_ulong *val) { - *val = env->mstatus; + *val = add_status_sd(riscv_cpu_mxl(env), env->mstatus); return RISCV_EXCP_NONE; } @@ -498,7 +516,6 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, { uint64_t mstatus = env->mstatus; uint64_t mask = 0; - int dirty; /* flush tlb on mstatus fields that affect VM */ if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV | @@ -520,12 +537,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, mstatus = (mstatus & ~mask) | (val & mask); - dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) | - ((mstatus & MSTATUS_XS) == MSTATUS_XS); - if (riscv_cpu_mxl(env) == MXL_RV32) { - mstatus = set_field(mstatus, MSTATUS32_SD, dirty); - } else { - mstatus = set_field(mstatus, MSTATUS64_SD, dirty); + if (riscv_cpu_mxl(env) == MXL_RV64) { /* SXL and UXL fields are for now read only */ mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64); mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64); @@ -798,13 +810,8 @@ static RISCVException read_sstatus(CPURISCVState *env, int csrno, { target_ulong mask = (sstatus_v1_10_mask); - if (riscv_cpu_mxl(env) == MXL_RV32) { - mask |= SSTATUS32_SD; - } else { - mask |= SSTATUS64_SD; - } - - *val = env->mstatus & mask; + /* TODO: Use SXL not MXL. */ + *val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask); return RISCV_EXCP_NONE; } diff --git a/target/riscv/translate.c b/target/riscv/translate.c index bed1c2174e..d38f87d718 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -280,7 +280,6 @@ static void gen_jal(DisasContext *ctx, int rd, target_ulong imm) static void mark_fs_dirty(DisasContext *ctx) { TCGv tmp; - target_ulong sd = get_xl(ctx) == MXL_RV32 ? MSTATUS32_SD : MSTATUS64_SD; if (ctx->mstatus_fs != MSTATUS_FS) { /* Remember the state change for the rest of the TB. */ @@ -288,7 +287,7 @@ static void mark_fs_dirty(DisasContext *ctx) tmp = tcg_temp_new(); tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus)); - tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd); + tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS); tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus)); tcg_temp_free(tmp); } @@ -299,7 +298,7 @@ static void mark_fs_dirty(DisasContext *ctx) tmp = tcg_temp_new(); tcg_gen_ld_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs)); - tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS | sd); + tcg_gen_ori_tl(tmp, tmp, MSTATUS_FS); tcg_gen_st_tl(tmp, cpu_env, offsetof(CPURISCVState, mstatus_hs)); tcg_temp_free(tmp); } From ef6310064820183cce7c5969cae293e680c57679 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 18 Oct 2021 12:38:39 +1000 Subject: [PATCH 23/33] hw/riscv: opentitan: Update to the latest build Update the OpenTitan machine model to match the latest OpenTitan FPGA design. Signed-off-by: Alistair Francis Reviewed-by: Bin Meng Message-id: 18b1b681b0f8dd2461e819d1217bf0b530812680.1634524691.git.alistair.francis@wdc.com --- hw/riscv/opentitan.c | 22 +++++++++++++++++----- include/hw/riscv/opentitan.h | 6 +++--- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 9803ae6d70..601f8deebe 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -46,19 +46,19 @@ static const MemMapEntry ibex_memmap[] = { [IBEX_DEV_PINMUX] = { 0x40460000, 0x1000 }, [IBEX_DEV_PADCTRL] = { 0x40470000, 0x1000 }, [IBEX_DEV_FLASH_CTRL] = { 0x41000000, 0x1000 }, - [IBEX_DEV_PLIC] = { 0x41010000, 0x1000 }, [IBEX_DEV_AES] = { 0x41100000, 0x1000 }, [IBEX_DEV_HMAC] = { 0x41110000, 0x1000 }, [IBEX_DEV_KMAC] = { 0x41120000, 0x1000 }, - [IBEX_DEV_KEYMGR] = { 0x41130000, 0x1000 }, + [IBEX_DEV_OTBN] = { 0x41130000, 0x10000 }, + [IBEX_DEV_KEYMGR] = { 0x41140000, 0x1000 }, [IBEX_DEV_CSRNG] = { 0x41150000, 0x1000 }, [IBEX_DEV_ENTROPY] = { 0x41160000, 0x1000 }, [IBEX_DEV_EDNO] = { 0x41170000, 0x1000 }, [IBEX_DEV_EDN1] = { 0x41180000, 0x1000 }, [IBEX_DEV_ALERT_HANDLER] = { 0x411b0000, 0x1000 }, [IBEX_DEV_NMI_GEN] = { 0x411c0000, 0x1000 }, - [IBEX_DEV_OTBN] = { 0x411d0000, 0x10000 }, [IBEX_DEV_PERI] = { 0x411f0000, 0x10000 }, + [IBEX_DEV_PLIC] = { 0x48000000, 0x4005000 }, [IBEX_DEV_FLASH_VIRTUAL] = { 0x80000000, 0x80000 }, }; @@ -105,7 +105,7 @@ static void lowrisc_ibex_soc_init(Object *obj) object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY); - object_initialize_child(obj, "plic", &s->plic, TYPE_IBEX_PLIC); + object_initialize_child(obj, "plic", &s->plic, TYPE_SIFIVE_PLIC); object_initialize_child(obj, "uart", &s->uart, TYPE_IBEX_UART); @@ -145,6 +145,18 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) &s->flash_alias); /* PLIC */ + qdev_prop_set_string(DEVICE(&s->plic), "hart-config", "M"); + qdev_prop_set_uint32(DEVICE(&s->plic), "hartid-base", 0); + qdev_prop_set_uint32(DEVICE(&s->plic), "num-sources", 180); + qdev_prop_set_uint32(DEVICE(&s->plic), "num-priorities", 3); + qdev_prop_set_uint32(DEVICE(&s->plic), "priority-base", 0x00); + qdev_prop_set_uint32(DEVICE(&s->plic), "pending-base", 0x1000); + qdev_prop_set_uint32(DEVICE(&s->plic), "enable-base", 0x2000); + qdev_prop_set_uint32(DEVICE(&s->plic), "enable-stride", 0x18); + qdev_prop_set_uint32(DEVICE(&s->plic), "context-base", 0x200004); + qdev_prop_set_uint32(DEVICE(&s->plic), "context-stride", 4); + qdev_prop_set_uint32(DEVICE(&s->plic), "aperture-size", memmap[IBEX_DEV_PLIC].size); + if (!sysbus_realize(SYS_BUS_DEVICE(&s->plic), errp)) { return; } @@ -153,7 +165,7 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) for (i = 0; i < ms->smp.cpus; i++) { CPUState *cpu = qemu_get_cpu(i); - qdev_connect_gpio_out(DEVICE(&s->plic), i, + qdev_connect_gpio_out(DEVICE(&s->plic), ms->smp.cpus + i, qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT)); } diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h index 9f93bebdac..eac35ef590 100644 --- a/include/hw/riscv/opentitan.h +++ b/include/hw/riscv/opentitan.h @@ -20,7 +20,7 @@ #define HW_OPENTITAN_H #include "hw/riscv/riscv_hart.h" -#include "hw/intc/ibex_plic.h" +#include "hw/intc/sifive_plic.h" #include "hw/char/ibex_uart.h" #include "hw/timer/ibex_timer.h" #include "qom/object.h" @@ -34,7 +34,7 @@ struct LowRISCIbexSoCState { /*< public >*/ RISCVHartArrayState cpus; - IbexPlicState plic; + SiFivePLICState plic; IbexUartState uart; IbexTimerState timer; @@ -87,7 +87,7 @@ enum { }; enum { - IBEX_TIMER_TIMEREXPIRED0_0 = 125, + IBEX_TIMER_TIMEREXPIRED0_0 = 126, IBEX_UART0_RX_PARITY_ERR_IRQ = 8, IBEX_UART0_RX_TIMEOUT_IRQ = 7, IBEX_UART0_RX_BREAK_ERR_IRQ = 6, From 434e7e0217d73c20f60bd52437d0a0ba8a3c6247 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 18 Oct 2021 12:38:55 +1000 Subject: [PATCH 24/33] hw/intc: Remove the Ibex PLIC The Ibex PLIC is now spec compliant. Let's remove the Ibex PLIC and instead use the SiFive PLIC. Signed-off-by: Alistair Francis Reviewed-by: Bin Meng Message-id: 5557935c2660c5e6281b6d21e6514e019593662e.1634524691.git.alistair.francis@wdc.com --- hw/intc/ibex_plic.c | 307 -------------------------------------------- hw/intc/meson.build | 1 - 2 files changed, 308 deletions(-) delete mode 100644 hw/intc/ibex_plic.c diff --git a/hw/intc/ibex_plic.c b/hw/intc/ibex_plic.c deleted file mode 100644 index ff430356f8..0000000000 --- a/hw/intc/ibex_plic.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * QEMU RISC-V lowRISC Ibex PLIC - * - * Copyright (c) 2020 Western Digital - * - * Documentation avaliable: https://docs.opentitan.org/hw/ip/rv_plic/doc/ - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2 or later, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see . - */ - -#include "qemu/osdep.h" -#include "qemu/log.h" -#include "hw/qdev-properties.h" -#include "hw/core/cpu.h" -#include "hw/boards.h" -#include "hw/pci/msi.h" -#include "target/riscv/cpu_bits.h" -#include "target/riscv/cpu.h" -#include "hw/intc/ibex_plic.h" -#include "hw/irq.h" - -static bool addr_between(uint32_t addr, uint32_t base, uint32_t num) -{ - uint32_t end = base + (num * 0x04); - - if (addr >= base && addr < end) { - return true; - } - - return false; -} - -static void ibex_plic_irqs_set_pending(IbexPlicState *s, int irq, bool level) -{ - int pending_num = irq / 32; - - if (!level) { - /* - * If the level is low make sure we clear the hidden_pending. - */ - s->hidden_pending[pending_num] &= ~(1 << (irq % 32)); - } - - if (s->claimed[pending_num] & 1 << (irq % 32)) { - /* - * The interrupt has been claimed, but not completed. - * The pending bit can't be set. - * Save the pending level for after the interrupt is completed. - */ - s->hidden_pending[pending_num] |= level << (irq % 32); - } else { - s->pending[pending_num] |= level << (irq % 32); - } -} - -static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context) -{ - int i; - uint32_t max_irq = 0; - uint32_t max_prio = s->threshold; - - for (i = 0; i < s->pending_num; i++) { - uint32_t irq_num = ctz64(s->pending[i]) + (i * 32); - - if (!(s->pending[i] & s->enable[i])) { - /* No pending and enabled IRQ */ - continue; - } - - if (s->priority[irq_num] > max_prio) { - max_irq = irq_num; - max_prio = s->priority[irq_num]; - } - } - - if (max_irq) { - s->claim = max_irq; - return true; - } - - return false; -} - -static void ibex_plic_update(IbexPlicState *s) -{ - int i; - - for (i = 0; i < s->num_cpus; i++) { - qemu_set_irq(s->external_irqs[i], ibex_plic_irqs_pending(s, 0)); - } -} - -static void ibex_plic_reset(DeviceState *dev) -{ - IbexPlicState *s = IBEX_PLIC(dev); - - s->threshold = 0x00000000; - s->claim = 0x00000000; -} - -static uint64_t ibex_plic_read(void *opaque, hwaddr addr, - unsigned int size) -{ - IbexPlicState *s = opaque; - int offset; - uint32_t ret = 0; - - if (addr_between(addr, s->pending_base, s->pending_num)) { - offset = (addr - s->pending_base) / 4; - ret = s->pending[offset]; - } else if (addr_between(addr, s->source_base, s->source_num)) { - qemu_log_mask(LOG_UNIMP, - "%s: Interrupt source mode not supported\n", __func__); - } else if (addr_between(addr, s->priority_base, s->priority_num)) { - offset = (addr - s->priority_base) / 4; - ret = s->priority[offset]; - } else if (addr_between(addr, s->enable_base, s->enable_num)) { - offset = (addr - s->enable_base) / 4; - ret = s->enable[offset]; - } else if (addr_between(addr, s->threshold_base, 1)) { - ret = s->threshold; - } else if (addr_between(addr, s->claim_base, 1)) { - int pending_num = s->claim / 32; - s->pending[pending_num] &= ~(1 << (s->claim % 32)); - - /* Set the interrupt as claimed, but not completed */ - s->claimed[pending_num] |= 1 << (s->claim % 32); - - /* Return the current claimed interrupt */ - ret = s->claim; - - /* Clear the claimed interrupt */ - s->claim = 0x00000000; - - /* Update the interrupt status after the claim */ - ibex_plic_update(s); - } - - return ret; -} - -static void ibex_plic_write(void *opaque, hwaddr addr, - uint64_t value, unsigned int size) -{ - IbexPlicState *s = opaque; - - if (addr_between(addr, s->pending_base, s->pending_num)) { - qemu_log_mask(LOG_GUEST_ERROR, - "%s: Pending registers are read only\n", __func__); - } else if (addr_between(addr, s->source_base, s->source_num)) { - qemu_log_mask(LOG_UNIMP, - "%s: Interrupt source mode not supported\n", __func__); - } else if (addr_between(addr, s->priority_base, s->priority_num)) { - uint32_t irq = ((addr - s->priority_base) >> 2) + 1; - s->priority[irq] = value & 7; - ibex_plic_update(s); - } else if (addr_between(addr, s->enable_base, s->enable_num)) { - uint32_t enable_reg = (addr - s->enable_base) / 4; - - s->enable[enable_reg] = value; - } else if (addr_between(addr, s->threshold_base, 1)) { - s->threshold = value & 3; - } else if (addr_between(addr, s->claim_base, 1)) { - if (s->claim == value) { - /* Interrupt was completed */ - s->claim = 0; - } - if (s->claimed[value / 32] & 1 << (value % 32)) { - int pending_num = value / 32; - - /* This value was already claimed, clear it. */ - s->claimed[pending_num] &= ~(1 << (value % 32)); - - if (s->hidden_pending[pending_num] & (1 << (value % 32))) { - /* - * If the bit in hidden_pending is set then that means we - * received an interrupt between claiming and completing - * the interrupt that hasn't since been de-asserted. - * On hardware this would trigger an interrupt, so let's - * trigger one here as well. - */ - s->pending[pending_num] |= 1 << (value % 32); - } - } - } - - ibex_plic_update(s); -} - -static const MemoryRegionOps ibex_plic_ops = { - .read = ibex_plic_read, - .write = ibex_plic_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4 - } -}; - -static void ibex_plic_irq_request(void *opaque, int irq, int level) -{ - IbexPlicState *s = opaque; - - ibex_plic_irqs_set_pending(s, irq, level > 0); - ibex_plic_update(s); -} - -static Property ibex_plic_properties[] = { - DEFINE_PROP_UINT32("num-cpus", IbexPlicState, num_cpus, 1), - DEFINE_PROP_UINT32("num-sources", IbexPlicState, num_sources, 176), - - DEFINE_PROP_UINT32("pending-base", IbexPlicState, pending_base, 0), - DEFINE_PROP_UINT32("pending-num", IbexPlicState, pending_num, 6), - - DEFINE_PROP_UINT32("source-base", IbexPlicState, source_base, 0x18), - DEFINE_PROP_UINT32("source-num", IbexPlicState, source_num, 6), - - DEFINE_PROP_UINT32("priority-base", IbexPlicState, priority_base, 0x30), - DEFINE_PROP_UINT32("priority-num", IbexPlicState, priority_num, 177), - - DEFINE_PROP_UINT32("enable-base", IbexPlicState, enable_base, 0x300), - DEFINE_PROP_UINT32("enable-num", IbexPlicState, enable_num, 6), - - DEFINE_PROP_UINT32("threshold-base", IbexPlicState, threshold_base, 0x318), - - DEFINE_PROP_UINT32("claim-base", IbexPlicState, claim_base, 0x31c), - DEFINE_PROP_END_OF_LIST(), -}; - -static void ibex_plic_init(Object *obj) -{ - IbexPlicState *s = IBEX_PLIC(obj); - - memory_region_init_io(&s->mmio, obj, &ibex_plic_ops, s, - TYPE_IBEX_PLIC, 0x400); - sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); -} - -static void ibex_plic_realize(DeviceState *dev, Error **errp) -{ - IbexPlicState *s = IBEX_PLIC(dev); - int i; - - s->pending = g_new0(uint32_t, s->pending_num); - s->hidden_pending = g_new0(uint32_t, s->pending_num); - s->claimed = g_new0(uint32_t, s->pending_num); - s->source = g_new0(uint32_t, s->source_num); - s->priority = g_new0(uint32_t, s->priority_num); - s->enable = g_new0(uint32_t, s->enable_num); - - qdev_init_gpio_in(dev, ibex_plic_irq_request, s->num_sources); - - s->external_irqs = g_malloc(sizeof(qemu_irq) * s->num_cpus); - qdev_init_gpio_out(dev, s->external_irqs, s->num_cpus); - - /* - * We can't allow the supervisor to control SEIP as this would allow the - * supervisor to clear a pending external interrupt which will result in - * a lost interrupt in the case a PLIC is attached. The SEIP bit must be - * hardware controlled when a PLIC is attached. - */ - MachineState *ms = MACHINE(qdev_get_machine()); - unsigned int smp_cpus = ms->smp.cpus; - for (i = 0; i < smp_cpus; i++) { - RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(i)); - if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) { - error_report("SEIP already claimed"); - exit(1); - } - } - - msi_nonbroken = true; -} - -static void ibex_plic_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->reset = ibex_plic_reset; - device_class_set_props(dc, ibex_plic_properties); - dc->realize = ibex_plic_realize; -} - -static const TypeInfo ibex_plic_info = { - .name = TYPE_IBEX_PLIC, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(IbexPlicState), - .instance_init = ibex_plic_init, - .class_init = ibex_plic_class_init, -}; - -static void ibex_plic_register_types(void) -{ - type_register_static(&ibex_plic_info); -} - -type_init(ibex_plic_register_types) diff --git a/hw/intc/meson.build b/hw/intc/meson.build index a1d00aa48d..c89d2ca180 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -32,7 +32,6 @@ specific_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c')) specific_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_vic.c')) specific_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_gic.c', 'exynos4210_combiner.c')) specific_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_irqmp.c')) -specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_plic.c')) specific_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic.c')) specific_ss.add(when: 'CONFIG_LOONGSON_LIOINTC', if_true: files('loongson_liointc.c')) specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gic.c')) From d8c6590f183cd93956b7a458d212778a143b89c8 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 18 Oct 2021 12:39:11 +1000 Subject: [PATCH 25/33] hw/intc: sifive_plic: Move the properties Signed-off-by: Alistair Francis Reviewed-by: Bin Meng Message-id: 3c125e27c49a4969df82bf8b197535ccd1996939.1634524691.git.alistair.francis@wdc.com --- hw/intc/sifive_plic.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index 9ba36dc0b3..f0e2799efc 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -355,21 +355,6 @@ static const MemoryRegionOps sifive_plic_ops = { } }; -static Property sifive_plic_properties[] = { - DEFINE_PROP_STRING("hart-config", SiFivePLICState, hart_config), - DEFINE_PROP_UINT32("hartid-base", SiFivePLICState, hartid_base, 0), - DEFINE_PROP_UINT32("num-sources", SiFivePLICState, num_sources, 0), - DEFINE_PROP_UINT32("num-priorities", SiFivePLICState, num_priorities, 0), - DEFINE_PROP_UINT32("priority-base", SiFivePLICState, priority_base, 0), - DEFINE_PROP_UINT32("pending-base", SiFivePLICState, pending_base, 0), - DEFINE_PROP_UINT32("enable-base", SiFivePLICState, enable_base, 0), - DEFINE_PROP_UINT32("enable-stride", SiFivePLICState, enable_stride, 0), - DEFINE_PROP_UINT32("context-base", SiFivePLICState, context_base, 0), - DEFINE_PROP_UINT32("context-stride", SiFivePLICState, context_stride, 0), - DEFINE_PROP_UINT32("aperture-size", SiFivePLICState, aperture_size, 0), - DEFINE_PROP_END_OF_LIST(), -}; - /* * parse PLIC hart/mode address offset config * @@ -496,6 +481,21 @@ static const VMStateDescription vmstate_sifive_plic = { } }; +static Property sifive_plic_properties[] = { + DEFINE_PROP_STRING("hart-config", SiFivePLICState, hart_config), + DEFINE_PROP_UINT32("hartid-base", SiFivePLICState, hartid_base, 0), + DEFINE_PROP_UINT32("num-sources", SiFivePLICState, num_sources, 0), + DEFINE_PROP_UINT32("num-priorities", SiFivePLICState, num_priorities, 0), + DEFINE_PROP_UINT32("priority-base", SiFivePLICState, priority_base, 0), + DEFINE_PROP_UINT32("pending-base", SiFivePLICState, pending_base, 0), + DEFINE_PROP_UINT32("enable-base", SiFivePLICState, enable_base, 0), + DEFINE_PROP_UINT32("enable-stride", SiFivePLICState, enable_stride, 0), + DEFINE_PROP_UINT32("context-base", SiFivePLICState, context_base, 0), + DEFINE_PROP_UINT32("context-stride", SiFivePLICState, context_stride, 0), + DEFINE_PROP_UINT32("aperture-size", SiFivePLICState, aperture_size, 0), + DEFINE_PROP_END_OF_LIST(), +}; + static void sifive_plic_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); From d680ff664e1c7e097922f62fef824027b8fb711a Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 18 Oct 2021 12:39:26 +1000 Subject: [PATCH 26/33] hw/intc: sifive_plic: Cleanup the realize function Signed-off-by: Alistair Francis Reviewed-by: Bin Meng Message-id: b94c098cb221e744683349b1ac794c23102ef471.1634524691.git.alistair.francis@wdc.com --- hw/intc/sifive_plic.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index f0e2799efc..d77a5ced23 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -422,35 +422,38 @@ static void sifive_plic_irq_request(void *opaque, int irq, int level) static void sifive_plic_realize(DeviceState *dev, Error **errp) { - SiFivePLICState *plic = SIFIVE_PLIC(dev); + SiFivePLICState *s = SIFIVE_PLIC(dev); int i; - memory_region_init_io(&plic->mmio, OBJECT(dev), &sifive_plic_ops, plic, - TYPE_SIFIVE_PLIC, plic->aperture_size); - parse_hart_config(plic); - plic->bitfield_words = (plic->num_sources + 31) >> 5; - plic->num_enables = plic->bitfield_words * plic->num_addrs; - plic->source_priority = g_new0(uint32_t, plic->num_sources); - plic->target_priority = g_new(uint32_t, plic->num_addrs); - plic->pending = g_new0(uint32_t, plic->bitfield_words); - plic->claimed = g_new0(uint32_t, plic->bitfield_words); - plic->enable = g_new0(uint32_t, plic->num_enables); - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio); - qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources); + memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_plic_ops, s, + TYPE_SIFIVE_PLIC, s->aperture_size); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); - plic->s_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts); - qdev_init_gpio_out(dev, plic->s_external_irqs, plic->num_harts); + parse_hart_config(s); - plic->m_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts); - qdev_init_gpio_out(dev, plic->m_external_irqs, plic->num_harts); + s->bitfield_words = (s->num_sources + 31) >> 5; + s->num_enables = s->bitfield_words * s->num_addrs; + s->source_priority = g_new0(uint32_t, s->num_sources); + s->target_priority = g_new(uint32_t, s->num_addrs); + s->pending = g_new0(uint32_t, s->bitfield_words); + s->claimed = g_new0(uint32_t, s->bitfield_words); + s->enable = g_new0(uint32_t, s->num_enables); + + qdev_init_gpio_in(dev, sifive_plic_irq_request, s->num_sources); + + s->s_external_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts); + qdev_init_gpio_out(dev, s->s_external_irqs, s->num_harts); + + s->m_external_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts); + qdev_init_gpio_out(dev, s->m_external_irqs, s->num_harts); /* We can't allow the supervisor to control SEIP as this would allow the * supervisor to clear a pending external interrupt which will result in * lost a interrupt in the case a PLIC is attached. The SEIP bit must be * hardware controlled when a PLIC is attached. */ - for (i = 0; i < plic->num_harts; i++) { - RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(plic->hartid_base + i)); + for (i = 0; i < s->num_harts; i++) { + RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) { error_report("SEIP already claimed"); exit(1); From 8d3dae162e61e6c71bbd3d9878cd1768ae9dd989 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 18 Oct 2021 12:39:41 +1000 Subject: [PATCH 27/33] hw/intc: sifive_plic: Cleanup the irq_request function Signed-off-by: Alistair Francis Reviewed-by: Bin Meng Message-id: 4200da222a65c89ed1ba35f754dcca7fdd9f08d6.1634524691.git.alistair.francis@wdc.com --- hw/intc/sifive_plic.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index d77a5ced23..877e76877c 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -412,12 +412,10 @@ static void parse_hart_config(SiFivePLICState *plic) static void sifive_plic_irq_request(void *opaque, int irq, int level) { - SiFivePLICState *plic = opaque; - if (RISCV_DEBUG_PLIC) { - qemu_log("sifive_plic_irq_request: irq=%d level=%d\n", irq, level); - } - sifive_plic_set_pending(plic, irq, level > 0); - sifive_plic_update(plic); + SiFivePLICState *s = opaque; + + sifive_plic_set_pending(s, irq, level > 0); + sifive_plic_update(s); } static void sifive_plic_realize(DeviceState *dev, Error **errp) From d4c624f482778cfe91938996a588df2df0e70f20 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 20 Oct 2021 09:41:07 +0800 Subject: [PATCH 28/33] hw/riscv: microchip_pfsoc: Use MachineState::ram and MachineClass::default_ram_id Using memory_region_init_ram(), which can't possibly handle vhost-user, and can't work as expected with '-numa node,memdev' options. Use MachineState::ram instead of manually initializing RAM memory region, as well as by providing MachineClass::default_ram_id to opt in to memdev scheme. Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Reviewed-by: Igor Mammedov Message-id: 20211020014112.7336-2-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/microchip_pfsoc.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index e475b6d511..3fc8545562 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -463,7 +463,7 @@ static void microchip_icicle_kit_machine_init(MachineState *machine) MemoryRegion *mem_low_alias = g_new(MemoryRegion, 1); MemoryRegion *mem_high = g_new(MemoryRegion, 1); MemoryRegion *mem_high_alias = g_new(MemoryRegion, 1); - uint64_t mem_high_size; + uint64_t mem_low_size, mem_high_size; hwaddr firmware_load_addr; const char *firmware_name; bool kernel_as_payload = false; @@ -485,31 +485,34 @@ static void microchip_icicle_kit_machine_init(MachineState *machine) TYPE_MICROCHIP_PFSOC); qdev_realize(DEVICE(&s->soc), NULL, &error_abort); + /* Split RAM into low and high regions using aliases to machine->ram */ + mem_low_size = memmap[MICROCHIP_PFSOC_DRAM_LO].size; + mem_high_size = machine->ram_size - mem_low_size; + memory_region_init_alias(mem_low, NULL, + "microchip.icicle.kit.ram_low", machine->ram, + 0, mem_low_size); + memory_region_init_alias(mem_high, NULL, + "microchip.icicle.kit.ram_high", machine->ram, + mem_low_size, mem_high_size); + /* Register RAM */ - memory_region_init_ram(mem_low, NULL, "microchip.icicle.kit.ram_low", - memmap[MICROCHIP_PFSOC_DRAM_LO].size, - &error_fatal); - memory_region_init_alias(mem_low_alias, NULL, - "microchip.icicle.kit.ram_low.alias", - mem_low, 0, - memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].size); memory_region_add_subregion(system_memory, memmap[MICROCHIP_PFSOC_DRAM_LO].base, mem_low); + memory_region_add_subregion(system_memory, + memmap[MICROCHIP_PFSOC_DRAM_HI].base, + mem_high); + + /* Create aliases for the low and high RAM regions */ + memory_region_init_alias(mem_low_alias, NULL, + "microchip.icicle.kit.ram_low.alias", + mem_low, 0, mem_low_size); memory_region_add_subregion(system_memory, memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].base, mem_low_alias); - - mem_high_size = machine->ram_size - 1 * GiB; - - memory_region_init_ram(mem_high, NULL, "microchip.icicle.kit.ram_high", - mem_high_size, &error_fatal); memory_region_init_alias(mem_high_alias, NULL, "microchip.icicle.kit.ram_high.alias", mem_high, 0, mem_high_size); - memory_region_add_subregion(system_memory, - memmap[MICROCHIP_PFSOC_DRAM_HI].base, - mem_high); memory_region_add_subregion(system_memory, memmap[MICROCHIP_PFSOC_DRAM_HI_ALIAS].base, mem_high_alias); @@ -606,6 +609,7 @@ static void microchip_icicle_kit_machine_class_init(ObjectClass *oc, void *data) MICROCHIP_PFSOC_COMPUTE_CPU_COUNT; mc->min_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT + 1; mc->default_cpus = mc->min_cpus; + mc->default_ram_id = "microchip.icicle.kit.ram"; /* * Map 513 MiB high memory, the mimimum required high memory size, because From 91b1fbdc0cca11ac23ddc61ee3ea0e9706b645cf Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 20 Oct 2021 09:41:08 +0800 Subject: [PATCH 29/33] hw/riscv: opentitan: Use MachineState::ram and MachineClass::default_ram_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using memory_region_init_ram(), which can't possibly handle vhost-user, and can't work as expected with '-numa node,memdev' options. Use MachineState::ram instead of manually initializing RAM memory region, as well as by providing MachineClass::default_ram_id to opt in to memdev scheme. While at it add check for user supplied RAM size and error out if it mismatches board expected value. Signed-off-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Reviewed-by: Igor Mammedov Message-id: 20211020014112.7336-3-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/opentitan.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 601f8deebe..83e1511f28 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -19,6 +19,7 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "hw/riscv/opentitan.h" #include "qapi/error.h" #include "hw/boards.h" @@ -64,20 +65,25 @@ static const MemMapEntry ibex_memmap[] = { static void opentitan_board_init(MachineState *machine) { + MachineClass *mc = MACHINE_GET_CLASS(machine); const MemMapEntry *memmap = ibex_memmap; OpenTitanState *s = g_new0(OpenTitanState, 1); MemoryRegion *sys_mem = get_system_memory(); - MemoryRegion *main_mem = g_new(MemoryRegion, 1); + + if (machine->ram_size != mc->default_ram_size) { + char *sz = size_to_str(mc->default_ram_size); + error_report("Invalid RAM size, should be %s", sz); + g_free(sz); + exit(EXIT_FAILURE); + } /* Initialize SoC */ object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_IBEX_SOC); qdev_realize(DEVICE(&s->soc), NULL, &error_abort); - memory_region_init_ram(main_mem, NULL, "riscv.lowrisc.ibex.ram", - memmap[IBEX_DEV_RAM].size, &error_fatal); memory_region_add_subregion(sys_mem, - memmap[IBEX_DEV_RAM].base, main_mem); + memmap[IBEX_DEV_RAM].base, machine->ram); if (machine->firmware) { riscv_load_firmware(machine->firmware, memmap[IBEX_DEV_RAM].base, NULL); @@ -95,6 +101,8 @@ static void opentitan_machine_init(MachineClass *mc) mc->init = opentitan_board_init; mc->max_cpus = 1; mc->default_cpu_type = TYPE_RISCV_CPU_IBEX; + mc->default_ram_id = "riscv.lowrisc.ibex.ram"; + mc->default_ram_size = ibex_memmap[IBEX_DEV_RAM].size; } DEFINE_MACHINE("opentitan", opentitan_machine_init) From 56917307f4780535d319dedc8973361a5da76f7b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 20 Oct 2021 09:41:09 +0800 Subject: [PATCH 30/33] hw/riscv: shakti_c: Use MachineState::ram and MachineClass::default_ram_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using memory_region_init_ram(), which can't possibly handle vhost-user, and can't work as expected with '-numa node,memdev' options. Use MachineState::ram instead of manually initializing RAM memory region, as well as by providing MachineClass::default_ram_id to opt in to memdev scheme. Signed-off-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Igor Mammedov Reviewed-by: Alistair Francis Message-id: 20211020014112.7336-4-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/shakti_c.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c index d7d1f91fa5..90e2cf609f 100644 --- a/hw/riscv/shakti_c.c +++ b/hw/riscv/shakti_c.c @@ -45,7 +45,6 @@ static void shakti_c_machine_state_init(MachineState *mstate) { ShaktiCMachineState *sms = RISCV_SHAKTI_MACHINE(mstate); MemoryRegion *system_memory = get_system_memory(); - MemoryRegion *main_mem = g_new(MemoryRegion, 1); /* Allow only Shakti C CPU for this platform */ if (strcmp(mstate->cpu_type, TYPE_RISCV_CPU_SHAKTI_C) != 0) { @@ -59,11 +58,9 @@ static void shakti_c_machine_state_init(MachineState *mstate) qdev_realize(DEVICE(&sms->soc), NULL, &error_abort); /* register RAM */ - memory_region_init_ram(main_mem, NULL, "riscv.shakti.c.ram", - mstate->ram_size, &error_fatal); memory_region_add_subregion(system_memory, shakti_c_memmap[SHAKTI_C_RAM].base, - main_mem); + mstate->ram); /* ROM reset vector */ riscv_setup_rom_reset_vec(mstate, &sms->soc.cpus, @@ -88,6 +85,7 @@ static void shakti_c_machine_class_init(ObjectClass *klass, void *data) mc->desc = "RISC-V Board compatible with Shakti SDK"; mc->init = shakti_c_machine_state_init; mc->default_cpu_type = TYPE_RISCV_CPU_SHAKTI_C; + mc->default_ram_id = "riscv.shakti.c.ram"; } static const TypeInfo shakti_c_machine_type_info = { From e2b3ef75445fc2342b00680dad7af3618dc69deb Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 20 Oct 2021 09:41:10 +0800 Subject: [PATCH 31/33] hw/riscv: sifive_e: Use MachineState::ram and MachineClass::default_ram_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using memory_region_init_ram(), which can't possibly handle vhost-user, and can't work as expected with '-numa node,memdev' options. Use MachineState::ram instead of manually initializing RAM memory region, as well as by providing MachineClass::default_ram_id to opt in to memdev scheme. While at it add check for user supplied RAM size and error out if it mismatches board expected value. Signed-off-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Alistair Francis Reviewed-by: Igor Mammedov Message-id: 20211020014112.7336-5-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/sifive_e.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c index 6e95ea5896..9b206407a6 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -29,6 +29,7 @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "qemu/error-report.h" #include "qapi/error.h" #include "hw/boards.h" @@ -71,22 +72,27 @@ static const MemMapEntry sifive_e_memmap[] = { static void sifive_e_machine_init(MachineState *machine) { + MachineClass *mc = MACHINE_GET_CLASS(machine); const MemMapEntry *memmap = sifive_e_memmap; SiFiveEState *s = RISCV_E_MACHINE(machine); MemoryRegion *sys_mem = get_system_memory(); - MemoryRegion *main_mem = g_new(MemoryRegion, 1); int i; + if (machine->ram_size != mc->default_ram_size) { + char *sz = size_to_str(mc->default_ram_size); + error_report("Invalid RAM size, should be %s", sz); + g_free(sz); + exit(EXIT_FAILURE); + } + /* Initialize SoC */ object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_E_SOC); qdev_realize(DEVICE(&s->soc), NULL, &error_abort); /* Data Tightly Integrated Memory */ - memory_region_init_ram(main_mem, NULL, "riscv.sifive.e.ram", - memmap[SIFIVE_E_DEV_DTIM].size, &error_fatal); memory_region_add_subregion(sys_mem, - memmap[SIFIVE_E_DEV_DTIM].base, main_mem); + memmap[SIFIVE_E_DEV_DTIM].base, machine->ram); /* Mask ROM reset vector */ uint32_t reset_vec[4]; @@ -142,6 +148,8 @@ static void sifive_e_machine_class_init(ObjectClass *oc, void *data) mc->init = sifive_e_machine_init; mc->max_cpus = 1; mc->default_cpu_type = SIFIVE_E_CPU; + mc->default_ram_id = "riscv.sifive.e.ram"; + mc->default_ram_size = sifive_e_memmap[SIFIVE_E_DEV_DTIM].size; object_class_property_add_bool(oc, "revb", sifive_e_machine_get_revb, sifive_e_machine_set_revb); From c188a9c4f78e21f7f979ab7ef19c5bf21e9dcf08 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 20 Oct 2021 09:41:11 +0800 Subject: [PATCH 32/33] hw/riscv: sifive_u: Use MachineState::ram and MachineClass::default_ram_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using memory_region_init_ram(), which can't possibly handle vhost-user, and can't work as expected with '-numa node,memdev' options. Use MachineState::ram instead of manually initializing RAM memory region, as well as by providing MachineClass::default_ram_id to opt in to memdev scheme. Signed-off-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Igor Mammedov Reviewed-by: Alistair Francis Message-id: 20211020014112.7336-6-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/sifive_u.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index fc5790b8ce..0217006c27 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -528,7 +528,6 @@ static void sifive_u_machine_init(MachineState *machine) const MemMapEntry *memmap = sifive_u_memmap; SiFiveUState *s = RISCV_U_MACHINE(machine); MemoryRegion *system_memory = get_system_memory(); - MemoryRegion *main_mem = g_new(MemoryRegion, 1); MemoryRegion *flash0 = g_new(MemoryRegion, 1); target_ulong start_addr = memmap[SIFIVE_U_DEV_DRAM].base; target_ulong firmware_end_addr, kernel_start_addr; @@ -549,10 +548,8 @@ static void sifive_u_machine_init(MachineState *machine) qdev_realize(DEVICE(&s->soc), NULL, &error_abort); /* register RAM */ - memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram", - machine->ram_size, &error_fatal); memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_DRAM].base, - main_mem); + machine->ram); /* register QSPI0 Flash */ memory_region_init_ram(flash0, NULL, "riscv.sifive.u.flash0", @@ -748,6 +745,7 @@ static void sifive_u_machine_class_init(ObjectClass *oc, void *data) mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1; mc->default_cpu_type = SIFIVE_U_CPU; mc->default_cpus = mc->min_cpus; + mc->default_ram_id = "riscv.sifive.u.ram"; object_class_property_add_bool(oc, "start-in-flash", sifive_u_machine_get_start_in_flash, From 11ec06f9eaedc801ded34c79861367b76ab2b731 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 20 Oct 2021 09:41:12 +0800 Subject: [PATCH 33/33] hw/riscv: spike: Use MachineState::ram and MachineClass::default_ram_id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using memory_region_init_ram(), which can't possibly handle vhost-user, and can't work as expected with '-numa node,memdev' options. Use MachineState::ram instead of manually initializing RAM memory region, as well as by providing MachineClass::default_ram_id to opt in to memdev scheme. Signed-off-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Igor Mammedov Reviewed-by: Alistair Francis Message-id: 20211020014112.7336-7-bmeng.cn@gmail.com Signed-off-by: Alistair Francis --- hw/riscv/spike.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 79ae355ae2..288d69cd9f 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -180,7 +180,6 @@ static void spike_board_init(MachineState *machine) const MemMapEntry *memmap = spike_memmap; SpikeState *s = SPIKE_MACHINE(machine); MemoryRegion *system_memory = get_system_memory(); - MemoryRegion *main_mem = g_new(MemoryRegion, 1); MemoryRegion *mask_rom = g_new(MemoryRegion, 1); target_ulong firmware_end_addr, kernel_start_addr; uint32_t fdt_load_addr; @@ -239,10 +238,8 @@ static void spike_board_init(MachineState *machine) } /* 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); + machine->ram); /* create device tree */ create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline, @@ -326,6 +323,7 @@ static void spike_machine_class_init(ObjectClass *oc, void *data) mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props; mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id; mc->numa_mem_supported = true; + mc->default_ram_id = "riscv.spike.ram"; } static const TypeInfo spike_machine_typeinfo = {