:p
atchew
Login
From: Alistair Francis <alistair.francis@wdc.com> The following changes since commit 4c127fdbe81d66e7cafed90908d0fd1f6f2a6cd0: Merge remote-tracking branch 'remotes/rth/tags/pull-arm-20211021' into staging (2021-10-21 09:53:27 -0700) are available in the Git repository at: git@github.com:alistair23/qemu.git tags/pull-riscv-to-apply-20211022-2 for you to fetch changes up to 11ec06f9eaedc801ded34c79861367b76ab2b731: hw/riscv: spike: Use MachineState::ram and MachineClass::default_ram_id (2021-10-22 23:35:47 +1000) ---------------------------------------------------------------- Fourth RISC-V PR for QEMU 6.2 - Vector extension bug fixes - Bit manipulation extension bug fix - Support vhost-user and numa mem options on all boards - Rationalise XLEN and operand lengths - Bump the OpenTitan FPGA support - Remove the Ibex PLIC - General code cleanup ---------------------------------------------------------------- Alistair Francis (7): target/riscv: Remove some unused macros target/riscv: Organise the CPU properties hw/riscv: opentitan: Update to the latest build hw/intc: Remove the Ibex PLIC hw/intc: sifive_plic: Move the properties hw/intc: sifive_plic: Cleanup the realize function hw/intc: sifive_plic: Cleanup the irq_request function Bin Meng (6): hw/riscv: microchip_pfsoc: Use MachineState::ram and MachineClass::default_ram_id hw/riscv: opentitan: Use MachineState::ram and MachineClass::default_ram_id hw/riscv: shakti_c: Use MachineState::ram and MachineClass::default_ram_id hw/riscv: sifive_e: Use MachineState::ram and MachineClass::default_ram_id hw/riscv: sifive_u: Use MachineState::ram and MachineClass::default_ram_id hw/riscv: spike: Use MachineState::ram and MachineClass::default_ram_id Frank Chang (2): target/riscv: Pass the same value to oprsz and maxsz for vmv.v.v target/riscv: fix TB_FLAGS bits overlapping bug for rvv/rvh Mingwang Li (1): hw/riscv: virt: Use machine->ram as the system memory Philipp Tomsich (1): target/riscv: Fix orc.b implementation Richard Henderson (15): target/riscv: Move cpu_get_tb_cpu_state out of line target/riscv: Create RISCVMXL enumeration target/riscv: Split misa.mxl and misa.ext target/riscv: Replace riscv_cpu_is_32bit with riscv_cpu_mxl target/riscv: Add MXL/SXL/UXL to TB_FLAGS target/riscv: Use REQUIRE_64BIT in amo_check64 target/riscv: Properly check SEW in amo_op target/riscv: Replace is_32bit with get_xl/get_xlen target/riscv: Replace DisasContext.w with DisasContext.ol target/riscv: Use gen_arith_per_ol for RVM target/riscv: Adjust trans_rev8_32 for riscv64 target/riscv: Use gen_unary_per_ol for RVB target/riscv: Use gen_shift*_per_ol for RVB, RVI target/riscv: Use riscv_csrrw_debug for cpu_dump target/riscv: Compute mstatus.sd on demand Travis Geiselbrecht (1): target/riscv: line up all of the registers in the info register dump include/hw/riscv/opentitan.h | 6 +- target/riscv/cpu.h | 87 +++------ target/riscv/cpu_bits.h | 16 +- hw/intc/ibex_plic.c | 307 -------------------------------- hw/intc/sifive_plic.c | 85 ++++----- hw/riscv/boot.c | 2 +- hw/riscv/microchip_pfsoc.c | 36 ++-- hw/riscv/opentitan.c | 38 +++- hw/riscv/shakti_c.c | 6 +- hw/riscv/sifive_e.c | 16 +- hw/riscv/sifive_u.c | 6 +- hw/riscv/spike.c | 6 +- hw/riscv/virt.c | 6 +- linux-user/elfload.c | 2 +- linux-user/riscv/cpu_loop.c | 2 +- semihosting/arm-compat-semi.c | 2 +- target/riscv/cpu.c | 216 ++++++++++++---------- target/riscv/cpu_helper.c | 92 +++++++++- target/riscv/csr.c | 104 ++++++----- target/riscv/gdbstub.c | 10 +- target/riscv/machine.c | 10 +- target/riscv/monitor.c | 4 +- target/riscv/translate.c | 174 +++++++++++++----- target/riscv/insn_trans/trans_rvb.c.inc | 153 +++++++++------- target/riscv/insn_trans/trans_rvi.c.inc | 44 ++--- target/riscv/insn_trans/trans_rvm.c.inc | 36 +++- target/riscv/insn_trans/trans_rvv.c.inc | 32 ++-- hw/intc/meson.build | 1 - 28 files changed, 720 insertions(+), 779 deletions(-) delete mode 100644 hw/intc/ibex_plic.c
From: Frank Chang <frank.chang@sifive.com> 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 <frank.chang@sifive.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211007081803.1705656-1-frank.chang@sifive.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -XXX,XX +XXX,XX @@ 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; -- 2.31.1
From: Travis Geiselbrecht <travisg@gmail.com> 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 <travisg@gmail.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20211009055019.545153-1-travisg@gmail.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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"); @@ -XXX,XX +XXX,XX @@ 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"); -- 2.31.1
From: Philipp Tomsich <philipp.tomsich@vrull.eu> 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 <philipp.tomsich@vrull.eu> Reported-by: Vincent Palatin <vpalatin@rivosinc.com> Tested-by: Vincent Palatin <vpalatin@rivosinc.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211013184125.2010897-1-philipp.tomsich@vrull.eu Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -XXX,XX +XXX,XX @@ 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); -- 2.31.1
From: Mingwang Li <limingwang@huawei.com> 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 <limingwang@huawei.com> Signed-off-by: Yifei Jiang <jiangyifei@huawei.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20211016030908.40480-1-limingwang@huawei.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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, @@ -XXX,XX +XXX,XX @@ 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); -- 2.31.1
From: Frank Chang <frank.chang@sifive.com> 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 <frank.chang@sifive.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-Id: <20211015074627.3957162-2-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ 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 @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -XXX,XX +XXX,XX @@ 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) -- 2.31.1
From: Alistair Francis <alistair.francis@wdc.com> 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 <alistair.francis@wdc.com> Reviewed-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -XXX,XX +XXX,XX @@ #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 -- 2.31.1
From: Alistair Francis <alistair.francis@wdc.com> Organise the CPU properties so that standard extensions come first then followed by experimental extensions. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ 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), @@ -XXX,XX +XXX,XX @@ 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), -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> Move the function to cpu_helper.c, as it is large and growing. Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-2-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -XXX,XX +XXX,XX @@ 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) { -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> Move the MXL_RV* defines to enumerators. Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-3-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -XXX,XX +XXX,XX @@ #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 -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> 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 <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-4-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 15 +++---- linux-user/elfload.c | 2 +- linux-user/riscv/cpu_loop.c | 2 +- target/riscv/cpu.c | 78 +++++++++++++++++++++---------------- 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/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ #include "exec/cpu-defs.h" #include "fpu/softfloat-types.h" #include "qom/object.h" +#include "cpu_bits.h" #define TCG_GUEST_DEFAULT_MO 0 @@ -XXX,XX +XXX,XX @@ # 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') @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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/linux-user/elfload.c b/linux-user/elfload.c index XXXXXXX..XXXXXXX 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/linux-user/riscv/cpu_loop.c +++ b/linux-user/riscv/cpu_loop.c @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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, @@ -XXX,XX +XXX,XX @@ 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"); @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ 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)) { @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -XXX,XX +XXX,XX @@ 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 */ @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -XXX,XX +XXX,XX @@ 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), @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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 @@ -XXX,XX +XXX,XX @@ 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 @@ -XXX,XX +XXX,XX @@ 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; -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> 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 <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-5-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 9 ++++++++- hw/riscv/boot.c | 2 +- semihosting/arm-compat-semi.c | 2 +- target/riscv/cpu.c | 24 ++++++++++++++---------- 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/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ 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/hw/riscv/boot.c b/hw/riscv/boot.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/semihosting/arm-compat-semi.c +++ b/semihosting/arm-compat-semi.c @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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)); } @@ -XXX,XX +XXX,XX @@ 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(); } } @@ -XXX,XX +XXX,XX @@ 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_helper.c b/target/riscv/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ 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) && @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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]; @@ -XXX,XX +XXX,XX @@ 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. @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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) { @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -XXX,XX +XXX,XX @@ 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, "<?xml version=\"1.0\"?>"); diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/monitor.c +++ b/target/riscv/monitor.c @@ -XXX,XX +XXX,XX @@ 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 { @@ -XXX,XX +XXX,XX @@ 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; -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> 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 <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-6-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 2 ++ target/riscv/cpu.c | 8 ++++++++ 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.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ 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.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ 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_helper.c b/target/riscv/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -XXX,XX +XXX,XX @@ 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) { @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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; -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> Use the same REQUIRE_64BIT check that we use elsewhere, rather than open-coding the use of is_32bit. Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-7-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -XXX,XX +XXX,XX @@ 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) -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> 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 <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-8-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -XXX,XX +XXX,XX @@ 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); -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> In preparation for RV128, replace a simple predicate with a more versatile test. Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-9-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/translate.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -XXX,XX +XXX,XX @@ 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) +#define get_xl(ctx) ((ctx)->xl) +#endif + +/* The word size for this machine mode. */ +static inline int __attribute__((unused)) get_xlen(DisasContext *ctx) { - return ctx->xl == MXL_RV32; + return 16 << get_xl(ctx); } -#endif /* The word size for this operation. */ static inline int oper_len(DisasContext *ctx) @@ -XXX,XX +XXX,XX @@ 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. */ @@ -XXX,XX +XXX,XX @@ 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) -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> 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 <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-10-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/translate.c | 69 ++++++++++++++++--------- 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 ++-- 4 files changed, 62 insertions(+), 43 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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) +/* 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 ctx->w ? 32 : TARGET_LONG_BITS; + return 16 << get_ol(ctx); } - /* * RISC-V requires NaN-boxing of narrower width floating point values. * This applies when a 32-bit value is assigned to a 64-bit FP register. @@ -XXX,XX +XXX,XX @@ 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]; @@ -XXX,XX +XXX,XX @@ 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(); } } } @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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)); @@ -XXX,XX +XXX,XX @@ 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]); diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); } -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> The multiply high-part instructions require a separate implementation for RV32 when TARGET_LONG_BITS == 64. Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-11-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/translate.c | 16 +++++++++++++++ target/riscv/insn_trans/trans_rvm.c.inc | 26 ++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -XXX,XX +XXX,XX @@ 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)) { diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/insn_trans/trans_rvm.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvm.c.inc +++ b/target/riscv/insn_trans/trans_rvm.c.inc @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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) -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> 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 <alistair.francis@wdc.com> Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-12-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -XXX,XX +XXX,XX @@ 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) -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> The count zeros instructions require a separate implementation for RV32 when TARGET_LONG_BITS == 64. Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-13-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/translate.c | 16 ++++++++++++ target/riscv/insn_trans/trans_rvb.c.inc | 33 ++++++++++++------------- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -XXX,XX +XXX,XX @@ 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); diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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) -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> Most shift instructions require a separate implementation for RV32 when TARGET_LONG_BITS == 64. Reviewed-by: LIU Zhiwei <zhiwei_liu@c-sky.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-14-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/translate.c | 31 +++++++++ target/riscv/insn_trans/trans_rvb.c.inc | 92 ++++++++++++++----------- target/riscv/insn_trans/trans_rvi.c.inc | 26 +++---- 3 files changed, 97 insertions(+), 52 deletions(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -XXX,XX +XXX,XX @@ 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)) { @@ -XXX,XX +XXX,XX @@ 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)) { diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/insn_trans/trans_rvb.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvb.c.inc +++ b/target/riscv/insn_trans/trans_rvb.c.inc @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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); -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> 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 <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-15-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ 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)); - } - 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); + { + 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); + } + } } - 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++) { -- 2.31.1
From: Richard Henderson <richard.henderson@linaro.org> 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 <alistair.francis@wdc.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20211020031709.359469-16-richard.henderson@linaro.org Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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 | @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -XXX,XX +XXX,XX @@ 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. */ @@ -XXX,XX +XXX,XX @@ 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); } @@ -XXX,XX +XXX,XX @@ 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); } -- 2.31.1
From: Alistair Francis <alistair.francis@wdc.com> Update the OpenTitan machine model to match the latest OpenTitan FPGA design. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Message-id: 18b1b681b0f8dd2461e819d1217bf0b530812680.1634524691.git.alistair.francis@wdc.com --- include/hw/riscv/opentitan.h | 6 +++--- hw/riscv/opentitan.c | 22 +++++++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/riscv/opentitan.h +++ b/include/hw/riscv/opentitan.h @@ -XXX,XX +XXX,XX @@ #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" @@ -XXX,XX +XXX,XX @@ struct LowRISCIbexSoCState { /*< public >*/ RISCVHartArrayState cpus; - IbexPlicState plic; + SiFivePLICState plic; IbexUartState uart; IbexTimerState timer; @@ -XXX,XX +XXX,XX @@ 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, diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -XXX,XX +XXX,XX @@ 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 }, }; @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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)); } -- 2.31.1
From: Alistair Francis <alistair.francis@wdc.com> The Ibex PLIC is now spec compliant. Let's remove the Ibex PLIC and instead use the SiFive PLIC. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> 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 XXXXXXX..XXXXXXX --- a/hw/intc/ibex_plic.c +++ /dev/null @@ -XXX,XX +XXX,XX @@ -/* - * 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 <http://www.gnu.org/licenses/>. - */ - -#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 XXXXXXX..XXXXXXX 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -XXX,XX +XXX,XX @@ 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')) -- 2.31.1
From: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> 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 XXXXXXX..XXXXXXX 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -XXX,XX +XXX,XX @@ 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 * @@ -XXX,XX +XXX,XX @@ 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); -- 2.31.1
From: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> Message-id: b94c098cb221e744683349b1ac794c23102ef471.1634524691.git.alistair.francis@wdc.com --- hw/intc/sifive_plic.c | 45 +++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -XXX,XX +XXX,XX @@ 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); - - plic->s_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts); - qdev_init_gpio_out(dev, plic->s_external_irqs, plic->num_harts); - - plic->m_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts); - qdev_init_gpio_out(dev, plic->m_external_irqs, plic->num_harts); + 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); + + parse_hart_config(s); + + 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); -- 2.31.1
From: Alistair Francis <alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com> 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 XXXXXXX..XXXXXXX 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -XXX,XX +XXX,XX @@ 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) -- 2.31.1
From: Bin Meng <bmeng.cn@gmail.com> 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 <bmeng.cn@gmail.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Message-id: 20211020014112.7336-2-bmeng.cn@gmail.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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 -- 2.31.1
From: Bin Meng <bmeng.cn@gmail.com> 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 <bmeng.cn@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Message-id: 20211020014112.7336-3-bmeng.cn@gmail.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "hw/riscv/opentitan.h" #include "qapi/error.h" #include "hw/boards.h" @@ -XXX,XX +XXX,XX @@ 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); @@ -XXX,XX +XXX,XX @@ 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) -- 2.31.1
From: Bin Meng <bmeng.cn@gmail.com> 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 <bmeng.cn@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20211020014112.7336-4-bmeng.cn@gmail.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/shakti_c.c +++ b/hw/riscv/shakti_c.c @@ -XXX,XX +XXX,XX @@ 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) { @@ -XXX,XX +XXX,XX @@ 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, @@ -XXX,XX +XXX,XX @@ 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 = { -- 2.31.1
From: Bin Meng <bmeng.cn@gmail.com> 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 <bmeng.cn@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Message-id: 20211020014112.7336-5-bmeng.cn@gmail.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/sifive_e.c +++ b/hw/riscv/sifive_e.c @@ -XXX,XX +XXX,XX @@ */ #include "qemu/osdep.h" +#include "qemu/cutils.h" #include "qemu/error-report.h" #include "qapi/error.h" #include "hw/boards.h" @@ -XXX,XX +XXX,XX @@ 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]; @@ -XXX,XX +XXX,XX @@ 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); -- 2.31.1
From: Bin Meng <bmeng.cn@gmail.com> 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 <bmeng.cn@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20211020014112.7336-6-bmeng.cn@gmail.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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", @@ -XXX,XX +XXX,XX @@ 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, -- 2.31.1
From: Bin Meng <bmeng.cn@gmail.com> 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 <bmeng.cn@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20211020014112.7336-7-bmeng.cn@gmail.com Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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, @@ -XXX,XX +XXX,XX @@ 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 = { -- 2.31.1
From: Alistair Francis <alistair.francis@wdc.com> The following changes since commit f5a2438405d4ae8b62de7c9b39fac0b2155ee544: Merge tag 'pull-qapi-2026-05-21' of https://repo.or.cz/qemu/armbru into staging (2026-05-21 09:00:22 -0400) are available in the Git repository at: https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20260522 for you to fetch changes up to b7d87fb10d53a918e9c4a3dfe1fb06ce42c52526: hw/riscv: riscv-iommu: Re-process command queue after clearing CMD_ILL (2026-05-22 09:59:21 +1000) ---------------------------------------------------------------- RISC-V PR for 11.1. * Remove spike as default machine * Deprecate the shakti_c machine * Set MISA.[C|X] based on the selected extensions * Update Maintainers for OpenSBI Firmware * Update OpenSBI to v1.8.1 * Avoid RISCVCPU copy in PMU FDT setup * A collection of specification compliance improvements * Fix Svnapot 64KB pages * Handle source overlap of vector widening reduction instructions * Check interrupt in SiFive UART after txctrl register is written * Fix medeleg[11] read-only zero bit for M-mode ECALL * Fix tail handling for vmv.s.x and vfmv.s.f * Update the local AIA interrupt mask * Add KVM support for Zicbop and BFloat16 extensions * Fix the IOMMU FSC SV32 capability check * Avoid caching PCI device IDs in the IOMMU * Implement Microchip mpfs ioscb PLLs and sysreg clock dividers * Remove the internal CPU riscv_cpu_* arrays * Fix IOCOUNTINH.CY toggle detection * Fix the read of pmpaddr(0-63) CSRs * Make hpmcounterh return the upper 32-bits * Minor fixes and enhancements of RISC-V AIA devices * Re-process IOMMU command queue after clearing CMD_ILL ---------------------------------------------------------------- Abhigyan Kumar (1): target/riscv: Fix medeleg[11] read-only zero bit for M-mode ECALL Alistair Francis (4): target/riscv: Remove spike as default machine target/riscv: Deprecate the shakti_c machine MAINTAINERS: Maintain OpenSBI Firmware target/riscv: Update the local interrupt mask Andrew Jones (1): hw/riscv/riscv-iommu: Fix Svnapot 64KB pages Anton Blanchard (1): target/riscv: rvv: Handle source overlap of vector widening reduction instructions Chengbo Gao (1): hw/riscv/riscv-iommu: Avoid caching PCI device IDs Daniel Henrique Barboza (16): roms/opensbi: Update to v1.8.1 target/riscv/cpu.c: add xlrbr isa_edata_arr[] entry target/riscv/cpu.c: fix smctr/ssctr isa_edata_arr[] order target/riscv: make riscv-qmp-cmds use isa_data_arr[] target/riscv/tcg: treat all exts equally in cpu_disable_priv_spec_isa_exts target/riscv/tcg: use only isa_edata_arr[] in cpu_cfg_ext_get_name() target/riscv/cpu.c: remove riscv_cpu_enable_named_feat() target/riscv: remove riscv_cpu_named_features[] target/riscv/tcg: use isa_edata_arr[] in riscv_cpu_update_misa_x() target/riscv/kvm: use isa_edata_arr[] for unavailable props target/riscv/tcg: use isa_edata_arr[] to enable max exts target/riscv/tcg: use cfg_offset as cpu_set_multi_ext cb opaque target/riscv: do not set defaults in cpu prop callback target/riscv/tcg: use isa_edata_arr[] to create user props target/riscv/cpu: remove riscv_cpu_* arrays target/riscv/csr.c: fix read of pmpaddr(0-63) CSRs Fangyu Yu (1): hw/riscv/riscv-iommu: Fix IOCOUNTINH.CY toggle detection Frank Chang (3): target/riscv: Update MISA.C for Zc* extensions target/riscv: Update MISA.X for non-standard extensions hw/char: Check interrupt after txctrl register is written Guenter Roeck (1): hw: misc: Implement Microchip mpfs ioscb PLLs and sysreg clock dividers Jay Chang (1): hw/riscv: riscv-iommu: Re-process command queue after clearing CMD_ILL Jim Shu (4): hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode hw/intc: riscv_aplic: Add reset API to APLIC hw/intc: riscv_imsic: Add reset API to IMSIC hw/intc: riscv_aplic: add trace events of APLIC read/write function Mohamed Ayman (1): riscv: virt: avoid RISCVCPU copy in PMU FDT setup Portia Stephens (1): target/riscv: Make hpmcounterh return the upper 32-bits Zishun Yi (9): target/riscv: Allow mseccfg access based on ext_zicfilp target/riscv: add Zvknha as an implied extension for Zvknhb target/riscv: Remove unconditional MENVCFG_CDE from mask target/riscv: Fix missing CDE check for scountinhibit target/riscv/pmp: Fix integer overflow in TOR and NA4 address computation target/riscv: Add mseccfg to VMStateDescription target/riscv: clear mseccfg on reset for all dependent extensions hw/riscv/riscv-iommu: fix FSC SV32 capability check hw/riscv/virt-acpi-build: Fix off-by-one error in RIMT ID mapping Zongmin Zhou (2): target/riscv/kvm: add KVM support for Zicbop extension target/riscv/kvm: Add BFloat16 extensions support chen.zhongyao@zte.com.cn (1): target/riscv: Fix tail handling for vmv.s.x and vfmv.s.f MAINTAINERS | 2 + docs/about/deprecated.rst | 21 +- docs/about/removed-features.rst | 14 ++ include/hw/misc/mchp_pfsoc_ioscb.h | 2 + target/riscv/cpu.h | 13 +- target/riscv/helper.h | 4 + hw/char/sifive_uart.c | 1 + hw/intc/riscv_aplic.c | 116 ++++++--- hw/intc/riscv_imsic.c | 19 ++ hw/misc/mchp_pfsoc_ioscb.c | 47 +++- hw/misc/mchp_pfsoc_sysreg.c | 13 + hw/riscv/riscv-iommu-hpm.c | 3 +- hw/riscv/riscv-iommu.c | 96 ++++++-- hw/riscv/shakti_c.c | 1 + hw/riscv/spike.c | 1 - hw/riscv/virt-acpi-build.c | 3 +- hw/riscv/virt.c | 4 +- target/riscv/cpu.c | 327 +++++++++---------------- target/riscv/csr.c | 36 ++- target/riscv/kvm/kvm-cpu.c | 62 +++-- target/riscv/machine.c | 20 ++ target/riscv/pmp.c | 4 +- target/riscv/riscv-qmp-cmds.c | 30 +-- target/riscv/tcg/tcg-cpu.c | 192 +++++++-------- target/riscv/vector_helper.c | 18 ++ target/riscv/insn_trans/trans_rvv.c.inc | 45 ++-- hw/intc/trace-events | 4 + pc-bios/opensbi-riscv32-generic-fw_dynamic.bin | Bin 268752 -> 270384 bytes pc-bios/opensbi-riscv64-generic-fw_dynamic.bin | Bin 273048 -> 275928 bytes roms/opensbi | 2 +- 30 files changed, 613 insertions(+), 487 deletions(-)
From: Alistair Francis <alistair.francis@wdc.com> In QEMU 10.0 we deprecated the default spike machine, let's finally remove spike as the default and require users to specify the machine. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260430052218.771358-2-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- docs/about/deprecated.rst | 18 ------------------ docs/about/removed-features.rst | 14 ++++++++++++++ hw/riscv/spike.c | 1 - 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -XXX,XX +XXX,XX @@ better reflects the way this property affects all random data within the device tree blob, not just the ``kaslr-seed`` node. -RISC-V default machine option (since 10.0) -'''''''''''''''''''''''''''''''''''''''''' - -RISC-V defines ``spike`` as the default machine if no machine option is -given in the command line. This happens because ``spike`` is the first -RISC-V machine implemented in QEMU and setting it as default was -convenient at that time. Now we have 7 riscv64 and 6 riscv32 machines -and having ``spike`` as a default is no longer justified. This default -will also promote situations where users think they're running ``virt`` -(the most used RISC-V machine type in 10.0) when in fact they're -running ``spike``. - -Removing the default machine option forces users to always set the machine -they want to use and avoids confusion. Existing users of the ``spike`` -machine must ensure that they're setting the ``spike`` machine in the -command line (``-M spike``). - - Backend options --------------- diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -XXX,XX +XXX,XX @@ firmware is available to boot it. It can be replaced by the ``ast2700fc``, another multi-SoC machine based on the newer AST2700 SoCs which are excepted to receive better support in the future. +RISC-V default machine (removed in 11.1) +'''''''''''''''''''''''''''''''''''''''' + +RISC-V used to define ``spike`` as the default machine if no machine option +was given via the command line. This happend because ``spike`` was the first +RISC-V machine implemented in QEMU and setting it as default was +convenient at that time. Now we have 7 riscv64 and 6 riscv32 machines +and having ``spike`` as a default is no longer justified. + +The default machine option has been removed, forcing users to always set the +machine they want to use to avoid confusion. Existing users of the ``spike`` +machine must ensure that they're setting the ``spike`` machine in the +command line (``-M spike``). + linux-user mode CPUs -------------------- diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -XXX,XX +XXX,XX @@ static void spike_machine_class_init(ObjectClass *oc, const void *data) mc->desc = "RISC-V Spike board"; mc->init = spike_board_init; mc->max_cpus = SPIKE_CPUS_MAX; - mc->is_default = true; mc->default_cpu_type = TYPE_RISCV_CPU_BASE; mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids; mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props; -- 2.53.0
From: Alistair Francis <alistair.francis@wdc.com> The RISC-V shakti_c machine hasn't had meaningful contributions since 2021 and is currently unmaintained. The machine is scheduled to be removed as it appears to have no users. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260430052218.771358-3-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- docs/about/deprecated.rst | 7 +++++++ hw/riscv/shakti_c.c | 1 + 2 files changed, 8 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -XXX,XX +XXX,XX @@ deprecated; use the new name ``dtb-randomness`` instead. The new name better reflects the way this property affects all random data within the device tree blob, not just the ``kaslr-seed`` node. +RISC-V Shakti machine (since 11.1) +'''''''''''''''''''''''''''''''''' + +The RISC-V ``shakti_c`` machine hasn't had meaningful contributions since 2021 +and is currently unmaintained. The machine is scheduled to be removed as it +appears to have no users. + Backend options --------------- diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/shakti_c.c +++ b/hw/riscv/shakti_c.c @@ -XXX,XX +XXX,XX @@ static void shakti_c_machine_class_init(ObjectClass *klass, const void *data) mc->init = shakti_c_machine_state_init; mc->default_cpu_type = TYPE_RISCV_CPU_SHAKTI_C; mc->valid_cpu_types = valid_cpu_types; + mc->deprecation_reason = "Currently unmaintained with no known users"; mc->default_ram_id = "riscv.shakti.c.ram"; } -- 2.53.0
From: Frank Chang <frank.chang@sifive.com> MISA.C is set if the following extensions are selected: * Zca and not F. * Zca, Zcf and F (but not D) is specified (RV32 only). * Zca, Zcf and Zcd if D is specified (RV32 only). * Zca, Zcd if D is specified (RV64 only). Therefore, MISA.C must be set according to the Zc* extension rules. Warn the user if RVC is explicitly disabled but MISA.C is required by the rules above. Signed-off-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Max Chou <max.chou@sifive.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260424050509.3935180-2-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_enable_implied_rules(RISCVCPU *cpu) } } +/* + * MISA.C is set if the following extensions are selected: + * - Zca and not F. + * - Zca, Zcf and F (but not D) is specified on RV32. + * - Zca, Zcf and Zcd if D is specified on RV32. + * - Zca, Zcd if D is specified on RV64. + */ +static void riscv_cpu_update_misa_c(RISCVCPU *cpu) +{ + CPURISCVState *env = &cpu->env; + bool set_misa_c = false; + + if (riscv_has_ext(env, RVC)) { + return; + } + + if (cpu->cfg.ext_zca && !riscv_has_ext(env, RVF)) { + set_misa_c = true; + } else if (riscv_cpu_mxl(env) == MXL_RV32 && + cpu->cfg.ext_zca && cpu->cfg.ext_zcf && + (riscv_has_ext(env, RVD) ? cpu->cfg.ext_zcd : + riscv_has_ext(env, RVF))) { + set_misa_c = true; + } else if (riscv_cpu_mxl(env) == MXL_RV64 && + cpu->cfg.ext_zca && cpu->cfg.ext_zcd) { + set_misa_c = true; + } + + if (set_misa_c) { + if (cpu_misa_ext_is_user_set(RVC)) { + warn_report("RVC mandated by Zca/Zcf/Zcd extensions"); + return; + } + + riscv_cpu_set_misa_ext(env, env->misa_ext | RVC); + } +} + void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) { CPURISCVState *env = &cpu->env; @@ -XXX,XX +XXX,XX @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) riscv_cpu_init_implied_exts_rules(); riscv_cpu_enable_implied_rules(cpu); + riscv_cpu_update_misa_c(cpu); riscv_cpu_validate_misa_priv(env, &local_err); if (local_err != NULL) { -- 2.53.0
From: Frank Chang <frank.chang@sifive.com> MISA.X is set if there are any non-standard extensions. We should set MISA.X when any of the vendor extensions is enabled. Signed-off-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Max Chou <max.chou@sifive.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260424050509.3935180-3-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 + target/riscv/tcg/tcg-cpu.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState CPURISCVState; #define RVH RV('H') #define RVG RV('G') #define RVB RV('B') +#define RVX RV('X') extern const uint32_t misa_bits[]; const char *riscv_get_misa_ext_name(uint32_t bit); diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_update_misa_c(RISCVCPU *cpu) } } +/* MISA.X is set when any of the non-standard extensions is enabled. */ +static void riscv_cpu_update_misa_x(RISCVCPU *cpu) +{ + CPURISCVState *env = &cpu->env; + const RISCVCPUMultiExtConfig *arr = riscv_cpu_vendor_exts; + + for (int i = 0; arr[i].name != NULL; i++) { + if (isa_ext_is_enabled(cpu, arr[i].offset)) { + riscv_cpu_set_misa_ext(env, env->misa_ext | RVX); + break; + } + } +} + void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) { CPURISCVState *env = &cpu->env; @@ -XXX,XX +XXX,XX @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) riscv_cpu_init_implied_exts_rules(); riscv_cpu_enable_implied_rules(cpu); riscv_cpu_update_misa_c(cpu); + riscv_cpu_update_misa_x(cpu); riscv_cpu_validate_misa_priv(env, &local_err); if (local_err != NULL) { -- 2.53.0
From: Alistair Francis <alistair.francis@wdc.com> Mark the OpenSBI Firmware as maintained by me (Alistair Francis) and add Daniel Henrique Barboza as a reviewer. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20260506234243.1873782-1-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index XXXXXXX..XXXXXXX 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -XXX,XX +XXX,XX @@ S: Supported F: hw/i386/amd_iommu* OpenSBI Firmware +M: Alistair Francis <Alistair.Francis@wdc.com> +R: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> L: qemu-riscv@nongnu.org S: Supported F: pc-bios/opensbi-* -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Update OpenSBI and the pre-built opensbi32 and opensbi64 images to version 1.8.1. We're going for the intermediate/bug fix release 1.8.1 directly due to a PMP related fix that was impacting QEMU profile CPUs. Changelog for v1.8.1: * Typo fix in comments of sbi_hartindex_to_hartid() * Fix hart protection abstraction for platforms without PMP Changelog for v1.8 includes, among other things: - IPI device ratings - SiFive CLINT v2 support - SiFive PL2 cache controller driver - SiFive Extensible Cache (EC) driver - SiFive TMC0 based HSM driver - SiFive SMC0 based system suspend driver - MPXY RPMI mailbox driver for voltage service group - MPXY RPMI mailbox driver for device power service group - MPXY RPMI mailbox driver for performance service group Check out the full release log at [1] for more info. [1] https://github.com/riscv-software-src/opensbi/releases/tag/v1.8 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260108160825.171794-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- .../opensbi-riscv32-generic-fw_dynamic.bin | Bin 268752 -> 270384 bytes .../opensbi-riscv64-generic-fw_dynamic.bin | Bin 273048 -> 275928 bytes roms/opensbi | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin index XXXXXXX..XXXXXXX 100644 Binary files a/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin and b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin differ diff --git a/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin index XXXXXXX..XXXXXXX 100644 Binary files a/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin and b/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin differ diff --git a/roms/opensbi b/roms/opensbi index XXXXXXX..XXXXXXX 160000 --- a/roms/opensbi +++ b/roms/opensbi @@ -1 +1 @@ -Subproject commit a32a91069119e7a5aa31e6bc51d5e00860be3d80 +Subproject commit 74434f255873d74e56cc50aa762d1caf24c099f8 -- 2.53.0
From: Mohamed Ayman <mohamedaymanworkspace@gmail.com> Use a pointer to the hart instead of copying RISCVCPU when passing pmu_avail_ctrs to riscv_pmu_generate_fdt_node(). Signed-off-by: Mohamed Ayman <mohamedaymanworkspace@gmail.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260503180252.1122776-1-mohamedaymanworkspace@gmail.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -XXX,XX +XXX,XX @@ static void create_fdt_pmu(RISCVVirtState *s) { g_autofree char *pmu_name = g_strdup_printf("/pmu"); MachineState *ms = MACHINE(s); - RISCVCPU hart = s->soc[0].harts[0]; + RISCVCPU *hart = &s->soc[0].harts[0]; qemu_fdt_add_subnode(ms->fdt, pmu_name); qemu_fdt_setprop_string(ms->fdt, pmu_name, "compatible", "riscv,pmu"); - riscv_pmu_generate_fdt_node(ms->fdt, hart.pmu_avail_ctrs, pmu_name); + riscv_pmu_generate_fdt_node(ms->fdt, hart->pmu_avail_ctrs, pmu_name); } static void create_fdt_sockets(RISCVVirtState *s, -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> The Zicfilp extension adds the MLPE field to the mseccfg CSR. According to the RISC-V Privileged Specification, mseccfg exists if any extension that adds a field to it is implemented. Currently, the `have_mseccfg()` predicate function checks for Smepmp, Zkr, and Smmpm, but misses Zicfilp. As a result, if a CPU is configured with `zicfilp=true` but without the other extensions, accessing the mseccfg CSR will incorrectly raise an illegal instruction exception. This patch adds the missing check for `ext_zicfilp` to ensure the CSR is properly accessible when the Zicfilp extension is enabled. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2561/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260511072705.3015986-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static RISCVException have_mseccfg(CPURISCVState *env, int csrno) if (riscv_cpu_cfg(env)->ext_smmpm) { return RISCV_EXCP_NONE; } + if (riscv_cpu_cfg(env)->ext_zicfilp) { + return RISCV_EXCP_NONE; + } return RISCV_EXCP_ILLEGAL_INST; } -- 2.53.0
From: Andrew Jones <andrew.jones@oss.qualcomm.com> The Svnapot extension encodes a 64KB leaf PTE by setting PTE_N and storing bits [3:0] of the PPN as a NAPOT size indicator. The IOMMU model wasn't checking PTE_N and therefore was using the raw (NAPOT- encoded) PPN directly in the physical address, yielding an address 32 KB above the correct base. Fix both riscv_iommu_spa_fetch() and pdt_memory_read() by mirroring the Svnapot handling already present in target/riscv/cpu_helper.c: napot_bits = ctz64(ppn) + 1 /* 4 for 64KB */ napot_mask = (1 << napot_bits) - 1 /* 0xF */ phys_base = PPN_PHYS(ppn & ~napot_mask) page_offset = addr & (PPN_PHYS(napot_mask) | (TARGET_PAGE_SIZE - 1)) The spec only defines napot_bits == 4 (64KB); any other value is treated as a reserved encoding. This is a fix, rather than new feature support, because the spec says "IOMMU implementations must support the Svnapot standard extension for NAPOT Translation Contiguity." Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation") Cc: qemu-stable@nongnu.org Signed-off-by: Andrew Jones <andrew.jones@oss.qualcomm.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Reviewed-by: Tomasz Jeznach <tjeznach@rivosinc.com> Message-ID: <20260508205129.377032-1-andrew.jones@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 44 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static bool riscv_iommu_msi_check(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, return true; } +/* Returns the NAPOT page mask, or 0 for reserved encodings. */ +static hwaddr riscv_iommu_napot_page_mask(hwaddr ppn, hwaddr addr, hwaddr *out) +{ + int napot_bits = ctz64(ppn) + 1; + hwaddr napot_mask, page_mask; + + /* The spec only defines 64KB (napot_bits == 4) */ + if (napot_bits != 4) { + return 0; + } + + napot_mask = (1ULL << napot_bits) - 1; + page_mask = PPN_PHYS(napot_mask) | (TARGET_PAGE_SIZE - 1); + + *out = PPN_PHYS(ppn & ~napot_mask) | (addr & page_mask); + + return page_mask; +} + /* * RISCV IOMMU Address Translation Lookup - Page Table Walk * @@ -XXX,XX +XXX,XX @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, } else { /* Leaf PTE, translation completed. */ sc[pass].step = sc[pass].levels; - base = PPN_PHYS(ppn) | (addr & ((1ULL << va_skip) - 1)); - /* Update address mask based on smallest translation granularity */ - iotlb->addr_mask &= (1ULL << va_skip) - 1; + + if (pte & PTE_N) { + hwaddr mask = riscv_iommu_napot_page_mask(ppn, addr, &base); + + if (!mask) { + break; + } + iotlb->addr_mask &= mask; + } else { + base = PPN_PHYS(ppn) | (addr & ((1ULL << va_skip) - 1)); + /* Update address mask based on smallest translation granularity */ + iotlb->addr_mask &= (1ULL << va_skip) - 1; + } + /* Continue with S-Stage translation? */ if (pass && sc[0].step != sc[0].levels) { pass = S_STAGE; @@ -XXX,XX +XXX,XX @@ static MemTxResult pdt_memory_read(RISCVIOMMUState *s, return MEMTX_ACCESS_ERROR; /* Misaligned PPN */ } else { /* Leaf PTE, translation completed. */ - base = PPN_PHYS(ppn) | (addr & ((1ULL << va_skip) - 1)); + if (pte & PTE_N) { + if (!riscv_iommu_napot_page_mask(ppn, addr, &base)) { + return MEMTX_ACCESS_ERROR; + } + } else { + base = PPN_PHYS(ppn) | (addr & ((1ULL << va_skip) - 1)); + } break; } -- 2.53.0
From: Anton Blanchard <antonb@tenstorrent.com> Widening reductions read vs2 as a vector of SEW elements and vs1[0] as a scalar of 2*SEW. The ISA does not allow the same vector register to be read with different EEWs, so they must not overlap. vs1 is read as a scalar from element 0, so it is treated as a single vector register (independent of LMUL) when checking overlap. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3208 Signed-off-by: Anton Blanchard <antonb@tenstorrent.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260417080328.31918-1-antonb@tenstorrent.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/insn_trans/trans_rvv.c.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -XXX,XX +XXX,XX @@ GEN_OPIVV_TRANS(vredxor_vs, reduction_check) static bool reduction_widen_check(DisasContext *s, arg_rmrr *a) { return reduction_check(s, a) && (s->sew < MO_64) && + !is_overlapped(a->rs1, 1, a->rs2, 1 << MAX(s->lmul, 0)) && ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)); } -- 2.53.0
From: Frank Chang <frank.chang@sifive.com> It's possible that the transmit watermark level (txctrl.txcnt) is updated when the user writes to txctrl register, which may decrease the transmit watermark level to less than the number of entries in the transmit FIFO. In such a case, the interrupt should be raised so we need to call sifive_uart_update_irq() to check and update interrupt when txctrl register is written. Otherwise, the interrupt will have to be delayed until next TX FIFO transmission is processed. Suggested-by: Chao Liu <chao.liu.zevorn@gmail.com> Signed-off-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260513030503.3665414-1-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/char/sifive_uart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/char/sifive_uart.c b/hw/char/sifive_uart.c index XXXXXXX..XXXXXXX 100644 --- a/hw/char/sifive_uart.c +++ b/hw/char/sifive_uart.c @@ -XXX,XX +XXX,XX @@ sifive_uart_write(void *opaque, hwaddr addr, if (SIFIVE_UART_TXEN(s->txctrl) && !fifo8_is_empty(&s->tx_fifo)) { sifive_uart_trigger_tx_fifo(s); } + sifive_uart_update_irq(s); return; case SIFIVE_UART_RXCTRL: s->rxctrl = val64; -- 2.53.0
From: Abhigyan Kumar <314abh@gmail.com> RISC-V Privileged Specification 3.1.8 (Machine Trap Delegation Registers (medeleg and mideleg)) mentions: "For exceptions that cannot occur in less privileged modes, the corresponding medeleg bits should be read-only zero. In particular, medeleg[11] is read-only zero." QEMU incorrectly included RISCV_EXCP_M_ECALL in DELEGABLE_EXCPS. It allowed the 11th bit to be written and read as set. Fixed by removing it from the DELEGABLE_EXCPS mask, adhering to the specification. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3438 Signed-off-by: Abhigyan Kumar <314abh@gmail.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260427060849.749179-2-314abh@gmail.com> [ Changes by AF: - Remove comment ] Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static const uint64_t all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS | (1ULL << (RISCV_EXCP_U_ECALL)) | \ (1ULL << (RISCV_EXCP_S_ECALL)) | \ (1ULL << (RISCV_EXCP_VS_ECALL)) | \ - (1ULL << (RISCV_EXCP_M_ECALL)) | \ (1ULL << (RISCV_EXCP_INST_PAGE_FAULT)) | \ (1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT)) | \ (1ULL << (RISCV_EXCP_STORE_PAGE_FAULT)) | \ -- 2.53.0
From: "chen.zhongyao@zte.com.cn" <chen.zhongyao@zte.com.cn> The risc-v vector spec defines vmv.s.x and vfmv.s.f as writing element 0 of the destination register while the remaining destination elements follow the current tail policy. When QEMU runs with rvv_ta_all_1s enabled, those elements must therefore become all 1s. QEMU handled both instructions as translation-time special cases that directly wrote vd[0] and skipped the usual tail processing. As a result, vmv.s.x and vfmv.s.f left the remaining destination elements unchanged instead of applying the configured tail policy. Fix this by routing both instructions through a helper that writes vd[0] and then treats the rest of the destination register as tail, reusing the existing agnostic-element fill logic. Signed-off-by: Zhongyao Chen <chen.zhongyao@zte.com.cn> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <202605061005.646A537u037157@mse-fl1.zte.com.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/helper.h | 4 +++ target/riscv/vector_helper.c | 18 ++++++++++ target/riscv/insn_trans/trans_rvv.c.inc | 44 ++++++++----------------- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(vmv_v_x_b, void, ptr, i64, env, i32) DEF_HELPER_4(vmv_v_x_h, void, ptr, i64, env, i32) DEF_HELPER_4(vmv_v_x_w, void, ptr, i64, env, i32) DEF_HELPER_4(vmv_v_x_d, void, ptr, i64, env, i32) +DEF_HELPER_4(vset_velem0_b, void, ptr, i64, env, i32) +DEF_HELPER_4(vset_velem0_h, void, ptr, i64, env, i32) +DEF_HELPER_4(vset_velem0_w, void, ptr, i64, env, i32) +DEF_HELPER_4(vset_velem0_d, void, ptr, i64, env, i32) DEF_HELPER_6(vsaddu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vsaddu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -XXX,XX +XXX,XX @@ GEN_VEXT_VMV_VX(vmv_v_x_h, int16_t, H2) GEN_VEXT_VMV_VX(vmv_v_x_w, int32_t, H4) GEN_VEXT_VMV_VX(vmv_v_x_d, int64_t, H8) +#define GEN_VEXT_SET_VELEM0(NAME, ETYPE, H) \ +void HELPER(NAME)(void *vd, uint64_t s1, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t esz = sizeof(ETYPE); \ + uint32_t vlenb = riscv_cpu_cfg(env)->vlenb; \ + uint32_t vta = vext_vta(desc); \ + \ + *((ETYPE *)vd + H(0)) = (ETYPE)s1; \ + /* Treat every element past vd[0] as tail for scalar-to-vector moves. */ \ + vext_set_elems_1s(vd, vta, esz, vlenb); \ +} + +GEN_VEXT_SET_VELEM0(vset_velem0_b, int8_t, H1) +GEN_VEXT_SET_VELEM0(vset_velem0_h, int16_t, H2) +GEN_VEXT_SET_VELEM0(vset_velem0_w, int32_t, H4) +GEN_VEXT_SET_VELEM0(vset_velem0_d, int64_t, H8) + #define GEN_VEXT_VMERGE_VV(NAME, ETYPE, H) \ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ CPURISCVState *env, uint32_t desc) \ diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -XXX,XX +XXX,XX @@ static void vec_element_loadi(DisasContext *s, TCGv_i64 dest, load_element(dest, tcg_env, endian_ofs(s, vreg, idx), s->sew, sign); } -/* Integer Scalar Move Instruction */ +typedef void gen_helper_vset_velem0(TCGv_ptr, TCGv_i64, TCGv_env, TCGv_i32); -static void store_element(TCGv_i64 val, TCGv_ptr base, - int ofs, int sew) +static void vec_element_storei_tail(DisasContext *s, int vreg, TCGv_i64 val) { - switch (sew) { - case MO_8: - tcg_gen_st8_i64(val, base, ofs); - break; - case MO_16: - tcg_gen_st16_i64(val, base, ofs); - break; - case MO_32: - tcg_gen_st32_i64(val, base, ofs); - break; - case MO_64: - tcg_gen_st_i64(val, base, ofs); - break; - default: - g_assert_not_reached(); - } -} + static gen_helper_vset_velem0 * const fns[4] = { + gen_helper_vset_velem0_b, gen_helper_vset_velem0_h, + gen_helper_vset_velem0_w, gen_helper_vset_velem0_d, + }; + TCGv_ptr dest = tcg_temp_new_ptr(); + uint32_t data = FIELD_DP32(0, VDATA, VTA, s->vta); + TCGv_i32 desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb, + s->cfg_ptr->vlenb, data)); -/* - * Store vreg[idx] = val. - * The index must be in range of VLMAX. - */ -static void vec_element_storei(DisasContext *s, int vreg, - int idx, TCGv_i64 val) -{ - store_element(val, tcg_env, endian_ofs(s, vreg, idx), s->sew); + tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vreg)); + fns[s->sew](dest, val, tcg_env, desc); } /* vmv.x.s rd, vs2 # x[rd] = vs2[0] */ @@ -XXX,XX +XXX,XX @@ static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a) */ s1 = get_gpr(s, a->rs1, EXT_NONE); tcg_gen_ext_tl_i64(t1, s1); - vec_element_storei(s, a->rd, 0, t1); + vec_element_storei_tail(s, a->rd, t1); gen_set_label(over); tcg_gen_movi_tl(cpu_vstart, 0); finalize_rvv_inst(s); @@ -XXX,XX +XXX,XX @@ static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a) t1 = tcg_temp_new_i64(); do_nanbox(s, t1, cpu_fpr[a->rs1]); - vec_element_storei(s, a->rd, 0, t1); + vec_element_storei_tail(s, a->rd, t1); gen_set_label(over); tcg_gen_movi_tl(cpu_vstart, 0); -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> The RISC-V unpriv specification (zvk.adoc) states that "Zvknhb implies Zvknha". This means that enabling Zvknhb should automatically enable Zvknha. Add Zvknha to ZVKNHB_IMPLIED to ensure the dependency is correctly enforced. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link:https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2635/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260511051736.2916225-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static RISCVCPUImpliedExtsRule ZVKNG_IMPLIED = { static RISCVCPUImpliedExtsRule ZVKNHB_IMPLIED = { .ext = CPU_CFG_OFFSET(ext_zvknhb), .implied_multi_exts = { - CPU_CFG_OFFSET(ext_zve64x), + CPU_CFG_OFFSET(ext_zve64x), CPU_CFG_OFFSET(ext_zvknha), RISCV_IMPLIED_EXTS_RULE_END }, -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> Currently, the MENVCFG_CDE (Counter Delegation Enable) bit is unconditionally included in the base write mask for CSR_MENVCFG. This make the subsequent conditional check `(cfg->ext_smcdeleg ? MENVCFG_CDE : 0)` completely ineffective, as a bitwise OR cannot clear a bit that is already set. Fix this by removing MENVCFG_CDE from the initial base mask. The bit will now only be writable when explicitly granted by the `ext_smcdeleg` configuration. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2601/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260511040534.2862443-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno, { const RISCVCPUConfig *cfg = riscv_cpu_cfg(env); uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | - MENVCFG_CBZE | MENVCFG_CDE; + MENVCFG_CBZE; bool stce_changed = false; if (riscv_cpu_mxl(env) == MXL_RV64) { -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> According to the RISC-V smcdeleg specification: "When menvcfg.CDE=0, attempts to access scountinhibit raise an illegal-instruction exception." The current implementation of scountinhibit_pred() only checks the hardware extensions (ext_ssccfg, ext_smcdeleg) and virtualization status, but completely misses the runtime environment configuration check (menvcfg.CDE). This allows S-mode to access scountinhibit even when the M-mode has explicitly disabled counter delegation. This issue was discovered by the SpecHunter tool (https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2571/qemu.txt). Fixes: 6247dc2ef70b ("target/riscv: Add counter delegation/configuration support") Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260508174917.371667-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static RISCVException scountinhibit_pred(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } + if (!get_field(env->menvcfg, MENVCFG_CDE)) { + return RISCV_EXCP_ILLEGAL_INST; + } + if (env->virt_enabled) { return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> According to the RISC-V Privileged Manual: "The Sv32 page-based virtual-memory scheme described in sv32 supports 34-bit physical addresses for RV32, so the PMP scheme must support addresses wider than XLEN for RV32." However, the current QEMU implementation uses `target_ulong` (which resolves to `uint32_t` on RV32) for PMP address variables. When shifting these addresses left (e.g., `this_addr << 2`), an integer overflow occurs, truncating the high bits of the 34-bit physical address. Fix this issue by changing the types of PMP address variables (`this_addr` and `prev_addr`) to `hwaddr`. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2472/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260511102627.3120140-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/pmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -XXX,XX +XXX,XX @@ static void pmp_decode_napot(hwaddr a, hwaddr *sa, hwaddr *ea) void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index) { uint8_t this_cfg = env->pmp_state.pmp[pmp_index].cfg_reg; - target_ulong this_addr = env->pmp_state.pmp[pmp_index].addr_reg; - target_ulong prev_addr = 0u; + hwaddr this_addr = env->pmp_state.pmp[pmp_index].addr_reg; + hwaddr prev_addr = 0u; hwaddr sa = 0u; hwaddr ea = 0u; int g = pmp_get_granularity_g(env); -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> Currently, the Machine Security Configuration Register (mseccfg) was missing from the live migration state. This omission causes the register to be reset to zero on the destination host after migration. Fixed by adding vmstate_mseccfg subsection This vulnerability was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/a22e4459cd026ae970791dfbd9cfe5d110fbd46b/output/riscv-isa-manual/pr-1879/qemu.txt#L121 Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260511124828.3210477-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/machine.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/target/riscv/machine.c b/target/riscv/machine.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_sstc = { } }; +static bool mseccfg_needed(void *opaque) +{ + RISCVCPU *cpu = opaque; + + return cpu->cfg.ext_smepmp || cpu->cfg.ext_zkr + || cpu->cfg.ext_smmpm || cpu->cfg.ext_zicfilp; +} + +static const VMStateDescription vmstate_mseccfg = { + .name = "cpu/mseccfg", + .version_id = 1, + .minimum_version_id = 1, + .needed = mseccfg_needed, + .fields = (const VMStateField[]) { + VMSTATE_UINTTL(env.mseccfg, RISCVCPU), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_riscv_cpu = { .name = "cpu", .version_id = 11, @@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_riscv_cpu = { &vmstate_ssp, &vmstate_ctr, &vmstate_sstc, + &vmstate_mseccfg, NULL } }; -- 2.53.0
From: Alistair Francis <alistair.francis@wdc.com> The RISC-V spec describes bits 0-15 as standard fixed interrupts. The AIA spec on the other hand describes bits 0-12 as standard fixed interrupts. This conflict causes issues for us as we don't dynamically determine if AIA is enabled when setting the *delegable_ints consts. This means currently we incorrectly treat the LCOFIP bit as delegable, even if AIA is disabled, which is incorrect (see the issues mentioned below). The AIA spec indicates that implementations can determine which bits of 13-63 in mvien are writable, so let's just make it bits 15-63 to match the main spec. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3133 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3134 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3135 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3138 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3140 Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260513051841.1671987-1-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static RISCVException write_stimecmph(CPURISCVState *env, int csrno, #define VSTOPI_NUM_SRCS 5 /* - * All core local interrupts except the fixed ones 0:12. This macro is for + * All core local interrupts except the fixed ones 0:15. This macro is for * virtual interrupts logic so please don't change this to avoid messing up * the whole support, For reference see AIA spec: `5.3 Interrupt filtering and * virtual interrupts for supervisor level` and `6.3.2 Virtual interrupts for * VS level`. */ -#define LOCAL_INTERRUPTS (~0x1FFFULL) +#define LOCAL_INTERRUPTS (~0xFFFFULL) static const uint64_t delegable_ints = S_MODE_INTERRUPTS | VS_MODE_INTERRUPTS | MIP_LCOFIP; -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> Currently, the `mseccfg` CSR is only cleared to 0 during reset if the `ext_smepmp` is enabled. However, this register is now shared by several other extensions such as `zkr`, `smmpm`, and `zicfilp`. Fix by clearing `mseccfg` if any dependent extension is present, and adjusting the relevant comments. This vulnerability was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-svvptc/pr-134/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260512052240.330815-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) /* * Clear mseccfg and unlock all the PMP entries upon reset. - * This is allowed as per the priv and smepmp specifications - * and is needed to clear stale entries across reboots. + * This is required as per the priv, smepmp, and other security + * extension specifications that share this CSR, and is needed + * to clear stale entries across reboots. */ - if (riscv_cpu_cfg(env)->ext_smepmp) { + if (riscv_cpu_cfg(env)->ext_smepmp || + riscv_cpu_cfg(env)->ext_zkr || + riscv_cpu_cfg(env)->ext_smmpm || + riscv_cpu_cfg(env)->ext_zicfilp) { env->mseccfg = 0; } -- 2.53.0
From: Zongmin Zhou <zhouzongmin@kylinos.cn> When the Zicbop extension is available expose it to the KVM guest. Also read and validate cbop_blocksize from the host via KVM interface. Signed-off-by: Zongmin Zhou <zhouzongmin@kylinos.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <9e388aa9984ea9d3d0c85e1630c9195023938952.1778653159.git.zhouzongmin@kylinos.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -XXX,XX +XXX,XX @@ static void kvm_cpu_csr_set_u64(RISCVCPU *cpu, KVMCPUConfig *csr_cfg, static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zicbom", ext_zicbom, KVM_RISCV_ISA_EXT_ZICBOM), + KVM_EXT_CFG("zicbop", ext_zicbop, KVM_RISCV_ISA_EXT_ZICBOP), KVM_EXT_CFG("zicboz", ext_zicboz, KVM_RISCV_ISA_EXT_ZICBOZ), KVM_EXT_CFG("ziccrse", ext_ziccrse, KVM_RISCV_ISA_EXT_ZICCRSE), KVM_EXT_CFG("zicntr", ext_zicntr, KVM_RISCV_ISA_EXT_ZICNTR), @@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_cboz_blocksize = { .kvm_reg_id = KVM_REG_RISCV_CONFIG_REG(zicboz_block_size) }; +static KVMCPUConfig kvm_cbop_blocksize = { + .name = "cbop_blocksize", + .offset = CPU_CFG_OFFSET(cbop_blocksize), + .kvm_reg_id = KVM_REG_RISCV_CONFIG_REG(zicbop_block_size) +}; + static KVMCPUConfig kvm_v_vlenb = { .name = "vlenb", .offset = CPU_CFG_OFFSET(vlenb), @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_init_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cbom_blocksize); } + if (cpu->cfg.ext_zicbop) { + kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cbop_blocksize); + } + if (cpu->cfg.ext_zicboz) { kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cboz_blocksize); } @@ -XXX,XX +XXX,XX @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp) int ret; /* short-circuit without spinning the scratch CPU */ - if (!cpu->cfg.ext_zicbom && !cpu->cfg.ext_zicboz && - !riscv_has_ext(env, RVV)) { + if (!cpu->cfg.ext_zicbom && !cpu->cfg.ext_zicbop && + !cpu->cfg.ext_zicboz && !riscv_has_ext(env, RVV)) { return; } @@ -XXX,XX +XXX,XX @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp) } } + if (cpu->cfg.ext_zicbop && + riscv_cpu_option_set(kvm_cbop_blocksize.name)) { + + reg.id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CONFIG, + kvm_cbop_blocksize.kvm_reg_id); + reg.addr = (uint64_t)&val; + ret = ioctl(kvmcpu.cpufd, KVM_GET_ONE_REG, ®); + if (ret != 0) { + error_setg_errno(errp, errno, "Unable to read cbop_blocksize"); + return; + } + + if (cpu->cfg.cbop_blocksize != val) { + error_setg(errp, "Unable to set cbop_blocksize to a different " + "value than the host (%lu)", val); + return; + } + } + /* Users are setting vlen, not vlenb */ if (riscv_has_ext(env, RVV) && riscv_cpu_option_set("vlen")) { if (!kvm_v_vlenb.supported) { -- 2.53.0
From: Zongmin Zhou <zhouzongmin@kylinos.cn> Expose the BFloat16 extensions (Zfbfmin, Zvfbfmin, Zvfbfwma) to KVM guests when available in hardware. Signed-off-by: Zongmin Zhou <zhouzongmin@kylinos.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <1258febb0eeb4ee286eb88f70b077a7f1ece507f.1778653159.git.zhouzongmin@kylinos.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zacas", ext_zacas, KVM_RISCV_ISA_EXT_ZACAS), KVM_EXT_CFG("zawrs", ext_zawrs, KVM_RISCV_ISA_EXT_ZAWRS), KVM_EXT_CFG("zfa", ext_zfa, KVM_RISCV_ISA_EXT_ZFA), + KVM_EXT_CFG("zfbfmin", ext_zfbfmin, KVM_RISCV_ISA_EXT_ZFBFMIN), KVM_EXT_CFG("zfh", ext_zfh, KVM_RISCV_ISA_EXT_ZFH), KVM_EXT_CFG("zfhmin", ext_zfhmin, KVM_RISCV_ISA_EXT_ZFHMIN), KVM_EXT_CFG("zba", ext_zba, KVM_RISCV_ISA_EXT_ZBA), @@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zvbc", ext_zvbc, KVM_RISCV_ISA_EXT_ZVBC), KVM_EXT_CFG("zvfh", ext_zvfh, KVM_RISCV_ISA_EXT_ZVFH), KVM_EXT_CFG("zvfhmin", ext_zvfhmin, KVM_RISCV_ISA_EXT_ZVFHMIN), + KVM_EXT_CFG("zvfbfmin", ext_zvfbfmin, KVM_RISCV_ISA_EXT_ZVFBFMIN), + KVM_EXT_CFG("zvfbfwma", ext_zvfbfwma, KVM_RISCV_ISA_EXT_ZVFBFWMA), KVM_EXT_CFG("zvkb", ext_zvkb, KVM_RISCV_ISA_EXT_ZVKB), KVM_EXT_CFG("zvkg", ext_zvkg, KVM_RISCV_ISA_EXT_ZVKG), KVM_EXT_CFG("zvkned", ext_zvkned, KVM_RISCV_ISA_EXT_ZVKNED), -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> Fix a mode-to-capability comparison error in riscv_iommu_validate_device_ctx. The code was comparing fsc_mode (a value) against a capability bitmask, making the SV32 support check ineffective. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-iommu/pr-694/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260511080904.3049446-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static bool riscv_iommu_validate_device_ctx(RISCVIOMMUState *s, } if (ctx->tc & RISCV_IOMMU_DC_TC_SXL) { - if (fsc_mode == RISCV_IOMMU_CAP_SV32 && + if (fsc_mode == RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 && !(s->cap & RISCV_IOMMU_CAP_SV32)) { return false; } -- 2.53.0
From: Chengbo Gao <gaochengbo@bosc.ac.cn> PCI bus numbers may still be unassigned when QEMU initializes a PCI device's bus-master address space. For devices behind bridges, pci_bus_num() can return 0 at that point because the guest has not yet programmed the bridge Secondary Bus Number register. The RISC-V IOMMU currently stores a fixed device_id in RISCVIOMMUSpace when the address space is created. If the guest later enumerates the device on a non-zero bus, DMA translation still uses the stale device_id and may look up the wrong device context in the DDT. Store the stable PCIBus pointer and devfn in RISCVIOMMUSpace instead, and compute the device_id from the current bus number when it is needed. This keeps DMA translation and ATS invalidation in sync with guest PCI bus enumeration. Signed-off-by: Chengbo Gao <gaochengbo@bosc.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260514020637.2819308-1-gaochengbo@bosc.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ struct RISCVIOMMUSpace { IOMMUMemoryRegion iova_mr; /* IOVA memory region for attached device */ AddressSpace iova_as; /* IOVA address space for attached device */ RISCVIOMMUState *iommu; /* Managing IOMMU device state */ - uint32_t devid; /* Requester identifier, AKA device_id */ + PCIBus *bus; /* PCI bus of the requester */ + uint8_t devfn; /* Requester identifier, AKA device_id */ bool notifier; /* IOMMU unmap notifier enabled */ QLIST_ENTRY(RISCVIOMMUSpace) list; }; @@ -XXX,XX +XXX,XX @@ struct RISCVIOMMUEntry { /* IOMMU index for transactions without process_id specified. */ #define RISCV_IOMMU_NOPROCID 0 +static uint32_t riscv_iommu_space_devid(RISCVIOMMUSpace *as) +{ + uint32_t devid = PCI_BUILD_BDF(pci_bus_num(as->bus), as->devfn); + + /* FIXME: PCIe bus remapping for attached endpoints. */ + devid |= as->iommu->bus << 8; + return devid; +} + static uint8_t riscv_iommu_get_icvec_vector(uint32_t icvec, uint32_t vec_type) { switch (vec_type) { @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_ctx_put(RISCVIOMMUState *s, void *ref) } /* Find or allocate address space for a given device */ -static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid) +static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, PCIBus *bus, + int devfn) { RISCVIOMMUSpace *as; - /* FIXME: PCIe bus remapping for attached endpoints. */ - devid |= s->bus << 8; - QLIST_FOREACH(as, &s->spaces, list) { - if (as->devid == devid) { + if (as->bus == bus && as->devfn == devfn) { break; } } @@ -XXX,XX +XXX,XX @@ static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid) as = g_new0(RISCVIOMMUSpace, 1); as->iommu = s; - as->devid = devid; + as->bus = bus; + as->devfn = devfn; snprintf(name, sizeof(name), "riscv-iommu-%04x:%02x.%d-iova", - PCI_BUS_NUM(as->devid), PCI_SLOT(as->devid), PCI_FUNC(as->devid)); + pci_bus_num(bus), PCI_SLOT(devfn), PCI_FUNC(devfn)); /* IOVA address space, untranslated addresses */ memory_region_init_iommu(&as->iova_mr, sizeof(as->iova_mr), @@ -XXX,XX +XXX,XX @@ static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid) QLIST_INSERT_HEAD(&s->spaces, as, list); - trace_riscv_iommu_new(s->parent_obj.id, PCI_BUS_NUM(as->devid), - PCI_SLOT(as->devid), PCI_FUNC(as->devid)); + trace_riscv_iommu_new(s->parent_obj.id, pci_bus_num(bus), + PCI_SLOT(devfn), PCI_FUNC(devfn)); } return &as->iova_as; } @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_ats(RISCVIOMMUState *s, pid = get_field(cmd->dword0, RISCV_IOMMU_CMD_ATS_PID); QLIST_FOREACH(as, &s->spaces, list) { - if (as->devid == devid) { + if (riscv_iommu_space_devid(as) == devid) { break; } } @@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry riscv_iommu_memory_region_translate( .addr_mask = ~0ULL, .perm = flag, }; + uint32_t devid = riscv_iommu_space_devid(as); - ctx = riscv_iommu_ctx(as->iommu, as->devid, iommu_idx, &ref); + ctx = riscv_iommu_ctx(as->iommu, devid, iommu_idx, &ref); if (ctx == NULL) { /* Translation disabled or invalid. */ iotlb.addr_mask = 0; @@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry riscv_iommu_memory_region_translate( } /* Trace all dma translations with original access flags. */ - trace_riscv_iommu_dma(as->iommu->parent_obj.id, PCI_BUS_NUM(as->devid), - PCI_SLOT(as->devid), PCI_FUNC(as->devid), iommu_idx, + trace_riscv_iommu_dma(as->iommu->parent_obj.id, PCI_BUS_NUM(devid), + PCI_SLOT(devid), PCI_FUNC(devid), iommu_idx, IOMMU_FLAG_STR[flag & IOMMU_RW], iotlb.iova, iotlb.translated_addr); @@ -XXX,XX +XXX,XX @@ static AddressSpace *riscv_iommu_find_as(PCIBus *bus, void *opaque, int devfn) /* Find first matching IOMMU */ while (s != NULL && as == NULL) { - as = riscv_iommu_space(s, PCI_BUILD_BDF(pci_bus_num(bus), devfn)); + as = riscv_iommu_space(s, bus, devfn); s = s->iommus.le_next; } -- 2.53.0
From: Guenter Roeck <linux@roeck-us.net> Minimal clock register configuration required to boot Linux without backtraces in the clock code. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Conor Dooley <conor.dooley@microchip.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260514-reference-overhand-749149e36a88@spud> [ Changes by AF: - Fixup checkpatch errors ] Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- include/hw/misc/mchp_pfsoc_ioscb.h | 2 ++ hw/misc/mchp_pfsoc_ioscb.c | 47 +++++++++++++++++++++++++++++- hw/misc/mchp_pfsoc_sysreg.c | 13 +++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/include/hw/misc/mchp_pfsoc_ioscb.h b/include/hw/misc/mchp_pfsoc_ioscb.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/misc/mchp_pfsoc_ioscb.h +++ b/include/hw/misc/mchp_pfsoc_ioscb.h @@ -XXX,XX +XXX,XX @@ typedef struct MchpPfSoCIoscbState { MemoryRegion mailbox; MemoryRegion cfg; MemoryRegion ccc; + MemoryRegion pll_nw_0; + MemoryRegion pll_nw_1; MemoryRegion pll_mss; MemoryRegion cfm_mss; MemoryRegion pll_ddr; diff --git a/hw/misc/mchp_pfsoc_ioscb.c b/hw/misc/mchp_pfsoc_ioscb.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/mchp_pfsoc_ioscb.c +++ b/hw/misc/mchp_pfsoc_ioscb.c @@ -XXX,XX +XXX,XX @@ #define IOSCB_MAILBOX_BASE 0x07020800 #define IOSCB_CFG_BASE 0x07080000 #define IOSCB_CCC_BASE 0x08000000 +#define IOSCB_PLL_NW0_BASE 0x08100000 +#define IOSCB_PLL_NW1_BASE 0x08200000 #define IOSCB_PLL_MSS_BASE 0x0E001000 #define IOSCB_CFM_MSS_BASE 0x0E002000 #define IOSCB_PLL_DDR_BASE 0x0E010000 @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps mchp_pfsoc_dummy_ops = { /* All PLL modules in IOSCB have the same register layout */ #define PLL_CTRL 0x04 +#define PLL_REF_FB 0x08 +#define PLL_DIV_0_1 0x10 +#define PLL_DIV_2_3 0x14 +#define PLL_CTRL2 0x18 +#define PLL_CAL 0x1c +#define PLL_PHADJ 0x20 +#define SSCG_REG_0 0x24 +#define SSCG_REG_1 0x28 +#define SSCG_REG_2 0x2c +#define SSCG_REG_3 0x30 static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset, unsigned size) @@ -XXX,XX +XXX,XX @@ static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset, /* PLL is locked */ val = BIT(25); break; + case PLL_DIV_0_1: + case PLL_DIV_2_3: + val = 0x01000100; /* return valid post divider values */ + break; + case PLL_CTRL2: + val = 0x00001110; + break; + case PLL_REF_FB: + val = 0x00000100; /* RFDIV := 1 */ + break; + case SSCG_REG_2: + val = 0x00000001; /* INTIN := 1 */ + break; + case PLL_PHADJ: + val = 0x00000401; + break; default: qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " "(size %d, offset 0x%" HWADDR_PRIx ")\n", @@ -XXX,XX +XXX,XX @@ static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset, return val; } +static void mchp_pfsoc_pll_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " + "(size %d, value 0x%" PRIx64 + ", offset 0x%" HWADDR_PRIx ")\n", + __func__, size, value, offset); +} + static const MemoryRegionOps mchp_pfsoc_pll_ops = { .read = mchp_pfsoc_pll_read, - .write = mchp_pfsoc_dummy_write, + .write = mchp_pfsoc_pll_write, .endianness = DEVICE_LITTLE_ENDIAN, }; @@ -XXX,XX +XXX,XX @@ static void mchp_pfsoc_ioscb_realize(DeviceState *dev, Error **errp) "mchp.pfsoc.ioscb.ccc", IOSCB_CCC_REG_SIZE); memory_region_add_subregion(&s->container, IOSCB_CCC_BASE, &s->ccc); + memory_region_init_io(&s->pll_nw_0, OBJECT(s), &mchp_pfsoc_pll_ops, s, + "mchp.pfsoc.ioscb.pll_nw_0", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_PLL_NW0_BASE, &s->pll_nw_0); + + memory_region_init_io(&s->pll_nw_1, OBJECT(s), &mchp_pfsoc_pll_ops, s, + "mchp.pfsoc.ioscb.pll_nw_1", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_PLL_NW1_BASE, &s->pll_nw_1); + memory_region_init_io(&s->pll_mss, OBJECT(s), &mchp_pfsoc_pll_ops, s, "mchp.pfsoc.ioscb.pll_mss", IOSCB_SUBMOD_REG_SIZE); memory_region_add_subregion(&s->container, IOSCB_PLL_MSS_BASE, &s->pll_mss); diff --git a/hw/misc/mchp_pfsoc_sysreg.c b/hw/misc/mchp_pfsoc_sysreg.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/mchp_pfsoc_sysreg.c +++ b/hw/misc/mchp_pfsoc_sysreg.c @@ -XXX,XX +XXX,XX @@ #include "hw/misc/mchp_pfsoc_sysreg.h" #include "system/runstate.h" +#define CLOCK_CONFIG_CR 0x8 +#define RTC_CLOCK_CR 0xc #define MSS_RESET_CR 0x18 #define ENVM_CR 0xb8 #define MESSAGE_INT 0x118c @@ -XXX,XX +XXX,XX @@ static uint64_t mchp_pfsoc_sysreg_read(void *opaque, hwaddr offset, uint32_t val = 0; switch (offset) { + case CLOCK_CONFIG_CR: + /* Icicle kit reference design cpu/axi/ahb divider setting */ + val = 0x24; + break; + case RTC_CLOCK_CR: + /* + * Bit 16 enables the RTC clock, 0x7d is the required divider + * setting for a 125 MHz reference. + */ + val = BIT(16) | 0x7d; + break; case ENVM_CR: /* Indicate the eNVM is running at the configured divider rate */ val = BIT(6); -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The entry was missing from isa_edata_arr[]. Fixes: 32bbab666 ("target/riscv: add draft RISC-V Zbr ext as xbr0p93") Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-2-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(svrsw60t59b, PRIV_VERSION_1_13_0, ext_svrsw60t59b), ISA_EXT_DATA_ENTRY(svukte, PRIV_VERSION_1_13_0, ext_svukte), ISA_EXT_DATA_ENTRY(svvptc, PRIV_VERSION_1_13_0, ext_svvptc), + ISA_EXT_DATA_ENTRY(xlrbr, PRIV_VERSION_1_13_0, ext_xlrbr), ISA_EXT_DATA_ENTRY(xmipscbop, PRIV_VERSION_1_12_0, ext_xmipscbop), ISA_EXT_DATA_ENTRY(xmipscmov, PRIV_VERSION_1_12_0, ext_xmipscmov), ISA_EXT_DATA_ENTRY(xmipslsp, PRIV_VERSION_1_12_0, ext_xmipslsp), -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Noticed when realizing that 'svadu' was too far apart from 'svade'. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-3-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(smcdeleg, PRIV_VERSION_1_13_0, ext_smcdeleg), ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf), ISA_EXT_DATA_ENTRY(smcsrind, PRIV_VERSION_1_13_0, ext_smcsrind), + ISA_EXT_DATA_ENTRY(smctr, PRIV_VERSION_1_12_0, ext_smctr), ISA_EXT_DATA_ENTRY(smdbltrp, PRIV_VERSION_1_13_0, ext_smdbltrp), ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp), ISA_EXT_DATA_ENTRY(smpmpmt, PRIV_VERSION_1_12_0, ext_smpmpmt), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf), ISA_EXT_DATA_ENTRY(sscounterenw, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(sscsrind, PRIV_VERSION_1_12_0, ext_sscsrind), + ISA_EXT_DATA_ENTRY(ssctr, PRIV_VERSION_1_12_0, ext_ssctr), ISA_EXT_DATA_ENTRY(ssdbltrp, PRIV_VERSION_1_13_0, ext_ssdbltrp), ISA_EXT_DATA_ENTRY(ssnpm, PRIV_VERSION_1_13_0, ext_ssnpm), ISA_EXT_DATA_ENTRY(sspm, PRIV_VERSION_1_13_0, ext_sspm), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(ssu64xl, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(supm, PRIV_VERSION_1_13_0, ext_supm), ISA_EXT_DATA_ENTRY(svade, PRIV_VERSION_1_11_0, ext_svade), - ISA_EXT_DATA_ENTRY(smctr, PRIV_VERSION_1_12_0, ext_smctr), - ISA_EXT_DATA_ENTRY(ssctr, PRIV_VERSION_1_12_0, ext_ssctr), ISA_EXT_DATA_ENTRY(svadu, PRIV_VERSION_1_12_0, ext_svadu), ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval), ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot), -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We want to reduce the usage of the riscv_cpu_* arrays in target/riscv/cpu.c, centering everything in isa_edata_arr[] instead, to reduce data duplication and make our lives a bit easier when adding new extensions. To do that we'll have to make isa_edata_arr[] do what the other arrays are currently doing, not breaking existing semantics in the process. The riscv_cpu_* arrays have a few exclusive uses: - set default extensions for rv32 and rv64; - create user CPU properties; - misc uses around tcg-cpu.c and kvm-cpu.c. We'll slowly make isa_edata_arr[] supersede these arrays. Start by adding a new 'prop_name' field in RISCVIsaExtData. This field is needed because not all extensions have properties and not all properties match the riscv,isa string name. Create two additional macros and reclassify existing isa_edata_arr[] entries as follows: - ISA_EXT_DATA_ENTRY creates an entry where prop_name == riscv,isa. Most of our regular extensions fall into this category; - ISA_EXPERIMENTAL_EXT_DATA_ENTRY: same as above but add a "x-" to the prop name, i.e. prop_name == "x-" + riscv,isa; - ISA_INTERNAL_EXT_DATA_ENTRY: used to declared internal extensions. By 'internal' we mean users/management can't set them on or off. With these new macros we can start our simplification by changing riscv-qmp-cmds to use isa_edata_arr[]. We'll just scroll through it once and gather what we need. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-4-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 + target/riscv/cpu.c | 60 +++++++++++++++++++++++------------ target/riscv/riscv-qmp-cmds.c | 30 ++++-------------- 3 files changed, 47 insertions(+), 44 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ extern const RISCVCPUMultiExtConfig riscv_cpu_named_features[]; typedef struct isa_ext_data { const char *name; + const char *prop_name; int min_version; int ext_enable_offset; } RISCVIsaExtData; diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_cfg_merge(RISCVCPUConfig *dest, const RISCVCPUConfig *src) #include "cpu_cfg_fields.h.inc" } +/* Use this for regular user facing extensions */ #define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \ - {#_name, _min_ver, CPU_CFG_OFFSET(_prop)} + {#_name, #_name, _min_ver, CPU_CFG_OFFSET(_prop)} + +/* + * Same as above but for experimental extensions. We'll add a + * "x-" right after "_name" when creating the user property. + */ +#define ISA_EXPERIMENTAL_EXT_DATA_ENTRY(_name, _min_ver, _prop) \ + {#_name, "x-" #_name, _min_ver, CPU_CFG_OFFSET(_prop)} + +/* + * Internal extensions are extensions we will declare in the + * riscv,isa DT but they don't have an user property, i.e. + * users/management can't enable/disable them. + */ +#define ISA_INTERNAL_EXT_DATA_ENTRY(_name, _min_ver, _prop) \ + {#_name, NULL, _min_ver, CPU_CFG_OFFSET(_prop)} /* * Here are the ordering rules of extension naming defined by RISC-V @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_cfg_merge(RISCVCPUConfig *dest, const RISCVCPUConfig *src) * instead. */ const RISCVIsaExtData isa_edata_arr[] = { - ISA_EXT_DATA_ENTRY(zic64b, PRIV_VERSION_1_12_0, ext_zic64b), + ISA_INTERNAL_EXT_DATA_ENTRY(zic64b, PRIV_VERSION_1_12_0, ext_zic64b), ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_zicbom), ISA_EXT_DATA_ENTRY(zicbop, PRIV_VERSION_1_12_0, ext_zicbop), ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_zicboz), - ISA_EXT_DATA_ENTRY(ziccamoa, PRIV_VERSION_1_11_0, has_priv_1_11), - ISA_EXT_DATA_ENTRY(ziccif, PRIV_VERSION_1_11_0, has_priv_1_11), - ISA_EXT_DATA_ENTRY(zicclsm, PRIV_VERSION_1_11_0, has_priv_1_11), + ISA_INTERNAL_EXT_DATA_ENTRY(ziccamoa, PRIV_VERSION_1_11_0, has_priv_1_11), + ISA_INTERNAL_EXT_DATA_ENTRY(ziccif, PRIV_VERSION_1_11_0, has_priv_1_11), + ISA_INTERNAL_EXT_DATA_ENTRY(zicclsm, PRIV_VERSION_1_11_0, has_priv_1_11), ISA_EXT_DATA_ENTRY(ziccrse, PRIV_VERSION_1_11_0, ext_ziccrse), ISA_EXT_DATA_ENTRY(zicfilp, PRIV_VERSION_1_12_0, ext_zicfilp), ISA_EXT_DATA_ENTRY(zicfiss, PRIV_VERSION_1_13_0, ext_zicfiss), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zilsd, PRIV_VERSION_1_12_0, ext_zilsd), ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_13_0, ext_zimop), ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul), - ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo), ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha), ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx), ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin), ISA_EXT_DATA_ENTRY(sdtrig, PRIV_VERSION_1_12_0, debug), - ISA_EXT_DATA_ENTRY(shcounterenw, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(sha, PRIV_VERSION_1_12_0, ext_sha), - ISA_EXT_DATA_ENTRY(shgatpa, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(shtvala, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(shvsatpa, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(shvstvala, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(shvstvecd, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(shcounterenw, PRIV_VERSION_1_12_0, + has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(sha, PRIV_VERSION_1_12_0, ext_sha), + ISA_INTERNAL_EXT_DATA_ENTRY(shgatpa, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(shtvala, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(shvsatpa, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(shvstvala, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(shvstvecd, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia), ISA_EXT_DATA_ENTRY(smcdeleg, PRIV_VERSION_1_13_0, ext_smcdeleg), ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen), ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia), ISA_EXT_DATA_ENTRY(ssccfg, PRIV_VERSION_1_13_0, ext_ssccfg), - ISA_EXT_DATA_ENTRY(ssccptr, PRIV_VERSION_1_11_0, has_priv_1_11), + ISA_INTERNAL_EXT_DATA_ENTRY(ssccptr, PRIV_VERSION_1_11_0, has_priv_1_11), ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf), - ISA_EXT_DATA_ENTRY(sscounterenw, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(sscounterenw, PRIV_VERSION_1_12_0, + has_priv_1_12), ISA_EXT_DATA_ENTRY(sscsrind, PRIV_VERSION_1_12_0, ext_sscsrind), ISA_EXT_DATA_ENTRY(ssctr, PRIV_VERSION_1_12_0, ext_ssctr), ISA_EXT_DATA_ENTRY(ssdbltrp, PRIV_VERSION_1_13_0, ext_ssdbltrp), ISA_EXT_DATA_ENTRY(ssnpm, PRIV_VERSION_1_13_0, ext_ssnpm), ISA_EXT_DATA_ENTRY(sspm, PRIV_VERSION_1_13_0, ext_sspm), - ISA_EXT_DATA_ENTRY(ssstateen, PRIV_VERSION_1_12_0, ext_ssstateen), - ISA_EXT_DATA_ENTRY(ssstrict, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(ssstateen, PRIV_VERSION_1_12_0, ext_ssstateen), + ISA_INTERNAL_EXT_DATA_ENTRY(ssstrict, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc), - ISA_EXT_DATA_ENTRY(sstvala, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(sstvecd, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(ssu64xl, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(sstvala, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(sstvecd, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(ssu64xl, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(supm, PRIV_VERSION_1_13_0, ext_supm), ISA_EXT_DATA_ENTRY(svade, PRIV_VERSION_1_11_0, ext_svade), ISA_EXT_DATA_ENTRY(svadu, PRIV_VERSION_1_12_0, ext_svadu), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot), ISA_EXT_DATA_ENTRY(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt), ISA_EXT_DATA_ENTRY(svrsw60t59b, PRIV_VERSION_1_13_0, ext_svrsw60t59b), - ISA_EXT_DATA_ENTRY(svukte, PRIV_VERSION_1_13_0, ext_svukte), + ISA_EXPERIMENTAL_EXT_DATA_ENTRY(svukte, PRIV_VERSION_1_13_0, ext_svukte), ISA_EXT_DATA_ENTRY(svvptc, PRIV_VERSION_1_13_0, ext_svvptc), ISA_EXT_DATA_ENTRY(xlrbr, PRIV_VERSION_1_13_0, ext_xlrbr), ISA_EXT_DATA_ENTRY(xmipscbop, PRIV_VERSION_1_12_0, ext_xmipscbop), diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/riscv-qmp-cmds.c +++ b/target/riscv/riscv-qmp-cmds.c @@ -XXX,XX +XXX,XX @@ static void riscv_obj_add_qdict_prop(Object *obj, QDict *qdict_out, } } -static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out, - const RISCVCPUMultiExtConfig *arr) +static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out) { - for (int i = 0; arr[i].name != NULL; i++) { - riscv_obj_add_qdict_prop(obj, qdict_out, arr[i].name); - } -} + const RISCVIsaExtData *edata; -static void riscv_obj_add_named_feats_qdict(Object *obj, QDict *qdict_out) -{ - const RISCVCPUMultiExtConfig *named_cfg; - RISCVCPU *cpu = RISCV_CPU(obj); - QObject *value; - bool flag_val; - - for (int i = 0; riscv_cpu_named_features[i].name != NULL; i++) { - named_cfg = &riscv_cpu_named_features[i]; - flag_val = isa_ext_is_enabled(cpu, named_cfg->offset); - value = QOBJECT(qbool_from_bool(flag_val)); - - qdict_put_obj(qdict_out, named_cfg->name, value); + for (edata = isa_edata_arr; edata && edata->name; edata++) { + if (edata->prop_name) { + riscv_obj_add_qdict_prop(obj, qdict_out, edata->prop_name); + } } } @@ -XXX,XX +XXX,XX @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, qdict_out = qdict_new(); - riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_extensions); - riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_experimental_exts); - riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_vendor_exts); - riscv_obj_add_named_feats_qdict(obj, qdict_out); + riscv_obj_add_multiext_props(obj, qdict_out); riscv_obj_add_profiles_qdict(obj, qdict_out); /* Add our CPU boolean options too */ -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Commit 7e4f75cadf ("target/riscv/tcg: hide warn for named feats when disabling via priv_ver") changed the design of disable_priv_spec_isa_exts to not warn when disabling what we were calling "named features" at that time. Back in that time we were adding RVA22 profile support and we were dealing with a RVI innovation: named features. These can be define as cute names for pre-existing behavior/parameters, e.g. 'zic64b' means all cache blocks must have 64 bytes. They do get inserted in the riscv,isa but they are not "real" extensions because users shouldn't be setting them in the command line, or so we thought back then, and we attempted to model that by calling it "named features". This didn't age that well: ziccrse is a so called named feature as far as TCG goes, but then KVM had to treat it as a regular extension that can be user set and we made an exception: ziccrse is a named feature that is user set by KVM. "Named features" are regular extensions that might or might not be user set, and might or might not warrant special handling during realize() by setting other parameters. And we'll being treating them as such, which will culminate in the end of riscv_cpu_named_features[] array in the end. This reverts commit 7e4f75cadf44ee67809c7ca82645a289a5268966. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-5-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) } isa_ext_update_enabled(cpu, edata->ext_enable_offset, false); - - /* - * Do not show user warnings for named features that users - * can't enable/disable in the command line. See commit - * 68c9e54bea for more info. - */ - if (cpu_cfg_offset_is_named_feat(edata->ext_enable_offset)) { - continue; - } #ifndef CONFIG_USER_ONLY warn_report("disabling %s extension for hart 0x%" PRIx64 " because privilege spec version does not match", @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_update_named_features(RISCVCPU *cpu) cpu->cfg.has_priv_1_13 = true; } + /* zic64b is 1.12 or later */ cpu->cfg.ext_zic64b = cpu->cfg.cbom_blocksize == 64 && cpu->cfg.cbop_blocksize == 64 && - cpu->cfg.cboz_blocksize == 64; + cpu->cfg.cboz_blocksize == 64 && + cpu->cfg.has_priv_1_12; cpu->cfg.ext_ssstateen = cpu->cfg.ext_smstateen; -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We're using both isa_edata_arr[] and riscv_cpu_named_features[] to find an extension name based on a cfg offset. This is reminiscent of a past where isa_edata_arr[] didn't include entries for internal extensions. At this point we can use just isa_edata_arr[]. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-6-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset) static const char *cpu_cfg_ext_get_name(uint32_t ext_offset) { - const RISCVCPUMultiExtConfig *feat; const RISCVIsaExtData *edata; for (edata = isa_edata_arr; edata->name != NULL; edata++) { @@ -XXX,XX +XXX,XX @@ static const char *cpu_cfg_ext_get_name(uint32_t ext_offset) } } - for (feat = riscv_cpu_named_features; feat->name != NULL; feat++) { - if (feat->offset == ext_offset) { - return feat->name; - } - } - g_assert_not_reached(); } -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Deprecate riscv_cpu_enable_named_feat() by creating implied rules for 'sha' and 'ssstateen'. 'zic64' is always true given that our default block size is set to 64. With this change we homogeneize extension handling when enabling profiles. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-7-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 25 ++++++++++++++++++++++-- target/riscv/tcg/tcg-cpu.c | 40 -------------------------------------- 2 files changed, 23 insertions(+), 42 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static RISCVCPUImpliedExtsRule ZVKSG_IMPLIED = { }, }; +static RISCVCPUImpliedExtsRule SHA_IMPLIED = { + .ext = CPU_CFG_OFFSET(ext_sha), + .implied_misa_exts = RVH, + .implied_multi_exts = { + CPU_CFG_OFFSET(ext_smstateen), + CPU_CFG_OFFSET(ext_ssstateen), + + RISCV_IMPLIED_EXTS_RULE_END + }, +}; + static RISCVCPUImpliedExtsRule SSCFG_IMPLIED = { .ext = CPU_CFG_OFFSET(ext_ssccfg), .implied_multi_exts = { @@ -XXX,XX +XXX,XX @@ static RISCVCPUImpliedExtsRule SSCTR_IMPLIED = { }, }; +static RISCVCPUImpliedExtsRule SSSTATEEN_IMPLIED = { + .ext = CPU_CFG_OFFSET(ext_ssstateen), + .implied_multi_exts = { + CPU_CFG_OFFSET(ext_smstateen), + + RISCV_IMPLIED_EXTS_RULE_END + }, +}; + static RISCVCPUImpliedExtsRule ZVFBFA_IMPLIED = { .ext = CPU_CFG_OFFSET(ext_zvfbfa), .implied_multi_exts = { @@ -XXX,XX +XXX,XX @@ RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[] = { &ZVFBFA_IMPLIED, &ZVFBFMIN_IMPLIED, &ZVFBFWMA_IMPLIED, &ZVFH_IMPLIED, &ZVFHMIN_IMPLIED, &ZVKN_IMPLIED, &ZVKNC_IMPLIED, &ZVKNG_IMPLIED, &ZVKNHB_IMPLIED, - &ZVKS_IMPLIED, &ZVKSC_IMPLIED, &ZVKSG_IMPLIED, &SSCFG_IMPLIED, - &SUPM_IMPLIED, &SSPM_IMPLIED, &SMCTR_IMPLIED, &SSCTR_IMPLIED, + &ZVKS_IMPLIED, &ZVKSC_IMPLIED, &ZVKSG_IMPLIED, &SHA_IMPLIED, + &SSCFG_IMPLIED, &SUPM_IMPLIED, &SSPM_IMPLIED, &SMCTR_IMPLIED, + &SSCTR_IMPLIED, &SSSTATEEN_IMPLIED, NULL }; diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static const char *cpu_cfg_ext_get_name(uint32_t ext_offset) g_assert_not_reached(); } -static bool cpu_cfg_offset_is_named_feat(uint32_t ext_offset) -{ - const RISCVCPUMultiExtConfig *feat; - - for (feat = riscv_cpu_named_features; feat->name != NULL; feat++) { - if (feat->offset == ext_offset) { - return true; - } - } - - return false; -} - -static void riscv_cpu_enable_named_feat(RISCVCPU *cpu, uint32_t feat_offset) -{ - /* - * All other named features are already enabled - * in riscv_tcg_cpu_instance_init(). - */ - switch (feat_offset) { - case CPU_CFG_OFFSET(ext_zic64b): - cpu->cfg.cbom_blocksize = 64; - cpu->cfg.cbop_blocksize = 64; - cpu->cfg.cboz_blocksize = 64; - break; - case CPU_CFG_OFFSET(ext_sha): - if (!cpu_misa_ext_is_user_set(RVH)) { - riscv_cpu_write_misa_bit(cpu, RVH, true); - } - /* fallthrough */ - case CPU_CFG_OFFSET(ext_ssstateen): - cpu->cfg.ext_smstateen = true; - break; - } -} - static void cpu_bump_multi_ext_priv_ver(CPURISCVState *env, uint32_t ext_offset) { @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_set_profile(RISCVCPU *cpu, ext_offset = profile->ext_offsets[i]; if (profile->enabled) { - if (cpu_cfg_offset_is_named_feat(ext_offset)) { - riscv_cpu_enable_named_feat(cpu, ext_offset); - } - cpu_bump_multi_ext_priv_ver(&cpu->env, ext_offset); } -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> This array has no uses left. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-8-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 - target/riscv/cpu.c | 26 -------------------------- target/riscv/tcg/tcg-cpu.c | 4 ++-- 3 files changed, 2 insertions(+), 29 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ typedef struct RISCVCPUMultiExtConfig { extern const RISCVCPUMultiExtConfig riscv_cpu_extensions[]; extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[]; extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[]; -extern const RISCVCPUMultiExtConfig riscv_cpu_named_features[]; typedef struct isa_ext_data { const char *name; diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { { }, }; -/* - * 'Named features' is the name we give to extensions that we - * don't want to expose to users. They are either immutable - * (always enabled/disable) or they'll vary depending on - * the resulting CPU state. - * - * Some of them are always enabled depending on priv version - * of the CPU and are declared directly in isa_edata_arr[]. - * The ones listed here have special checks during finalize() - * time and require their own flags like regular extensions. - * See riscv_cpu_update_named_features() for more info. - */ -const RISCVCPUMultiExtConfig riscv_cpu_named_features[] = { - MULTI_EXT_CFG_BOOL("zic64b", ext_zic64b, true), - MULTI_EXT_CFG_BOOL("ssstateen", ext_ssstateen, true), - MULTI_EXT_CFG_BOOL("sha", ext_sha, true), - - /* - * 'ziccrse' has its own flag because the KVM driver - * wants to enable/disable it on its own accord. - */ - MULTI_EXT_CFG_BOOL("ziccrse", ext_ziccrse, true), - - { }, -}; - static void cpu_set_prop_err(RISCVCPU *cpu, const char *propname, Error **errp) { diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) } } -static void riscv_cpu_update_named_features(RISCVCPU *cpu) +static void riscv_cpu_update_cfg(RISCVCPU *cpu) { if (cpu->env.priv_ver >= PRIV_VERSION_1_11_0) { cpu->cfg.has_priv_1_11 = true; @@ -XXX,XX +XXX,XX @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) return; } - riscv_cpu_update_named_features(cpu); + riscv_cpu_update_cfg(cpu); riscv_cpu_validate_profiles(cpu); if (cpu->cfg.ext_smepmp && !cpu->cfg.pmp) { -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The non-standard extensions, in this particular function the vendor extensions, are all riscv,isa names that starts with 'x'. In theory this is a bit slower than using riscv_cpu_vendor_exts (isa_edata_arr is longer) but riscv_cpu_update_misa_x() is executed only once during finalize(), i.e. not a hot path. We're accepting a tiny performance hit as as a tradeoff for the code simplication we'll have later by removing all riscv_cpu_* arrays. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-9-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_update_misa_c(RISCVCPU *cpu) static void riscv_cpu_update_misa_x(RISCVCPU *cpu) { CPURISCVState *env = &cpu->env; - const RISCVCPUMultiExtConfig *arr = riscv_cpu_vendor_exts; + const RISCVIsaExtData *edata; - for (int i = 0; arr[i].name != NULL; i++) { - if (isa_ext_is_enabled(cpu, arr[i].offset)) { + for (edata = isa_edata_arr; edata && edata->name; edata++) { + if (edata->name[0] == 'x' + && isa_ext_is_enabled(cpu, edata->ext_enable_offset)) { riscv_cpu_set_misa_ext(env, env->misa_ext | RVX); break; } -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Use isa_edata_arr[] directly instead of going through 3 different arrays to populate the unavailable KVM properties. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-10-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) NULL, (void *)prop_name); } -static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj, - const RISCVCPUMultiExtConfig *array) -{ - const RISCVCPUMultiExtConfig *prop; - - g_assert(array); - - for (prop = array; prop && prop->name; prop++) { - riscv_cpu_add_kvm_unavail_prop(obj, prop->name); - } -} - static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj) { + const RISCVIsaExtData *edata; int i; riscv_add_satp_mode_properties(cpu_obj); @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj) NULL, multi_cfg); } - riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_extensions); - riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_vendor_exts); - riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_experimental_exts); + /* + * Mark all isa_edata_arr properties that collides with + * a KVM property as unavailable. + */ + for (edata = isa_edata_arr; edata && edata->name; edata++) { + if (edata->prop_name) { + riscv_cpu_add_kvm_unavail_prop(cpu_obj, edata->prop_name); + } + } /* We don't have the needed KVM support for profiles */ for (i = 0; riscv_profiles[i] != NULL; i++) { -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Use isa_edata_arr[] to enable all feasible extensions. Filter experimental and vendor extensions by checking if the riscv,isa or the prop name starts with 'x'. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-11-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_init_max_cpu_extensions(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); CPURISCVState *env = &cpu->env; - const RISCVCPUMultiExtConfig *prop; + const RISCVIsaExtData *edata; /* Enable RVG and RVV that are disabled by default */ riscv_cpu_set_misa_ext(env, env->misa_ext | RVB | RVG | RVV); - for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { - isa_ext_update_enabled(cpu, prop->offset, true); + for (edata = isa_edata_arr; edata && edata->name; edata++) { + if (edata->name[0] == 'x' + || (edata->prop_name && edata->prop_name[0] == 'x')) { + continue; + } + + isa_ext_update_enabled(cpu, edata->ext_enable_offset, true); } /* -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The cpu_get_multi_ext_cfg/cpu_set_multi_ext_cfg callbacks are using a RISCVCPUMultiExtConfig pointer as opaque, but internally we're just using multi_ext_cfg->offset. Use multi_ext_cfg->offset as opaque instead. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-12-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_add_profiles(Object *cpu_obj) static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque; RISCVCPU *cpu = RISCV_CPU(obj); + uint32_t cfg_offset = *(uint32_t *)opaque; bool vendor_cpu = riscv_cpu_is_vendor(obj); bool prev_val, value; @@ -XXX,XX +XXX,XX @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, return; } - cpu_cfg_ext_add_user_opt(multi_ext_cfg->offset, value); + cpu_cfg_ext_add_user_opt(cfg_offset, value); - prev_val = isa_ext_is_enabled(cpu, multi_ext_cfg->offset); + prev_val = isa_ext_is_enabled(cpu, cfg_offset); if (value == prev_val) { return; @@ -XXX,XX +XXX,XX @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, } if (value) { - cpu_bump_multi_ext_priv_ver(&cpu->env, multi_ext_cfg->offset); + cpu_bump_multi_ext_priv_ver(&cpu->env, cfg_offset); } - isa_ext_update_enabled(cpu, multi_ext_cfg->offset, value); + isa_ext_update_enabled(cpu, cfg_offset, value); } static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque; - bool value = isa_ext_is_enabled(RISCV_CPU(obj), multi_ext_cfg->offset); + uint32_t cfg_offset = *(uint32_t *)opaque; + bool value = isa_ext_is_enabled(RISCV_CPU(obj), cfg_offset); visit_type_bool(v, name, &value, errp); } @@ -XXX,XX +XXX,XX @@ static void cpu_add_multi_ext_prop(Object *cpu_obj, object_property_add(cpu_obj, multi_cfg->name, "bool", cpu_get_multi_ext_cfg, cpu_set_multi_ext_cfg, - NULL, (void *)multi_cfg); + NULL, (void *)&multi_cfg->offset); if (!generic_cpu) { return; -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Do not rely on riscv_cpu_* arrays to set rv32/rv64 CPU defaults - add them to the CPU definition like we do with all other CPUs (aside from 'max'). Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-13-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 40 ++++++++++++++++++++++++++++++++++++++ target/riscv/tcg/tcg-cpu.c | 14 ------------- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE32, TYPE_RISCV_DYNAMIC_CPU, .cfg.max_satp_mode = VM_1_10_SV32, .misa_mxl_max = MXL_RV32, + + /* Default extensions as of QEMU 11.1. */ + .cfg.ext_zicbom = true, + .cfg.ext_zicbop = true, + .cfg.ext_zicboz = true, + .cfg.ext_zicntr = true, + .cfg.ext_zicsr = true, + .cfg.ext_zifencei = true, + .cfg.ext_zihintntl = true, + .cfg.ext_zihintpause = true, + .cfg.ext_zihpm = true, + .cfg.ext_zawrs = true, + .cfg.ext_zfa = true, + .cfg.ext_zba = true, + .cfg.ext_zbb = true, + .cfg.ext_zbc = true, + .cfg.ext_zbs = true, + .cfg.ext_sstc = true, + .cfg.ext_svadu = true, + .cfg.ext_svvptc = true, ), DEFINE_RISCV_CPU(TYPE_RISCV_CPU_IBEX, TYPE_RISCV_VENDOR_CPU, @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE64, TYPE_RISCV_DYNAMIC_CPU, .cfg.max_satp_mode = VM_1_10_SV57, .misa_mxl_max = MXL_RV64, + + /* Default extensions as of QEMU 11.1. */ + .cfg.ext_zicbom = true, + .cfg.ext_zicbop = true, + .cfg.ext_zicboz = true, + .cfg.ext_zicntr = true, + .cfg.ext_zicsr = true, + .cfg.ext_zifencei = true, + .cfg.ext_zihintntl = true, + .cfg.ext_zihintpause = true, + .cfg.ext_zihpm = true, + .cfg.ext_zawrs = true, + .cfg.ext_zfa = true, + .cfg.ext_zba = true, + .cfg.ext_zbb = true, + .cfg.ext_zbc = true, + .cfg.ext_zbs = true, + .cfg.ext_sstc = true, + .cfg.ext_svadu = true, + .cfg.ext_svvptc = true, ), DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E51, TYPE_RISCV_CPU_SIFIVE_E, diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name, static void cpu_add_multi_ext_prop(Object *cpu_obj, const RISCVCPUMultiExtConfig *multi_cfg) { - bool generic_cpu = riscv_cpu_is_generic(cpu_obj); - object_property_add(cpu_obj, multi_cfg->name, "bool", cpu_get_multi_ext_cfg, cpu_set_multi_ext_cfg, NULL, (void *)&multi_cfg->offset); - - if (!generic_cpu) { - return; - } - - /* - * Set def val directly instead of using - * object_property_set_bool() to save the set() - * callback hash for user inputs. - */ - isa_ext_update_enabled(RISCV_CPU(cpu_obj), multi_cfg->offset, - multi_cfg->enabled); } static void riscv_cpu_add_multiext_prop_array(Object *obj, -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> This change has been done twice now: one in riscv-qmp-cmds, another in the KVM. We're now ready to do it for TCG. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-14-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name, visit_type_bool(v, name, &value, errp); } -static void cpu_add_multi_ext_prop(Object *cpu_obj, - const RISCVCPUMultiExtConfig *multi_cfg) -{ - object_property_add(cpu_obj, multi_cfg->name, "bool", - cpu_get_multi_ext_cfg, - cpu_set_multi_ext_cfg, - NULL, (void *)&multi_cfg->offset); -} - -static void riscv_cpu_add_multiext_prop_array(Object *obj, - const RISCVCPUMultiExtConfig *array) -{ - const RISCVCPUMultiExtConfig *prop; - - g_assert(array); - - for (prop = array; prop && prop->name; prop++) { - cpu_add_multi_ext_prop(obj, prop); - } -} - /* * Add CPU properties with user-facing flags. * @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_add_multiext_prop_array(Object *obj, */ static void riscv_cpu_add_user_properties(Object *obj) { + const RISCVIsaExtData *edata; + #ifndef CONFIG_USER_ONLY riscv_add_satp_mode_properties(obj); #endif riscv_cpu_add_misa_properties(obj); - riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_extensions); - riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_vendor_exts); - riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_experimental_exts); + for (edata = isa_edata_arr; edata && edata->name; edata++) { + if (edata->prop_name) { + object_property_add(obj, edata->prop_name, "bool", + cpu_get_multi_ext_cfg, + cpu_set_multi_ext_cfg, + NULL, (void *)&edata->ext_enable_offset); + } + } riscv_cpu_add_profiles(obj); } -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> There is no more uses left for these arrays. isa_edata_arr[] is doing everything we need, making our lives a little easier when adding new extensions. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-15-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 10 --- target/riscv/cpu.c | 159 --------------------------------------------- 2 files changed, 169 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset); void riscv_cpu_set_misa_ext(CPURISCVState *env, uint32_t ext); bool riscv_cpu_is_vendor(Object *cpu_obj); -typedef struct RISCVCPUMultiExtConfig { - const char *name; - uint32_t offset; - bool enabled; -} RISCVCPUMultiExtConfig; - -extern const RISCVCPUMultiExtConfig riscv_cpu_extensions[]; -extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[]; -extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[]; - typedef struct isa_ext_data { const char *name; const char *prop_name; diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ const char *riscv_get_misa_ext_description(uint32_t bit) return val; } -#define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \ - {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \ - .enabled = _defval} - -const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { - /* Defaults for standard extensions */ - MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false), - MULTI_EXT_CFG_BOOL("smcntrpmf", ext_smcntrpmf, false), - MULTI_EXT_CFG_BOOL("smcsrind", ext_smcsrind, false), - MULTI_EXT_CFG_BOOL("smcdeleg", ext_smcdeleg, false), - MULTI_EXT_CFG_BOOL("sscsrind", ext_sscsrind, false), - MULTI_EXT_CFG_BOOL("ssccfg", ext_ssccfg, false), - MULTI_EXT_CFG_BOOL("smctr", ext_smctr, false), - MULTI_EXT_CFG_BOOL("ssctr", ext_ssctr, false), - MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true), - MULTI_EXT_CFG_BOOL("zicfilp", ext_zicfilp, false), - MULTI_EXT_CFG_BOOL("zicfiss", ext_zicfiss, false), - MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true), - MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true), - MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true), - MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false), - MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false), - MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false), - MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false), - MULTI_EXT_CFG_BOOL("zabha", ext_zabha, false), - MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false), - MULTI_EXT_CFG_BOOL("zalasr", ext_zalasr, false), - MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false), - MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true), - MULTI_EXT_CFG_BOOL("zfa", ext_zfa, true), - MULTI_EXT_CFG_BOOL("zfbfmin", ext_zfbfmin, false), - MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false), - MULTI_EXT_CFG_BOOL("zfhmin", ext_zfhmin, false), - MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false), - MULTI_EXT_CFG_BOOL("zve32x", ext_zve32x, false), - MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false), - MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false), - MULTI_EXT_CFG_BOOL("zve64x", ext_zve64x, false), - MULTI_EXT_CFG_BOOL("zvfbfa", ext_zvfbfa, false), - MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false), - MULTI_EXT_CFG_BOOL("zvfbfwma", ext_zvfbfwma, false), - MULTI_EXT_CFG_BOOL("zvfh", ext_zvfh, false), - MULTI_EXT_CFG_BOOL("zvfhmin", ext_zvfhmin, false), - MULTI_EXT_CFG_BOOL("sstc", ext_sstc, true), - MULTI_EXT_CFG_BOOL("ssnpm", ext_ssnpm, false), - MULTI_EXT_CFG_BOOL("sspm", ext_sspm, false), - MULTI_EXT_CFG_BOOL("supm", ext_supm, false), - - MULTI_EXT_CFG_BOOL("smaia", ext_smaia, false), - MULTI_EXT_CFG_BOOL("smdbltrp", ext_smdbltrp, false), - MULTI_EXT_CFG_BOOL("smepmp", ext_smepmp, false), - MULTI_EXT_CFG_BOOL("smpmpmt", ext_smpmpmt, false), - MULTI_EXT_CFG_BOOL("smrnmi", ext_smrnmi, false), - MULTI_EXT_CFG_BOOL("smmpm", ext_smmpm, false), - MULTI_EXT_CFG_BOOL("smnpm", ext_smnpm, false), - MULTI_EXT_CFG_BOOL("smstateen", ext_smstateen, false), - MULTI_EXT_CFG_BOOL("ssaia", ext_ssaia, false), - MULTI_EXT_CFG_BOOL("ssdbltrp", ext_ssdbltrp, false), - MULTI_EXT_CFG_BOOL("svade", ext_svade, false), - MULTI_EXT_CFG_BOOL("svadu", ext_svadu, true), - MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false), - MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false), - MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false), - MULTI_EXT_CFG_BOOL("svrsw60t59b", ext_svrsw60t59b, false), - MULTI_EXT_CFG_BOOL("svvptc", ext_svvptc, true), - - MULTI_EXT_CFG_BOOL("zicntr", ext_zicntr, true), - MULTI_EXT_CFG_BOOL("zihpm", ext_zihpm, true), - MULTI_EXT_CFG_BOOL("zilsd", ext_zilsd, false), - - MULTI_EXT_CFG_BOOL("zba", ext_zba, true), - MULTI_EXT_CFG_BOOL("zbb", ext_zbb, true), - MULTI_EXT_CFG_BOOL("zbc", ext_zbc, true), - MULTI_EXT_CFG_BOOL("zbkb", ext_zbkb, false), - MULTI_EXT_CFG_BOOL("zbkc", ext_zbkc, false), - MULTI_EXT_CFG_BOOL("zbkx", ext_zbkx, false), - MULTI_EXT_CFG_BOOL("zbs", ext_zbs, true), - MULTI_EXT_CFG_BOOL("zk", ext_zk, false), - MULTI_EXT_CFG_BOOL("zkn", ext_zkn, false), - MULTI_EXT_CFG_BOOL("zknd", ext_zknd, false), - MULTI_EXT_CFG_BOOL("zkne", ext_zkne, false), - MULTI_EXT_CFG_BOOL("zknh", ext_zknh, false), - MULTI_EXT_CFG_BOOL("zkr", ext_zkr, false), - MULTI_EXT_CFG_BOOL("zks", ext_zks, false), - MULTI_EXT_CFG_BOOL("zksed", ext_zksed, false), - MULTI_EXT_CFG_BOOL("zksh", ext_zksh, false), - MULTI_EXT_CFG_BOOL("zkt", ext_zkt, false), - MULTI_EXT_CFG_BOOL("ztso", ext_ztso, false), - - MULTI_EXT_CFG_BOOL("zdinx", ext_zdinx, false), - MULTI_EXT_CFG_BOOL("zfinx", ext_zfinx, false), - MULTI_EXT_CFG_BOOL("zhinx", ext_zhinx, false), - MULTI_EXT_CFG_BOOL("zhinxmin", ext_zhinxmin, false), - - MULTI_EXT_CFG_BOOL("zicbom", ext_zicbom, true), - MULTI_EXT_CFG_BOOL("zicbop", ext_zicbop, true), - MULTI_EXT_CFG_BOOL("zicboz", ext_zicboz, true), - - MULTI_EXT_CFG_BOOL("zmmul", ext_zmmul, false), - - MULTI_EXT_CFG_BOOL("zca", ext_zca, false), - MULTI_EXT_CFG_BOOL("zcb", ext_zcb, false), - MULTI_EXT_CFG_BOOL("zcd", ext_zcd, false), - MULTI_EXT_CFG_BOOL("zce", ext_zce, false), - MULTI_EXT_CFG_BOOL("zcf", ext_zcf, false), - MULTI_EXT_CFG_BOOL("zcmp", ext_zcmp, false), - MULTI_EXT_CFG_BOOL("zcmt", ext_zcmt, false), - MULTI_EXT_CFG_BOOL("zicond", ext_zicond, false), - MULTI_EXT_CFG_BOOL("zclsd", ext_zclsd, false), - - /* Vector cryptography extensions */ - MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false), - MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false), - MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false), - MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false), - MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false), - MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false), - MULTI_EXT_CFG_BOOL("zvknhb", ext_zvknhb, false), - MULTI_EXT_CFG_BOOL("zvksed", ext_zvksed, false), - MULTI_EXT_CFG_BOOL("zvksh", ext_zvksh, false), - MULTI_EXT_CFG_BOOL("zvkt", ext_zvkt, false), - MULTI_EXT_CFG_BOOL("zvkn", ext_zvkn, false), - MULTI_EXT_CFG_BOOL("zvknc", ext_zvknc, false), - MULTI_EXT_CFG_BOOL("zvkng", ext_zvkng, false), - MULTI_EXT_CFG_BOOL("zvks", ext_zvks, false), - MULTI_EXT_CFG_BOOL("zvksc", ext_zvksc, false), - MULTI_EXT_CFG_BOOL("zvksg", ext_zvksg, false), - - { }, -}; - -const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { - MULTI_EXT_CFG_BOOL("xtheadba", ext_xtheadba, false), - MULTI_EXT_CFG_BOOL("xtheadbb", ext_xtheadbb, false), - MULTI_EXT_CFG_BOOL("xtheadbs", ext_xtheadbs, false), - MULTI_EXT_CFG_BOOL("xtheadcmo", ext_xtheadcmo, false), - MULTI_EXT_CFG_BOOL("xtheadcondmov", ext_xtheadcondmov, false), - MULTI_EXT_CFG_BOOL("xtheadfmemidx", ext_xtheadfmemidx, false), - MULTI_EXT_CFG_BOOL("xtheadfmv", ext_xtheadfmv, false), - MULTI_EXT_CFG_BOOL("xtheadmac", ext_xtheadmac, false), - MULTI_EXT_CFG_BOOL("xtheadmemidx", ext_xtheadmemidx, false), - MULTI_EXT_CFG_BOOL("xtheadmempair", ext_xtheadmempair, false), - MULTI_EXT_CFG_BOOL("xtheadsync", ext_xtheadsync, false), - MULTI_EXT_CFG_BOOL("xventanacondops", ext_XVentanaCondOps, false), - MULTI_EXT_CFG_BOOL("xmipscbop", ext_xmipscbop, false), - MULTI_EXT_CFG_BOOL("xmipscmov", ext_xmipscmov, false), - MULTI_EXT_CFG_BOOL("xmipslsp", ext_xmipslsp, false), - MULTI_EXT_CFG_BOOL("xlrbr", ext_xlrbr, false), - - { }, -}; - -/* These are experimental so mark with 'x-' */ -const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { - MULTI_EXT_CFG_BOOL("x-svukte", ext_svukte, false), - - { }, -}; - static void cpu_set_prop_err(RISCVCPU *cpu, const char *propname, Error **errp) { -- 2.53.0
From: Fangyu Yu <fangyu.yu@linux.alibaba.com> Fix IOCOUNTINH.CY toggle detection by comparing normalized CY bit rather than XORing whole register with boolean. Fixes: 2cf2a6c027ba ("hw/riscv/riscv-iommu: add IOCOUNTINH mmio writes") Signed-off-by: Fangyu Yu <fangyu.yu@linux.alibaba.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Message-ID: <20260509074941.99295-1-fangyu.yu@linux.alibaba.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu-hpm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/riscv/riscv-iommu-hpm.c b/hw/riscv/riscv-iommu-hpm.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu-hpm.c +++ b/hw/riscv/riscv-iommu-hpm.c @@ -XXX,XX +XXX,XX @@ void riscv_iommu_process_iocntinh_cy(RISCVIOMMUState *s, bool prev_cy_inh) s, RISCV_IOMMU_REG_IOCOUNTINH); /* We only need to process CY bit toggle. */ - if (!(inhibit ^ prev_cy_inh)) { + bool cy_inh = !!(inhibit & RISCV_IOMMU_IOCOUNTINH_CY); + if (cy_inh == prev_cy_inh) { return; } -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The priv spec defines, for RV64, that the upper 10 bits of pmpaddr0-pmpaddr63 are WARL and are supposed to be cleared. After this patch, using the bug reproducer in [1], writing ffffffffffffffff in pmpaddr0 and reading it back now results in 003fffffffffffff. Here's the 'diff -cp' dump before and after this change: *************** IN: *** 5272,5278 **** pmpcfg10 0000000000000000 pmpcfg12 0000000000000000 pmpcfg14 0000000000000000 ! pmpaddr0 ffffffffffffffff pmpaddr1 0000000000000000 pmpaddr2 0000000000000000 pmpaddr3 0000000000000000 Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260514123342.2139464-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static RISCVException read_pmpaddr(CPURISCVState *env, int csrno, target_ulong *val) { *val = pmpaddr_csr_read(env, csrno - CSR_PMPADDR0); + + /* + * For RV64, bits 54-63 of the address registers + * PMPAADDR(0-63) is a WARL zero field (priv spec, + * section "Physical Memory Protection CSRs"). + * + * We'll have to add an annoying TARGET_RISCV64 gate + * here to avoid complaints about masking bits 0-53 + * of a potential 32 bit target_ulong '*var'. + */ +#ifdef TARGET_RISCV64 + if (env->misa_mxl == MXL_RV64 + && csrno >= CSR_PMPADDR0 && csrno <= CSR_PMPADDR63) { + target_ulong read_mask = MAKE_64BIT_MASK(0, 54); + *val &= read_mask; + } +#endif return RISCV_EXCP_NONE; } -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> In build_rimt(), the calculation of `num_ids` for the ID mapping array incorrectly uses the same formula (`0xffff - s->pci_iommu_bdf`) for both System IOMMU and PCI IOMMU topologies. For a System IOMMU, `s->pci_iommu_bdf` is 0. This results in a `num_ids` value of 0xffff. Since the source ID base starts at 0, the mapping only covers Requester IDs from 0 to 0xfffe. The final valid PCI Requester ID (0xffff) is erroneously omitted from the RIMT table. Fix this by decoupling the `num_ids` calculation. For System IOMMUs, explicitly set `num_ids` to 0x10000 to cover the entire PCI Requester ID space. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/c78dacf66c8acd677b3538c837fde310bb71a97b/output/riscv-server-platform/pr-102/qemu.txt#L32 Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512062310.348208-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt-acpi-build.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -XXX,XX +XXX,XX @@ static void build_rimt(GArray *table_data, BIOSLinker *linker, range = &g_array_index(iommu_idmaps, AcpiRimtIdMapping, i); if (virt_is_iommu_sys_enabled(s)) { range->source_id_base = 0; + range->num_ids = 0x10000; } else { range->source_id_base = s->pci_iommu_bdf + 1; + range->num_ids = 0xffff - s->pci_iommu_bdf; } - range->num_ids = 0xffff - s->pci_iommu_bdf; build_rimt_id_mapping(table_data, range->source_id_base, range->num_ids, iommu_offset); } -- 2.53.0
From: Portia Stephens <portias@oss.tenstorrent.com> The counter value was not being bitshifted for a hpmcounterh read resulting in hpmcounterh returning the bottom 32-bits. Fixes: cfc96df65e01 ("target/riscv: Remove upper_half from riscv_pmu_ctr_get_fixed_counters_val") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3498 Cc: qemu-stable@nongnu.org Signed-off-by: Portia Stephens <portias@oss.tenstorrent.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260519043352.3685866-1-stephensportia@gmail.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, */ if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { - *val = riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx) - - ctr_prev + ctr_val; + uint64_t cntr = riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx) - + ctr_prev + ctr_val; + *val = extract64(cntr, start, length); } else { *val = ctr_val; } -- 2.53.0
From: Jim Shu <jim.shu@sifive.com> According to the AIA spec ch4.7 ("Precise effects on interrupt-pending bits"), pending bit of APLIC should be set/cleared whenever the rectified input value is high/low in the both level-trigger mode and direct delivery mode. Currently, QEMU APLIC only clears the pending bit when interrupt is claimed in APLIC, but not clears it when the rectified input value is low. (e.g. IRQ source signal is low in the LEVEL_HIGH/Level1 mode). The software may receive an additional IRQ if the peripheral triggers one after the software clears the APLIC IRQ but before it clears the peripheral's IRQ. Thus, we also clear the pending bit via the rectified input value in the level-trigger mode. This change doesn't affect MSI delivery mode. Calling riscv_aplic_msi_irq_update() when IRQ pending is low will do nothing. Signed-off-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260428160103.3551125-2-jim.shu@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/intc/riscv_aplic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_aplic.c +++ b/hw/intc/riscv_aplic.c @@ -XXX,XX +XXX,XX @@ static void riscv_aplic_request(void *opaque, int irq, int level) } break; case APLIC_SOURCECFG_SM_LEVEL_HIGH: - if ((level > 0) && !(state & APLIC_ISTATE_PENDING)) { - riscv_aplic_set_pending_raw(aplic, irq, true); + if ((level > 0) != !!(state & APLIC_ISTATE_PENDING)) { + riscv_aplic_set_pending_raw(aplic, irq, level > 0); update = true; } break; case APLIC_SOURCECFG_SM_LEVEL_LOW: - if ((level <= 0) && !(state & APLIC_ISTATE_PENDING)) { - riscv_aplic_set_pending_raw(aplic, irq, true); + if ((level <= 0) != !!(state & APLIC_ISTATE_PENDING)) { + riscv_aplic_set_pending_raw(aplic, irq, level <= 0); update = true; } break; -- 2.53.0
From: Jim Shu <jim.shu@sifive.com> Clearing APLIC registers and qemu_irq in the reset function Signed-off-by: Jim Shu <jim.shu@sifive.com> Signed-off-by: Fea.Wang <fea.wang@sifive.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260428160103.3551125-3-jim.shu@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/intc/riscv_aplic.c | 45 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_aplic.c +++ b/hw/intc/riscv_aplic.c @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps riscv_aplic_ops = { } }; +static void riscv_aplic_reset_enter(Object *obj, ResetType type) +{ + RISCVAPLICState *aplic = RISCV_APLIC(obj); + int i; + + aplic->domaincfg = 0; + memset(aplic->sourcecfg, 0, sizeof(uint32_t) * aplic->num_irqs); + memset(aplic->target, 0, sizeof(uint32_t) * aplic->num_irqs); + if (!aplic->msimode) { + for (i = 0; i < aplic->num_irqs; i++) { + aplic->target[i] = 1; + } + } + + for (i = 0; i < aplic->num_irqs ; i++) { + riscv_aplic_set_enabled_raw(aplic, i, false); + } + + /* Need to unlock [ms]msicfgaddrh.L */ + aplic->mmsicfgaddr = 0; + aplic->mmsicfgaddrH = 0; + aplic->smsicfgaddr = 0; + aplic->smsicfgaddrH = 0; + + if (!aplic->msimode) { + /* Reset IDC registers only in non-MSI mode */ + for (i = 0; i < aplic->num_harts; i++) { + aplic->idelivery[i] = 0; + aplic->iforce[i] = 0; + aplic->ithreshold[i] = 0; + } + + for (i = 0; i < aplic->num_harts; i++) { + qemu_irq_lower(aplic->external_irqs[i]); + } + } +} + static void riscv_aplic_realize(DeviceState *dev, Error **errp) { uint32_t i; @@ -XXX,XX +XXX,XX @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp) aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs); aplic->state = g_new0(uint32_t, aplic->num_irqs); aplic->target = g_new0(uint32_t, aplic->num_irqs); - if (!aplic->msimode) { - for (i = 0; i < aplic->num_irqs; i++) { - aplic->target[i] = 1; - } - } aplic->idelivery = g_new0(uint32_t, aplic->num_harts); aplic->iforce = g_new0(uint32_t, aplic->num_harts); aplic->ithreshold = g_new0(uint32_t, aplic->num_harts); @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_riscv_aplic = { static void riscv_aplic_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); device_class_set_props(dc, riscv_aplic_properties); dc->realize = riscv_aplic_realize; + rc->phases.enter = riscv_aplic_reset_enter; dc->vmsd = &vmstate_riscv_aplic; } -- 2.53.0
From: Jim Shu <jim.shu@sifive.com> Clearing IMSIC registers and qemu_irq in the reset function Signed-off-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260428160103.3551125-4-jim.shu@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/intc/riscv_imsic.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_imsic.c +++ b/hw/intc/riscv_imsic.c @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps riscv_imsic_ops = { } }; +static void riscv_imsic_reset_enter(Object *obj, ResetType type) +{ + RISCVIMSICState *imsic = RISCV_IMSIC(obj); + int i; + + memset(imsic->eidelivery, 0, sizeof(uint32_t) * imsic->num_pages); + memset(imsic->eithreshold, 0, sizeof(uint32_t) * imsic->num_pages); + + for (i = 0; i < imsic->num_eistate; i++) { + imsic->eistate[i] &= ~IMSIC_EISTATE_ENABLED; + } + + for (i = 0; i < imsic->num_pages; i++) { + qemu_irq_lower(imsic->external_irqs[i]); + } +} + static void riscv_imsic_realize(DeviceState *dev, Error **errp) { RISCVIMSICState *imsic = RISCV_IMSIC(dev); @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_riscv_imsic = { static void riscv_imsic_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); device_class_set_props(dc, riscv_imsic_properties); dc->realize = riscv_imsic_realize; + rc->phases.enter = riscv_imsic_reset_enter; dc->vmsd = &vmstate_riscv_imsic; } -- 2.53.0
From: Jim Shu <jim.shu@sifive.com> Add the trace events for APLIC read/write functions. Signed-off-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260428160103.3551125-5-jim.shu@sifive.com> [ Changes by AF: - Init val to zero to avoid uninitialised build errors ] Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/intc/riscv_aplic.c | 63 ++++++++++++++++++++++++++----------------- hw/intc/trace-events | 4 +++ 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_aplic.c +++ b/hw/intc/riscv_aplic.c @@ -XXX,XX +XXX,XX @@ #include "system/tcg.h" #include "kvm/kvm_riscv.h" #include "migration/vmstate.h" +#include "trace.h" #define APLIC_MAX_IDC (1UL << 14) #define APLIC_MAX_SOURCE 1024 @@ -XXX,XX +XXX,XX @@ static void riscv_aplic_request(void *opaque, int irq, int level) static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size) { uint32_t irq, word, idc; + uint64_t val = 0; RISCVAPLICState *aplic = opaque; /* Reads must be 4 byte words */ @@ -XXX,XX +XXX,XX @@ static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size) } if (addr == APLIC_DOMAINCFG) { - return APLIC_DOMAINCFG_RDONLY | aplic->domaincfg | - (aplic->msimode ? APLIC_DOMAINCFG_DM : 0); + val = APLIC_DOMAINCFG_RDONLY | aplic->domaincfg | + (aplic->msimode ? APLIC_DOMAINCFG_DM : 0); } else if ((APLIC_SOURCECFG_BASE <= addr) && (addr < (APLIC_SOURCECFG_BASE + (aplic->num_irqs - 1) * 4))) { irq = ((addr - APLIC_SOURCECFG_BASE) >> 2) + 1; - return aplic->sourcecfg[irq]; + val = aplic->sourcecfg[irq]; } else if (aplic->mmode && aplic->msimode && (addr == APLIC_MMSICFGADDR)) { - return aplic->mmsicfgaddr; + val = aplic->mmsicfgaddr; } else if (aplic->mmode && aplic->msimode && (addr == APLIC_MMSICFGADDRH)) { - return aplic->mmsicfgaddrH; + val = aplic->mmsicfgaddrH; } else if (aplic->mmode && aplic->msimode && (addr == APLIC_SMSICFGADDR)) { /* @@ -XXX,XX +XXX,XX @@ static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size) * only zero in at least one of the supervisor-level child * domains). */ - return (aplic->num_children) ? aplic->smsicfgaddr : 0; + val = (aplic->num_children) ? aplic->smsicfgaddr : 0; } else if (aplic->mmode && aplic->msimode && (addr == APLIC_SMSICFGADDRH)) { - return (aplic->num_children) ? aplic->smsicfgaddrH : 0; + val = (aplic->num_children) ? aplic->smsicfgaddrH : 0; } else if ((APLIC_SETIP_BASE <= addr) && (addr < (APLIC_SETIP_BASE + aplic->bitfield_words * 4))) { word = (addr - APLIC_SETIP_BASE) >> 2; - return riscv_aplic_read_pending_word(aplic, word); + val = riscv_aplic_read_pending_word(aplic, word); } else if (addr == APLIC_SETIPNUM) { - return 0; + val = 0; } else if ((APLIC_CLRIP_BASE <= addr) && (addr < (APLIC_CLRIP_BASE + aplic->bitfield_words * 4))) { word = (addr - APLIC_CLRIP_BASE) >> 2; - return riscv_aplic_read_input_word(aplic, word); + val = riscv_aplic_read_input_word(aplic, word); } else if (addr == APLIC_CLRIPNUM) { - return 0; + val = 0; } else if ((APLIC_SETIE_BASE <= addr) && (addr < (APLIC_SETIE_BASE + aplic->bitfield_words * 4))) { word = (addr - APLIC_SETIE_BASE) >> 2; - return riscv_aplic_read_enabled_word(aplic, word); + val = riscv_aplic_read_enabled_word(aplic, word); } else if (addr == APLIC_SETIENUM) { - return 0; + val = 0; } else if ((APLIC_CLRIE_BASE <= addr) && (addr < (APLIC_CLRIE_BASE + aplic->bitfield_words * 4))) { - return 0; + val = 0; } else if (addr == APLIC_CLRIENUM) { - return 0; + val = 0; } else if (addr == APLIC_SETIPNUM_LE) { - return 0; + val = 0; } else if (addr == APLIC_SETIPNUM_BE) { - return 0; + val = 0; } else if (addr == APLIC_GENMSI) { - return (aplic->msimode) ? aplic->genmsi : 0; + val = (aplic->msimode) ? aplic->genmsi : 0; } else if ((APLIC_TARGET_BASE <= addr) && (addr < (APLIC_TARGET_BASE + (aplic->num_irqs - 1) * 4))) { irq = ((addr - APLIC_TARGET_BASE) >> 2) + 1; if (!riscv_aplic_source_active(aplic, irq)) { - return 0; + val = 0; + } else { + val = aplic->target[irq]; } - return aplic->target[irq]; } else if (!aplic->msimode && (APLIC_IDC_BASE <= addr) && (addr < (APLIC_IDC_BASE + aplic->num_harts * APLIC_IDC_SIZE))) { idc = (addr - APLIC_IDC_BASE) / APLIC_IDC_SIZE; switch (addr - (APLIC_IDC_BASE + idc * APLIC_IDC_SIZE)) { case APLIC_IDC_IDELIVERY: - return aplic->idelivery[idc]; + val = aplic->idelivery[idc]; + break; case APLIC_IDC_IFORCE: - return aplic->iforce[idc]; + val = aplic->iforce[idc]; + break; case APLIC_IDC_ITHRESHOLD: - return aplic->ithreshold[idc]; + val = aplic->ithreshold[idc]; + break; case APLIC_IDC_TOPI: - return riscv_aplic_idc_topi(aplic, idc); + val = riscv_aplic_idc_topi(aplic, idc); + break; case APLIC_IDC_CLAIMI: - return riscv_aplic_idc_claimi(aplic, idc); + val = riscv_aplic_idc_claimi(aplic, idc); + break; default: goto err; }; } + trace_riscv_aplic_read(addr, size, val); + return val; + err: qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid register read 0x%" HWADDR_PRIx "\n", @@ -XXX,XX +XXX,XX @@ static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value, goto err; } + trace_riscv_aplic_write(addr, size, value); + if (addr == APLIC_DOMAINCFG) { /* Only IE bit writable at the moment */ value &= APLIC_DOMAINCFG_IE; diff --git a/hw/intc/trace-events b/hw/intc/trace-events index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -XXX,XX +XXX,XX @@ loongarch_msi_set_irq(int irq_num) "set msi irq %d" loongarch_extioi_setirq(int irq, int level) "set extirq irq %d level %d" loongarch_extioi_readw(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64 loongarch_extioi_writew(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64 + +# riscv_aplic.c +riscv_aplic_read(uint64_t offset, unsigned size, uint64_t value) "offset: 0x%" PRIx64 ", size: %u, value: 0x%" PRIx64 +riscv_aplic_write(uint64_t offset, unsigned size, uint64_t value) "offset: 0x%" PRIx64 ", size: %u, value: 0x%" PRIx64 -- 2.53.0
From: Jay Chang <jay.chang@sifive.com> When software clears CMD_ILL or CQMF error bits by writing 1 to CQCSR, the IOMMU should re-check the command queue and continue processing pending commands if head != tail. Per RISC-V IOMMU specification : If command-queue access leads to a memory fault then the command-queue-memory-fault bit is set to 1 and the commandqueue stalls until this bit is cleared. To re-enable command processing, software should clear this bit by writing 1. Signed-off-by: Jay Chang <jay.chang@sifive.com> Reviewed-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Message-ID: <20260518070143.8405-1-jay.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_process_cq_control(RISCVIOMMUState *s) } riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_CQCSR, ctrl_set, ctrl_clr); + + /* + * After clearing error bits (CMD_ILL, CQMF), if queue is still active, + * re-process pending command. + */ + ctrl_set = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_CQCSR); + if ((ctrl_set & RISCV_IOMMU_CQCSR_CQON) && + !(ctrl_set & (RISCV_IOMMU_CQCSR_CMD_ILL | RISCV_IOMMU_CQCSR_CQMF))) { + riscv_iommu_process_cq_tail(s); + } } static void riscv_iommu_process_fq_control(RISCVIOMMUState *s) -- 2.53.0