From 12b12a14c73ee200c7cff42aab6113a0649fa132 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 12 Oct 2023 13:46:01 -0300 Subject: [PATCH 01/49] target/riscv: rename ext_ifencei to ext_zifencei Add a leading 'z' to improve grepping. When one wants to search for uses of zifencei they're more likely to do 'grep -i zifencei' than 'grep -i ifencei'. Suggested-by: Andrew Jones Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-ID: <20231012164604.398496-2-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 22 +++++++++++----------- target/riscv/cpu_cfg.h | 2 +- target/riscv/insn_trans/trans_rvi.c.inc | 2 +- target/riscv/tcg/tcg-cpu.c | 8 ++++---- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ac4a6c7eec..3693eabb34 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -80,7 +80,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_icboz), ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond), ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_icsr), - ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_ifencei), + ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_zifencei), ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl), ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause), ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul), @@ -382,7 +382,7 @@ static void riscv_any_cpu_init(Object *obj) env->priv_ver = PRIV_VERSION_LATEST; /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_ifencei = true; + cpu->cfg.ext_zifencei = true; cpu->cfg.ext_icsr = true; cpu->cfg.mmu = true; cpu->cfg.pmp = true; @@ -430,7 +430,7 @@ static void rv64_sifive_u_cpu_init(Object *obj) #endif /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_ifencei = true; + cpu->cfg.ext_zifencei = true; cpu->cfg.ext_icsr = true; cpu->cfg.mmu = true; cpu->cfg.pmp = true; @@ -448,7 +448,7 @@ static void rv64_sifive_e_cpu_init(Object *obj) #endif /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_ifencei = true; + cpu->cfg.ext_zifencei = true; cpu->cfg.ext_icsr = true; cpu->cfg.pmp = true; } @@ -494,7 +494,7 @@ static void rv64_veyron_v1_cpu_init(Object *obj) /* Enable ISA extensions */ cpu->cfg.mmu = true; - cpu->cfg.ext_ifencei = true; + cpu->cfg.ext_zifencei = true; cpu->cfg.ext_icsr = true; cpu->cfg.pmp = true; cpu->cfg.ext_icbom = true; @@ -566,7 +566,7 @@ static void rv32_sifive_u_cpu_init(Object *obj) #endif /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_ifencei = true; + cpu->cfg.ext_zifencei = true; cpu->cfg.ext_icsr = true; cpu->cfg.mmu = true; cpu->cfg.pmp = true; @@ -584,7 +584,7 @@ static void rv32_sifive_e_cpu_init(Object *obj) #endif /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_ifencei = true; + cpu->cfg.ext_zifencei = true; cpu->cfg.ext_icsr = true; cpu->cfg.pmp = true; } @@ -602,7 +602,7 @@ static void rv32_ibex_cpu_init(Object *obj) cpu->cfg.epmp = true; /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_ifencei = true; + cpu->cfg.ext_zifencei = true; cpu->cfg.ext_icsr = true; cpu->cfg.pmp = true; } @@ -619,7 +619,7 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj) #endif /* inherited from parent obj via riscv_cpu_init() */ - cpu->cfg.ext_ifencei = true; + cpu->cfg.ext_zifencei = true; cpu->cfg.ext_icsr = true; cpu->cfg.pmp = true; } @@ -1242,7 +1242,7 @@ const char *riscv_get_misa_ext_description(uint32_t bit) const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { /* Defaults for standard extensions */ MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false), - MULTI_EXT_CFG_BOOL("zifencei", ext_ifencei, true), + MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true), MULTI_EXT_CFG_BOOL("zicsr", ext_icsr, true), MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true), MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true), @@ -1347,7 +1347,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { /* Deprecated entries marked for future removal */ const RISCVCPUMultiExtConfig riscv_cpu_deprecated_exts[] = { - MULTI_EXT_CFG_BOOL("Zifencei", ext_ifencei, true), + MULTI_EXT_CFG_BOOL("Zifencei", ext_zifencei, true), MULTI_EXT_CFG_BOOL("Zicsr", ext_icsr, true), MULTI_EXT_CFG_BOOL("Zihintntl", ext_zihintntl, true), MULTI_EXT_CFG_BOOL("Zihintpause", ext_zihintpause, true), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 0e6a0f245c..a3f96eb878 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -61,7 +61,7 @@ struct RISCVCPUConfig { bool ext_zksed; bool ext_zksh; bool ext_zkt; - bool ext_ifencei; + bool ext_zifencei; bool ext_icsr; bool ext_icbom; bool ext_icboz; diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index 25cb60558a..faf6d65064 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -799,7 +799,7 @@ static bool trans_fence(DisasContext *ctx, arg_fence *a) static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a) { - if (!ctx->cfg_ptr->ext_ifencei) { + if (!ctx->cfg_ptr->ext_zifencei) { return false; } diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index a28918ab30..9b8f3f54a7 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -278,7 +278,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) !(riscv_has_ext(env, RVI) && riscv_has_ext(env, RVM) && riscv_has_ext(env, RVA) && riscv_has_ext(env, RVF) && riscv_has_ext(env, RVD) && - cpu->cfg.ext_icsr && cpu->cfg.ext_ifencei)) { + cpu->cfg.ext_icsr && cpu->cfg.ext_zifencei)) { if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_icsr)) && !cpu->cfg.ext_icsr) { @@ -286,15 +286,15 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) return; } - if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_ifencei)) && - !cpu->cfg.ext_ifencei) { + if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zifencei)) && + !cpu->cfg.ext_zifencei) { error_setg(errp, "RVG requires Zifencei but user set " "Zifencei to false"); return; } cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_icsr), true); - cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_ifencei), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zifencei), true); env->misa_ext |= RVI | RVM | RVA | RVF | RVD; env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD; From 960b389b7d15f2ebb2b4d75d98d5ffec2c6a8348 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 12 Oct 2023 13:46:02 -0300 Subject: [PATCH 02/49] target/riscv: rename ext_icsr to ext_zicsr Add a leading 'z' to improve grepping. When one wants to search for uses of zicsr they're more likely to do 'grep -i zicsr' than 'grep -i icsr'. Suggested-by: Andrew Jones Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-ID: <20231012164604.398496-3-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- hw/riscv/boot.c | 2 +- target/riscv/cpu.c | 22 +++++++++++----------- target/riscv/cpu_cfg.h | 2 +- target/riscv/csr.c | 2 +- target/riscv/gdbstub.c | 2 +- target/riscv/tcg/tcg-cpu.c | 14 +++++++------- 6 files changed, 22 insertions(+), 22 deletions(-) diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 52bf8e67de..0ffca05189 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -414,7 +414,7 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts reset_vec[4] = 0x0182b283; /* ld t0, 24(t0) */ } - if (!harts->harts[0].cfg.ext_icsr) { + if (!harts->harts[0].cfg.ext_zicsr) { /* * The Zicsr extension has been disabled, so let's ensure we don't * run the CSR instruction. Let's fill the address with a non diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 3693eabb34..566b7545e8 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -79,7 +79,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_icbom), ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_icboz), ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond), - ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_icsr), + ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_zicsr), ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_zifencei), ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl), ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause), @@ -383,7 +383,7 @@ static void riscv_any_cpu_init(Object *obj) /* inherited from parent obj via riscv_cpu_init() */ cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_icsr = true; + cpu->cfg.ext_zicsr = true; cpu->cfg.mmu = true; cpu->cfg.pmp = true; } @@ -431,7 +431,7 @@ static void rv64_sifive_u_cpu_init(Object *obj) /* inherited from parent obj via riscv_cpu_init() */ cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_icsr = true; + cpu->cfg.ext_zicsr = true; cpu->cfg.mmu = true; cpu->cfg.pmp = true; } @@ -449,7 +449,7 @@ static void rv64_sifive_e_cpu_init(Object *obj) /* inherited from parent obj via riscv_cpu_init() */ cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_icsr = true; + cpu->cfg.ext_zicsr = true; cpu->cfg.pmp = true; } @@ -495,7 +495,7 @@ static void rv64_veyron_v1_cpu_init(Object *obj) /* Enable ISA extensions */ cpu->cfg.mmu = true; cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_icsr = true; + cpu->cfg.ext_zicsr = true; cpu->cfg.pmp = true; cpu->cfg.ext_icbom = true; cpu->cfg.cbom_blocksize = 64; @@ -567,7 +567,7 @@ static void rv32_sifive_u_cpu_init(Object *obj) /* inherited from parent obj via riscv_cpu_init() */ cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_icsr = true; + cpu->cfg.ext_zicsr = true; cpu->cfg.mmu = true; cpu->cfg.pmp = true; } @@ -585,7 +585,7 @@ static void rv32_sifive_e_cpu_init(Object *obj) /* inherited from parent obj via riscv_cpu_init() */ cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_icsr = true; + cpu->cfg.ext_zicsr = true; cpu->cfg.pmp = true; } @@ -603,7 +603,7 @@ static void rv32_ibex_cpu_init(Object *obj) /* inherited from parent obj via riscv_cpu_init() */ cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_icsr = true; + cpu->cfg.ext_zicsr = true; cpu->cfg.pmp = true; } @@ -620,7 +620,7 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj) /* inherited from parent obj via riscv_cpu_init() */ cpu->cfg.ext_zifencei = true; - cpu->cfg.ext_icsr = true; + cpu->cfg.ext_zicsr = true; cpu->cfg.pmp = true; } #endif @@ -1243,7 +1243,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { /* Defaults for standard extensions */ MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false), MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true), - MULTI_EXT_CFG_BOOL("zicsr", ext_icsr, true), + 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("zawrs", ext_zawrs, true), @@ -1348,7 +1348,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { /* Deprecated entries marked for future removal */ const RISCVCPUMultiExtConfig riscv_cpu_deprecated_exts[] = { MULTI_EXT_CFG_BOOL("Zifencei", ext_zifencei, true), - MULTI_EXT_CFG_BOOL("Zicsr", ext_icsr, true), + 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("Zawrs", ext_zawrs, true), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index a3f96eb878..9ea30da7e0 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -62,7 +62,7 @@ struct RISCVCPUConfig { bool ext_zksh; bool ext_zkt; bool ext_zifencei; - bool ext_icsr; + bool ext_zicsr; bool ext_icbom; bool ext_icboz; bool ext_zicond; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 4b4ab56c40..30cc21e979 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3858,7 +3858,7 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, int csr_min_priv = csr_ops[csrno].min_priv_ver; /* ensure the CSR extension is enabled */ - if (!riscv_cpu_cfg(env)->ext_icsr) { + if (!riscv_cpu_cfg(env)->ext_zicsr) { return RISCV_EXCP_ILLEGAL_INST; } diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 524bede865..58b3ace0fe 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -342,7 +342,7 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) g_assert_not_reached(); } - if (cpu->cfg.ext_icsr) { + if (cpu->cfg.ext_zicsr) { int base_reg = cs->gdb_num_regs; gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, riscv_gen_dynamic_csr_xml(cs, base_reg), diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 9b8f3f54a7..418b040d6d 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -278,10 +278,10 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) !(riscv_has_ext(env, RVI) && riscv_has_ext(env, RVM) && riscv_has_ext(env, RVA) && riscv_has_ext(env, RVF) && riscv_has_ext(env, RVD) && - cpu->cfg.ext_icsr && cpu->cfg.ext_zifencei)) { + cpu->cfg.ext_zicsr && cpu->cfg.ext_zifencei)) { - if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_icsr)) && - !cpu->cfg.ext_icsr) { + if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zicsr)) && + !cpu->cfg.ext_zicsr) { error_setg(errp, "RVG requires Zicsr but user set Zicsr to false"); return; } @@ -293,7 +293,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) return; } - cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_icsr), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zicsr), true); cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zifencei), true); env->misa_ext |= RVI | RVM | RVA | RVF | RVD; @@ -329,7 +329,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) return; } - if (riscv_has_ext(env, RVF) && !cpu->cfg.ext_icsr) { + if (riscv_has_ext(env, RVF) && !cpu->cfg.ext_zicsr) { error_setg(errp, "F extension requires Zicsr"); return; } @@ -434,7 +434,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) } if (cpu->cfg.ext_zfinx) { - if (!cpu->cfg.ext_icsr) { + if (!cpu->cfg.ext_zicsr) { error_setg(errp, "Zfinx extension requires Zicsr"); return; } @@ -494,7 +494,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) return; } - if (cpu->cfg.ext_zcmt && !cpu->cfg.ext_icsr) { + if (cpu->cfg.ext_zcmt && !cpu->cfg.ext_zicsr) { error_setg(errp, "Zcmt extension requires Zicsr extension"); return; } From a326a2b0b2afae9285126cb1c56e71926d3702c7 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 12 Oct 2023 13:46:03 -0300 Subject: [PATCH 03/49] target/riscv: rename ext_icbom to ext_zicbom Add a leading 'z' to improve grepping. When one wants to search for uses of zicbom they're more likely to do 'grep -i zicbom' than 'grep -i icbom'. Suggested-by: Andrew Jones Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-ID: <20231012164604.398496-4-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 2 +- target/riscv/cpu.c | 6 +++--- target/riscv/cpu_cfg.h | 2 +- target/riscv/insn_trans/trans_rvzicbo.c.inc | 8 ++++---- target/riscv/kvm/kvm-cpu.c | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 9de578c756..54e0fe8ecc 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -263,7 +263,7 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket, qemu_fdt_setprop_string(ms->fdt, cpu_name, "riscv,isa", name); g_free(name); - if (cpu_ptr->cfg.ext_icbom) { + if (cpu_ptr->cfg.ext_zicbom) { qemu_fdt_setprop_cell(ms->fdt, cpu_name, "riscv,cbom-block-size", cpu_ptr->cfg.cbom_blocksize); } diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 566b7545e8..943d5ecbfb 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -76,7 +76,7 @@ const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV, * instead. */ const RISCVIsaExtData isa_edata_arr[] = { - ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_icbom), + ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_zicbom), ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_icboz), ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond), ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_zicsr), @@ -497,7 +497,7 @@ static void rv64_veyron_v1_cpu_init(Object *obj) cpu->cfg.ext_zifencei = true; cpu->cfg.ext_zicsr = true; cpu->cfg.pmp = true; - cpu->cfg.ext_icbom = true; + cpu->cfg.ext_zicbom = true; cpu->cfg.cbom_blocksize = 64; cpu->cfg.cboz_blocksize = 64; cpu->cfg.ext_icboz = true; @@ -1284,7 +1284,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { MULTI_EXT_CFG_BOOL("zhinx", ext_zhinx, false), MULTI_EXT_CFG_BOOL("zhinxmin", ext_zhinxmin, false), - MULTI_EXT_CFG_BOOL("zicbom", ext_icbom, true), + MULTI_EXT_CFG_BOOL("zicbom", ext_zicbom, true), MULTI_EXT_CFG_BOOL("zicboz", ext_icboz, true), MULTI_EXT_CFG_BOOL("zmmul", ext_zmmul, false), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 9ea30da7e0..e6bef0070f 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -63,7 +63,7 @@ struct RISCVCPUConfig { bool ext_zkt; bool ext_zifencei; bool ext_zicsr; - bool ext_icbom; + bool ext_zicbom; bool ext_icboz; bool ext_zicond; bool ext_zihintntl; diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc b/target/riscv/insn_trans/trans_rvzicbo.c.inc index e5a7704f54..e6ed548376 100644 --- a/target/riscv/insn_trans/trans_rvzicbo.c.inc +++ b/target/riscv/insn_trans/trans_rvzicbo.c.inc @@ -16,10 +16,10 @@ * this program. If not, see . */ -#define REQUIRE_ZICBOM(ctx) do { \ - if (!ctx->cfg_ptr->ext_icbom) { \ - return false; \ - } \ +#define REQUIRE_ZICBOM(ctx) do { \ + if (!ctx->cfg_ptr->ext_zicbom) { \ + return false; \ + } \ } while (0) #define REQUIRE_ZICBOZ(ctx) do { \ diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 26e68c7ab4..4d4c17fd77 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -213,7 +213,7 @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu, CPUState *cs) .kvm_reg_id = _reg_id} static KVMCPUConfig kvm_multi_ext_cfgs[] = { - KVM_EXT_CFG("zicbom", ext_icbom, KVM_RISCV_ISA_EXT_ZICBOM), + KVM_EXT_CFG("zicbom", ext_zicbom, KVM_RISCV_ISA_EXT_ZICBOM), KVM_EXT_CFG("zicboz", ext_icboz, KVM_RISCV_ISA_EXT_ZICBOZ), KVM_EXT_CFG("zihintpause", ext_zihintpause, KVM_RISCV_ISA_EXT_ZIHINTPAUSE), KVM_EXT_CFG("zbb", ext_zbb, KVM_RISCV_ISA_EXT_ZBB), @@ -804,7 +804,7 @@ static void kvm_riscv_read_multiext_legacy(RISCVCPU *cpu, kvm_cpu_cfg_set(cpu, multi_ext_cfg, val); } - if (cpu->cfg.ext_icbom) { + if (cpu->cfg.ext_zicbom) { kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cbom_blocksize); } @@ -897,7 +897,7 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) kvm_cpu_cfg_set(cpu, multi_ext_cfg, val); } - if (cpu->cfg.ext_icbom) { + if (cpu->cfg.ext_zicbom) { kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cbom_blocksize); } From e57039ddab55bb0f711b3bf46d39f887663243a0 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 12 Oct 2023 13:46:04 -0300 Subject: [PATCH 04/49] target/riscv: rename ext_icboz to ext_zicboz Add a leading 'z' to improve grepping. When one wants to search for uses of zicboz they're more likely to do 'grep -i zicboz' than 'grep -i icboz'. Suggested-by: Andrew Jones Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-ID: <20231012164604.398496-5-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 2 +- target/riscv/cpu.c | 6 +++--- target/riscv/cpu_cfg.h | 2 +- target/riscv/insn_trans/trans_rvzicbo.c.inc | 8 ++++---- target/riscv/kvm/kvm-cpu.c | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 54e0fe8ecc..1732c42915 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -268,7 +268,7 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket, cpu_ptr->cfg.cbom_blocksize); } - if (cpu_ptr->cfg.ext_icboz) { + if (cpu_ptr->cfg.ext_zicboz) { qemu_fdt_setprop_cell(ms->fdt, cpu_name, "riscv,cboz-block-size", cpu_ptr->cfg.cboz_blocksize); } diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 943d5ecbfb..efafc0ba0b 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -77,7 +77,7 @@ const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV, */ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_zicbom), - ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_icboz), + ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_zicboz), ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond), ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_zicsr), ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_zifencei), @@ -500,7 +500,7 @@ static void rv64_veyron_v1_cpu_init(Object *obj) cpu->cfg.ext_zicbom = true; cpu->cfg.cbom_blocksize = 64; cpu->cfg.cboz_blocksize = 64; - cpu->cfg.ext_icboz = true; + cpu->cfg.ext_zicboz = true; cpu->cfg.ext_smaia = true; cpu->cfg.ext_ssaia = true; cpu->cfg.ext_sscofpmf = true; @@ -1285,7 +1285,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { MULTI_EXT_CFG_BOOL("zhinxmin", ext_zhinxmin, false), MULTI_EXT_CFG_BOOL("zicbom", ext_zicbom, true), - MULTI_EXT_CFG_BOOL("zicboz", ext_icboz, true), + MULTI_EXT_CFG_BOOL("zicboz", ext_zicboz, true), MULTI_EXT_CFG_BOOL("zmmul", ext_zmmul, false), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index e6bef0070f..208cac1c7c 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -64,7 +64,7 @@ struct RISCVCPUConfig { bool ext_zifencei; bool ext_zicsr; bool ext_zicbom; - bool ext_icboz; + bool ext_zicboz; bool ext_zicond; bool ext_zihintntl; bool ext_zihintpause; diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc b/target/riscv/insn_trans/trans_rvzicbo.c.inc index e6ed548376..d5d7095903 100644 --- a/target/riscv/insn_trans/trans_rvzicbo.c.inc +++ b/target/riscv/insn_trans/trans_rvzicbo.c.inc @@ -22,10 +22,10 @@ } \ } while (0) -#define REQUIRE_ZICBOZ(ctx) do { \ - if (!ctx->cfg_ptr->ext_icboz) { \ - return false; \ - } \ +#define REQUIRE_ZICBOZ(ctx) do { \ + if (!ctx->cfg_ptr->ext_zicboz) { \ + return false; \ + } \ } while (0) static bool trans_cbo_clean(DisasContext *ctx, arg_cbo_clean *a) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 4d4c17fd77..6e1678542b 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -214,7 +214,7 @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu, CPUState *cs) static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zicbom", ext_zicbom, KVM_RISCV_ISA_EXT_ZICBOM), - KVM_EXT_CFG("zicboz", ext_icboz, KVM_RISCV_ISA_EXT_ZICBOZ), + KVM_EXT_CFG("zicboz", ext_zicboz, KVM_RISCV_ISA_EXT_ZICBOZ), KVM_EXT_CFG("zihintpause", ext_zihintpause, KVM_RISCV_ISA_EXT_ZIHINTPAUSE), KVM_EXT_CFG("zbb", ext_zbb, KVM_RISCV_ISA_EXT_ZBB), KVM_EXT_CFG("ssaia", ext_ssaia, KVM_RISCV_ISA_EXT_SSAIA), @@ -808,7 +808,7 @@ static void kvm_riscv_read_multiext_legacy(RISCVCPU *cpu, kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cbom_blocksize); } - if (cpu->cfg.ext_icboz) { + if (cpu->cfg.ext_zicboz) { kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cboz_blocksize); } } @@ -901,7 +901,7 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cbom_blocksize); } - if (cpu->cfg.ext_icboz) { + if (cpu->cfg.ext_zicboz) { kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cboz_blocksize); } } From a7b69170254b15b5a40b318ed5559084ccfc466b Mon Sep 17 00:00:00 2001 From: Rajnesh Kanwal Date: Mon, 16 Oct 2023 12:17:31 +0100 Subject: [PATCH 05/49] target/riscv: Without H-mode mask all HS mode inturrupts in mie. Signed-off-by: Rajnesh Kanwal Reviewed-by: Alistair Francis Message-ID: <20231016111736.28721-2-rkanwal@rivosinc.com> Signed-off-by: Alistair Francis --- 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 30cc21e979..4847b47a98 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1525,7 +1525,7 @@ static RISCVException rmw_mie64(CPURISCVState *env, int csrno, env->mie = (env->mie & ~mask) | (new_val & mask); if (!riscv_has_ext(env, RVH)) { - env->mie &= ~((uint64_t)MIP_SGEIP); + env->mie &= ~((uint64_t)HS_MODE_INTERRUPTS); } return RISCV_EXCP_NONE; From d17bcae5f7e9f949052a1f126a7f23e7279b6d96 Mon Sep 17 00:00:00 2001 From: Rajnesh Kanwal Date: Mon, 16 Oct 2023 12:17:32 +0100 Subject: [PATCH 06/49] target/riscv: Check for async flag in case of RISCV_EXCP_SEMIHOST. RISCV_EXCP_SEMIHOST is set to 0x10, which can be a local interrupt id as well. This change moves RISCV_EXCP_SEMIHOST to switch case so that async flag check is performed before invoking semihosting logic. Signed-off-by: Rajnesh Kanwal Reviewed-by: Alistair Francis Message-ID: <20231016111736.28721-3-rkanwal@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu_helper.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 8c28241c18..aaeb1d0d5c 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -1605,15 +1605,13 @@ void riscv_cpu_do_interrupt(CPUState *cs) target_ulong htval = 0; target_ulong mtval2 = 0; - if (cause == RISCV_EXCP_SEMIHOST) { - do_common_semihosting(cs); - env->pc += 4; - return; - } - if (!async) { /* set tval to badaddr for traps with address information */ switch (cause) { + case RISCV_EXCP_SEMIHOST: + do_common_semihosting(cs); + env->pc += 4; + return; case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT: case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT: case RISCV_EXCP_LOAD_ADDR_MIS: From b901c7eb701a8f4d512be3a70958150fc5d0cd90 Mon Sep 17 00:00:00 2001 From: Rajnesh Kanwal Date: Mon, 16 Oct 2023 12:17:33 +0100 Subject: [PATCH 07/49] target/riscv: Set VS* bits to one in mideleg when H-Ext is enabled With H-Ext supported, VS bits are all hardwired to one in MIDELEG denoting always delegated interrupts. This is being done in rmw_mideleg but given mideleg is used in other places when routing interrupts this change initializes it in riscv_cpu_realize to be on the safe side. Signed-off-by: Rajnesh Kanwal Reviewed-by: Alistair Francis Message-ID: <20231016111736.28721-4-rkanwal@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/tcg/tcg-cpu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 418b040d6d..bbce254ee1 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -618,7 +618,12 @@ static bool tcg_cpu_realize(CPUState *cs, Error **errp) cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, riscv_pmu_timer_cb, cpu); } - } + } + + /* With H-Ext, VSSIP, VSTIP, VSEIP and SGEIP are hardwired to one. */ + if (riscv_has_ext(env, RVH)) { + env->mideleg = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP | MIP_SGEIP; + } #endif return true; From 1ebad505f3d5108513bf150b901344caceb3a7c1 Mon Sep 17 00:00:00 2001 From: Rajnesh Kanwal Date: Mon, 16 Oct 2023 12:17:34 +0100 Subject: [PATCH 08/49] target/riscv: Split interrupt logic from riscv_cpu_update_mip. This is to allow virtual interrupts to be inserted into S and VS modes. Given virtual interrupts will be maintained in separate mvip and hvip CSRs, riscv_cpu_update_mip will no longer be in the path and interrupts need to be triggered for these cases from rmw_hvip64 and rmw_mvip64 functions. Signed-off-by: Rajnesh Kanwal Reviewed-by: Alistair Francis Message-ID: <20231016111736.28721-5-rkanwal@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 1 + target/riscv/cpu_helper.c | 25 ++++++++++++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index f8ffa5ee38..6fe32e6b38 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -463,6 +463,7 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env); int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts); uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, uint64_t value); +void riscv_cpu_interrupt(CPURISCVState *env); #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */ void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *), void *arg); diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index aaeb1d0d5c..581b8c6380 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -620,11 +620,12 @@ int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts) } } -uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, - uint64_t value) +void riscv_cpu_interrupt(CPURISCVState *env) { + uint64_t gein, vsgein = 0, vstip = 0; CPUState *cs = env_cpu(env); - uint64_t gein, vsgein = 0, vstip = 0, old = env->mip; + + QEMU_IOTHREAD_LOCK_GUARD(); if (env->virt_enabled) { gein = get_field(env->hstatus, HSTATUS_VGEIN); @@ -633,15 +634,25 @@ uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, vstip = env->vstime_irq ? MIP_VSTIP : 0; - QEMU_IOTHREAD_LOCK_GUARD(); - - env->mip = (env->mip & ~mask) | (value & mask); - if (env->mip | vsgein | vstip) { cpu_interrupt(cs, CPU_INTERRUPT_HARD); } else { cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); } +} + +uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, uint64_t value) +{ + uint64_t old = env->mip; + + /* No need to update mip for VSTIP */ + mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 : mask; + + QEMU_IOTHREAD_LOCK_GUARD(); + + env->mip = (env->mip & ~mask) | (value & mask); + + riscv_cpu_interrupt(env); return old; } From 1697837ed98cf56a6f65edd06128151f83b99403 Mon Sep 17 00:00:00 2001 From: Rajnesh Kanwal Date: Mon, 16 Oct 2023 12:17:35 +0100 Subject: [PATCH 09/49] target/riscv: Add M-mode virtual interrupt and IRQ filtering support. This change adds support for inserting virtual interrupts from M-mode into S-mode using mvien and mvip csrs. IRQ filtering is a use case of this change, i-e M-mode can stop delegating an interrupt to S-mode and instead enable it in MIE and receive those interrupts in M-mode and then selectively inject the interrupt using mvien and mvip. Also, the spec doesn't mandate the interrupt to be actually supported in hardware. Which allows M-mode to assert virtual interrupts to S-mode that have no connection to any real interrupt events. This is defined as part of the AIA specification [0], "5.3 Interrupt filtering and virtual interrupts for supervisor level". [0]: https://github.com/riscv/riscv-aia/releases/download/1.0/riscv-interrupts-1.0.pdf Signed-off-by: Rajnesh Kanwal Reviewed-by: Daniel Henrique Barboza Message-ID: <20231016111736.28721-6-rkanwal@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 3 +- target/riscv/cpu.h | 8 ++ target/riscv/cpu_bits.h | 6 + target/riscv/cpu_helper.c | 26 +++- target/riscv/csr.c | 279 ++++++++++++++++++++++++++++++++++---- target/riscv/machine.c | 7 +- 6 files changed, 291 insertions(+), 38 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index efafc0ba0b..859ac59c6c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -813,7 +813,8 @@ static bool riscv_cpu_has_work(CPUState *cs) * Definition of the WFI instruction requires it to ignore the privilege * mode and delegation registers, but respect individual enables */ - return riscv_cpu_all_pending(env) != 0; + return riscv_cpu_all_pending(env) != 0 || + riscv_cpu_sirq_pending(env) != RISCV_EXCP_NONE; #else return true; #endif diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6fe32e6b38..30f9481f45 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -202,6 +202,12 @@ struct CPUArchState { uint64_t mie; uint64_t mideleg; + /* + * When mideleg[i]=0 and mvien[i]=1, sie[i] is no more + * alias of mie[i] and needs to be maintained separatly. + */ + uint64_t sie; + target_ulong satp; /* since: priv-1.10.0 */ target_ulong stval; target_ulong medeleg; @@ -222,6 +228,8 @@ struct CPUArchState { /* AIA CSRs */ target_ulong miselect; target_ulong siselect; + uint64_t mvien; + uint64_t mvip; /* Hypervisor CSRs */ target_ulong hstatus; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 3d6ffaabc7..ebd7917d49 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -735,6 +735,12 @@ typedef enum RISCVException { #define MIE_SSIE (1 << IRQ_S_SOFT) #define MIE_USIE (1 << IRQ_U_SOFT) +/* Machine constants */ +#define M_MODE_INTERRUPTS ((uint64_t)(MIP_MSIP | MIP_MTIP | MIP_MEIP)) +#define S_MODE_INTERRUPTS ((uint64_t)(MIP_SSIP | MIP_STIP | MIP_SEIP)) +#define VS_MODE_INTERRUPTS ((uint64_t)(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)) +#define HS_MODE_INTERRUPTS ((uint64_t)(MIP_SGEIP | VS_MODE_INTERRUPTS)) + /* General PointerMasking CSR bits */ #define PM_ENABLE 0x00000001ULL #define PM_CURRENT 0x00000002ULL diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 581b8c6380..b36161708a 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -376,6 +376,10 @@ static int riscv_cpu_pending_to_irq(CPURISCVState *env, return best_irq; } +/* + * Doesn't report interrupts inserted using mvip from M-mode firmware. Those + * are returned in riscv_cpu_sirq_pending(). + */ uint64_t riscv_cpu_all_pending(CPURISCVState *env) { uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN); @@ -398,9 +402,10 @@ int riscv_cpu_sirq_pending(CPURISCVState *env) { uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP); + uint64_t irqs_f = env->mvip & env->mvien & ~env->mideleg & env->sie; return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S, - irqs, env->siprio); + irqs | irqs_f, env->siprio); } int riscv_cpu_vsirq_pending(CPURISCVState *env) @@ -414,8 +419,8 @@ int riscv_cpu_vsirq_pending(CPURISCVState *env) static int riscv_cpu_local_irq_pending(CPURISCVState *env) { + uint64_t irqs, pending, mie, hsie, vsie, irqs_f; int virq; - uint64_t irqs, pending, mie, hsie, vsie; /* Determine interrupt enable state of all privilege modes */ if (env->virt_enabled) { @@ -441,8 +446,11 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env) irqs, env->miprio); } + /* Check for virtual S-mode interrupts. */ + irqs_f = env->mvip & (env->mvien & ~env->mideleg) & env->sie; + /* Check HS-mode interrupts */ - irqs = pending & env->mideleg & ~env->hideleg & -hsie; + irqs = ((pending & env->mideleg & ~env->hideleg) | irqs_f) & -hsie; if (irqs) { return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S, irqs, env->siprio); @@ -622,7 +630,7 @@ int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts) void riscv_cpu_interrupt(CPURISCVState *env) { - uint64_t gein, vsgein = 0, vstip = 0; + uint64_t gein, vsgein = 0, vstip = 0, irqf = 0; CPUState *cs = env_cpu(env); QEMU_IOTHREAD_LOCK_GUARD(); @@ -630,11 +638,13 @@ void riscv_cpu_interrupt(CPURISCVState *env) if (env->virt_enabled) { gein = get_field(env->hstatus, HSTATUS_VGEIN); vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; + } else { + irqf = env->mvien & env->mvip & env->sie; } vstip = env->vstime_irq ? MIP_VSTIP : 0; - if (env->mip | vsgein | vstip) { + if (env->mip | vsgein | vstip | irqf) { cpu_interrupt(cs, CPU_INTERRUPT_HARD); } else { cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); @@ -1611,6 +1621,8 @@ void riscv_cpu_do_interrupt(CPUState *cs) bool async = !!(cs->exception_index & RISCV_EXCP_INT_FLAG); target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK; uint64_t deleg = async ? env->mideleg : env->medeleg; + bool s_injected = env->mvip & (1 << cause) & env->mvien && + !(env->mip & (1 << cause)); target_ulong tval = 0; target_ulong tinst = 0; target_ulong htval = 0; @@ -1699,8 +1711,8 @@ void riscv_cpu_do_interrupt(CPUState *cs) __func__, env->mhartid, async, cause, env->pc, tval, riscv_cpu_get_trap_name(cause, async)); - if (env->priv <= PRV_S && - cause < TARGET_LONG_BITS && ((deleg >> cause) & 1)) { + if (env->priv <= PRV_S && cause < 64 && + (((deleg >> cause) & 1) || s_injected)) { /* handle the trap in S-mode */ if (riscv_has_ext(env, RVH)) { uint64_t hdeleg = async ? env->hideleg : env->hedeleg; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 4847b47a98..645f30f028 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1117,21 +1117,16 @@ static RISCVException write_stimecmph(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -/* Machine constants */ - -#define M_MODE_INTERRUPTS ((uint64_t)(MIP_MSIP | MIP_MTIP | MIP_MEIP)) -#define S_MODE_INTERRUPTS ((uint64_t)(MIP_SSIP | MIP_STIP | MIP_SEIP | \ - MIP_LCOFIP)) -#define VS_MODE_INTERRUPTS ((uint64_t)(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)) -#define HS_MODE_INTERRUPTS ((uint64_t)(MIP_SGEIP | VS_MODE_INTERRUPTS)) - #define VSTOPI_NUM_SRCS 5 -static const uint64_t delegable_ints = S_MODE_INTERRUPTS | - VS_MODE_INTERRUPTS; -static const uint64_t vs_delegable_ints = VS_MODE_INTERRUPTS; +#define LOCAL_INTERRUPTS (~0x1FFF) + +static const uint64_t delegable_ints = + S_MODE_INTERRUPTS | VS_MODE_INTERRUPTS | MIP_LCOFIP; +static const uint64_t vs_delegable_ints = + (VS_MODE_INTERRUPTS | LOCAL_INTERRUPTS) & ~MIP_LCOFIP; static const uint64_t all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS | - HS_MODE_INTERRUPTS; + HS_MODE_INTERRUPTS | LOCAL_INTERRUPTS; #define DELEGABLE_EXCPS ((1ULL << (RISCV_EXCP_INST_ADDR_MIS)) | \ (1ULL << (RISCV_EXCP_INST_ACCESS_FAULT)) | \ (1ULL << (RISCV_EXCP_ILLEGAL_INST)) | \ @@ -1162,12 +1157,30 @@ static const target_ulong vs_delegable_excps = DELEGABLE_EXCPS & static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS; -static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP | - SIP_LCOFIP; + +/* + * Spec allows for bits 13:63 to be either read-only or writable. + * So far we have interrupt LCOFIP in that region which is writable. + * + * Also, spec allows to inject virtual interrupts in this region even + * without any hardware interrupts for that interrupt number. + * + * For now interrupt in 13:63 region are all kept writable. 13 being + * LCOFIP and 14:63 being virtual only. Change this in future if we + * introduce more interrupts that are not writable. + */ + +/* Bit STIP can be an alias of mip.STIP that's why it's writable in mvip. */ +static const target_ulong mvip_writable_mask = MIP_SSIP | MIP_STIP | MIP_SEIP | + LOCAL_INTERRUPTS; +static const target_ulong mvien_writable_mask = MIP_SSIP | MIP_SEIP | + LOCAL_INTERRUPTS; + +static const target_ulong sip_writable_mask = SIP_SSIP | LOCAL_INTERRUPTS; static const target_ulong hip_writable_mask = MIP_VSSIP; static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | - MIP_VSEIP; -static const target_ulong vsip_writable_mask = MIP_VSSIP; + MIP_VSEIP | LOCAL_INTERRUPTS; +static const target_ulong vsip_writable_mask = MIP_VSSIP | LOCAL_INTERRUPTS; const bool valid_vm_1_10_32[16] = { [VM_1_10_MBARE] = true, @@ -1562,6 +1575,52 @@ static RISCVException rmw_mieh(CPURISCVState *env, int csrno, return ret; } +static RISCVException rmw_mvien64(CPURISCVState *env, int csrno, + uint64_t *ret_val, + uint64_t new_val, uint64_t wr_mask) +{ + uint64_t mask = wr_mask & mvien_writable_mask; + + if (ret_val) { + *ret_val = env->mvien; + } + + env->mvien = (env->mvien & ~mask) | (new_val & mask); + + return RISCV_EXCP_NONE; +} + +static RISCVException rmw_mvien(CPURISCVState *env, int csrno, + target_ulong *ret_val, + target_ulong new_val, target_ulong wr_mask) +{ + uint64_t rval; + RISCVException ret; + + ret = rmw_mvien64(env, csrno, &rval, new_val, wr_mask); + if (ret_val) { + *ret_val = rval; + } + + return ret; +} + +static RISCVException rmw_mvienh(CPURISCVState *env, int csrno, + target_ulong *ret_val, + target_ulong new_val, target_ulong wr_mask) +{ + uint64_t rval; + RISCVException ret; + + ret = rmw_mvien64(env, csrno, &rval, + ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32); + if (ret_val) { + *ret_val = rval >> 32; + } + + return ret; +} + static int read_mtopi(CPURISCVState *env, int csrno, target_ulong *val) { int irq; @@ -1703,6 +1762,11 @@ static int rmw_xireg(CPURISCVState *env, int csrno, target_ulong *val, priv = PRV_M; break; case CSR_SIREG: + if (env->priv == PRV_S && env->mvien & MIP_SEIP && + env->siselect >= ISELECT_IMSIC_EIDELIVERY && + env->siselect <= ISELECT_IMSIC_EIE63) { + goto done; + } iprio = env->siprio; isel = env->siselect; priv = PRV_S; @@ -1769,6 +1833,9 @@ static int rmw_xtopei(CPURISCVState *env, int csrno, target_ulong *val, priv = PRV_M; break; case CSR_STOPEI: + if (env->mvien & MIP_SEIP && env->priv == PRV_S) { + goto done; + } priv = PRV_S; break; case CSR_VSTOPEI: @@ -2360,6 +2427,143 @@ static RISCVException rmw_miph(CPURISCVState *env, int csrno, return ret; } +/* + * The function is written for two use-cases: + * 1- To access mvip csr as is for m-mode access. + * 2- To access sip as a combination of mip and mvip for s-mode. + * + * Both report bits 1, 5, 9 and 13:63 but with the exception of + * STIP being read-only zero in case of mvip when sstc extension + * is present. + * Also, sip needs to be read-only zero when both mideleg[i] and + * mvien[i] are zero but mvip needs to be an alias of mip. + */ +static RISCVException rmw_mvip64(CPURISCVState *env, int csrno, + uint64_t *ret_val, + uint64_t new_val, uint64_t wr_mask) +{ + RISCVCPU *cpu = env_archcpu(env); + target_ulong ret_mip = 0; + RISCVException ret; + uint64_t old_mvip; + + /* + * mideleg[i] mvien[i] + * 0 0 No delegation. mvip[i] is alias of mip[i]. + * 0 1 mvip[i] becomes source of interrupt, mip bypassed. + * 1 X mip[i] is source of interrupt and mvip[i] aliases + * mip[i]. + * + * So alias condition would be for bits: + * ((S_MODE_INTERRUPTS | LOCAL_INTERRUPTS) & (mideleg | ~mvien)) | + * (!sstc & MIP_STIP) + * + * Non-alias condition will be for bits: + * (S_MODE_INTERRUPTS | LOCAL_INTERRUPTS) & (~mideleg & mvien) + * + * alias_mask denotes the bits that come from mip nalias_mask denotes bits + * that come from hvip. + */ + uint64_t alias_mask = ((S_MODE_INTERRUPTS | LOCAL_INTERRUPTS) & + (env->mideleg | ~env->mvien)) | MIP_STIP; + uint64_t nalias_mask = (S_MODE_INTERRUPTS | LOCAL_INTERRUPTS) & + (~env->mideleg & env->mvien); + uint64_t wr_mask_mvip; + uint64_t wr_mask_mip; + + /* + * mideleg[i] mvien[i] + * 0 0 sip[i] read-only zero. + * 0 1 sip[i] alias of mvip[i]. + * 1 X sip[i] alias of mip[i]. + * + * Both alias and non-alias mask remain same for sip except for bits + * which are zero in both mideleg and mvien. + */ + if (csrno == CSR_SIP) { + /* Remove bits that are zero in both mideleg and mvien. */ + alias_mask &= (env->mideleg | env->mvien); + nalias_mask &= (env->mideleg | env->mvien); + } + + /* + * If sstc is present, mvip.STIP is not an alias of mip.STIP so clear + * that our in mip returned value. + */ + if (cpu->cfg.ext_sstc && (env->priv == PRV_M) && + get_field(env->menvcfg, MENVCFG_STCE)) { + alias_mask &= ~MIP_STIP; + } + + wr_mask_mip = wr_mask & alias_mask & mvip_writable_mask; + wr_mask_mvip = wr_mask & nalias_mask & mvip_writable_mask; + + /* + * For bits set in alias_mask, mvip needs to be alias of mip, so forward + * this to rmw_mip. + */ + ret = rmw_mip(env, CSR_MIP, &ret_mip, new_val, wr_mask_mip); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + old_mvip = env->mvip; + + /* + * Write to mvip. Update only non-alias bits. Alias bits were updated + * in mip in rmw_mip above. + */ + if (wr_mask_mvip) { + env->mvip = (env->mvip & ~wr_mask_mvip) | (new_val & wr_mask_mvip); + + /* + * Given mvip is separate source from mip, we need to trigger interrupt + * from here separately. Normally this happen from riscv_cpu_update_mip. + */ + riscv_cpu_interrupt(env); + } + + if (ret_val) { + ret_mip &= alias_mask; + old_mvip &= nalias_mask; + + *ret_val = old_mvip | ret_mip; + } + + return RISCV_EXCP_NONE; +} + +static RISCVException rmw_mvip(CPURISCVState *env, int csrno, + target_ulong *ret_val, + target_ulong new_val, target_ulong wr_mask) +{ + uint64_t rval; + RISCVException ret; + + ret = rmw_mvip64(env, csrno, &rval, new_val, wr_mask); + if (ret_val) { + *ret_val = rval; + } + + return ret; +} + +static RISCVException rmw_mviph(CPURISCVState *env, int csrno, + target_ulong *ret_val, + target_ulong new_val, target_ulong wr_mask) +{ + uint64_t rval; + RISCVException ret; + + ret = rmw_mvip64(env, csrno, &rval, + ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32); + if (ret_val) { + *ret_val = rval >> 32; + } + + return ret; +} + /* Supervisor Trap Setup */ static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno, Int128 *val) @@ -2454,20 +2658,37 @@ static RISCVException rmw_sie64(CPURISCVState *env, int csrno, uint64_t *ret_val, uint64_t new_val, uint64_t wr_mask) { + uint64_t nalias_mask = (S_MODE_INTERRUPTS | LOCAL_INTERRUPTS) & + (~env->mideleg & env->mvien); + uint64_t alias_mask = (S_MODE_INTERRUPTS | LOCAL_INTERRUPTS) & env->mideleg; + uint64_t sie_mask = wr_mask & nalias_mask; RISCVException ret; - uint64_t mask = env->mideleg & S_MODE_INTERRUPTS; + /* + * mideleg[i] mvien[i] + * 0 0 sie[i] read-only zero. + * 0 1 sie[i] is a separate writable bit. + * 1 X sie[i] alias of mie[i]. + * + * Both alias and non-alias mask remain same for sip except for bits + * which are zero in both mideleg and mvien. + */ if (env->virt_enabled) { if (env->hvictl & HVICTL_VTI) { return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } ret = rmw_vsie64(env, CSR_VSIE, ret_val, new_val, wr_mask); + if (ret_val) { + *ret_val &= alias_mask; + } } else { - ret = rmw_mie64(env, csrno, ret_val, new_val, wr_mask & mask); - } + ret = rmw_mie64(env, csrno, ret_val, new_val, wr_mask & alias_mask); + if (ret_val) { + *ret_val &= alias_mask; + *ret_val |= env->sie & nalias_mask; + } - if (ret_val) { - *ret_val &= mask; + env->sie = (env->sie & ~sie_mask) | (new_val & sie_mask); } return ret; @@ -2665,7 +2886,7 @@ static RISCVException rmw_sip64(CPURISCVState *env, int csrno, uint64_t new_val, uint64_t wr_mask) { RISCVException ret; - uint64_t mask = env->mideleg & sip_writable_mask; + uint64_t mask = (env->mideleg | env->mvien) & sip_writable_mask; if (env->virt_enabled) { if (env->hvictl & HVICTL_VTI) { @@ -2673,11 +2894,12 @@ static RISCVException rmw_sip64(CPURISCVState *env, int csrno, } ret = rmw_vsip64(env, CSR_VSIP, ret_val, new_val, wr_mask); } else { - ret = rmw_mip64(env, csrno, ret_val, new_val, wr_mask & mask); + ret = rmw_mvip64(env, csrno, ret_val, new_val, wr_mask & mask); } if (ret_val) { - *ret_val &= env->mideleg & S_MODE_INTERRUPTS; + *ret_val &= (env->mideleg | env->mvien) & + (S_MODE_INTERRUPTS | LOCAL_INTERRUPTS); } return ret; @@ -2842,6 +3064,7 @@ static int read_vstopi(CPURISCVState *env, int csrno, target_ulong *val) *val = (iid & TOPI_IID_MASK) << TOPI_IID_SHIFT; *val |= iprio; + return RISCV_EXCP_NONE; } @@ -4165,14 +4388,14 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MTOPI] = { "mtopi", aia_any, read_mtopi }, /* Virtual Interrupts for Supervisor Level (AIA) */ - [CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore }, - [CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore }, + [CSR_MVIEN] = { "mvien", aia_any, NULL, NULL, rmw_mvien }, + [CSR_MVIP] = { "mvip", aia_any, NULL, NULL, rmw_mvip }, /* Machine-Level High-Half CSRs (AIA) */ [CSR_MIDELEGH] = { "midelegh", aia_any32, NULL, NULL, rmw_midelegh }, [CSR_MIEH] = { "mieh", aia_any32, NULL, NULL, rmw_mieh }, - [CSR_MVIENH] = { "mvienh", aia_any32, read_zero, write_ignore }, - [CSR_MVIPH] = { "mviph", aia_any32, read_zero, write_ignore }, + [CSR_MVIENH] = { "mvienh", aia_any32, NULL, NULL, rmw_mvienh }, + [CSR_MVIPH] = { "mviph", aia_any32, NULL, NULL, rmw_mviph }, [CSR_MIPH] = { "miph", aia_any32, NULL, NULL, rmw_miph }, /* Execution environment configuration */ diff --git a/target/riscv/machine.c b/target/riscv/machine.c index c7c862cdd3..f65a95f9e7 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -351,8 +351,8 @@ static const VMStateDescription vmstate_jvt = { const VMStateDescription vmstate_riscv_cpu = { .name = "cpu", - .version_id = 8, - .minimum_version_id = 8, + .version_id = 9, + .minimum_version_id = 9, .post_load = riscv_cpu_post_load, .fields = (VMStateField[]) { VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), @@ -379,6 +379,9 @@ const VMStateDescription vmstate_riscv_cpu = { VMSTATE_UINT64(env.mip, RISCVCPU), VMSTATE_UINT64(env.miclaim, RISCVCPU), VMSTATE_UINT64(env.mie, RISCVCPU), + VMSTATE_UINT64(env.mvien, RISCVCPU), + VMSTATE_UINT64(env.mvip, RISCVCPU), + VMSTATE_UINT64(env.sie, RISCVCPU), VMSTATE_UINT64(env.mideleg, RISCVCPU), VMSTATE_UINTTL(env.satp, RISCVCPU), VMSTATE_UINTTL(env.stval, RISCVCPU), From 40336d5b1d4c6b8b8b38c77fda254457d44fe90b Mon Sep 17 00:00:00 2001 From: Rajnesh Kanwal Date: Mon, 16 Oct 2023 12:17:36 +0100 Subject: [PATCH 10/49] target/riscv: Add HS-mode virtual interrupt and IRQ filtering support. This change adds support for inserting virtual interrupts from HS-mode into VS-mode using hvien and hvip csrs. This also allows for IRQ filtering from HS-mode. Also, the spec doesn't mandate the interrupt to be actually supported in hardware. Which allows HS-mode to assert virtual interrupts to VS-mode that have no connection to any real interrupt events. This is defined as part of the AIA specification [0], "6.3.2 Virtual interrupts for VS level". [0]: https://github.com/riscv/riscv-aia/releases/download/1.0/riscv-interrupts-1.0.pdf Signed-off-by: Rajnesh Kanwal Reviewed-by: Daniel Henrique Barboza Message-ID: <20231016111736.28721-7-rkanwal@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 3 +- target/riscv/cpu.h | 14 +++ target/riscv/cpu_helper.c | 48 +++++++--- target/riscv/csr.c | 194 ++++++++++++++++++++++++++++++++++---- target/riscv/machine.c | 7 +- 5 files changed, 235 insertions(+), 31 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 859ac59c6c..2f98ce56e0 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -814,7 +814,8 @@ static bool riscv_cpu_has_work(CPUState *cs) * mode and delegation registers, but respect individual enables */ return riscv_cpu_all_pending(env) != 0 || - riscv_cpu_sirq_pending(env) != RISCV_EXCP_NONE; + riscv_cpu_sirq_pending(env) != RISCV_EXCP_NONE || + riscv_cpu_vsirq_pending(env) != RISCV_EXCP_NONE; #else return true; #endif diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 30f9481f45..7f61e17202 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -208,6 +208,12 @@ struct CPUArchState { */ uint64_t sie; + /* + * When hideleg[i]=0 and hvien[i]=1, vsie[i] is no more + * alias of sie[i] (mie[i]) and needs to be maintained separatly. + */ + uint64_t vsie; + target_ulong satp; /* since: priv-1.10.0 */ target_ulong stval; target_ulong medeleg; @@ -242,6 +248,14 @@ struct CPUArchState { target_ulong hgeie; target_ulong hgeip; uint64_t htimedelta; + uint64_t hvien; + + /* + * Bits VSSIP, VSTIP and VSEIP in hvip are maintained in mip. Other bits + * from 0:12 are reserved. Bits 13:63 are not aliased and must be separately + * maintain in hvip. + */ + uint64_t hvip; /* Hypervisor controlled virtual interrupt priorities */ target_ulong hvictl; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index b36161708a..b7af69de53 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -377,8 +377,9 @@ static int riscv_cpu_pending_to_irq(CPURISCVState *env, } /* - * Doesn't report interrupts inserted using mvip from M-mode firmware. Those - * are returned in riscv_cpu_sirq_pending(). + * Doesn't report interrupts inserted using mvip from M-mode firmware or + * using hvip bits 13:63 from HS-mode. Those are returned in + * riscv_cpu_sirq_pending() and riscv_cpu_vsirq_pending(). */ uint64_t riscv_cpu_all_pending(CPURISCVState *env) { @@ -410,16 +411,23 @@ int riscv_cpu_sirq_pending(CPURISCVState *env) int riscv_cpu_vsirq_pending(CPURISCVState *env) { - uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & - (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP); + uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & env->hideleg; + uint64_t irqs_f_vs = env->hvip & env->hvien & ~env->hideleg & env->vsie; + uint64_t vsbits; + + /* Bring VS-level bits to correct position */ + vsbits = irqs & VS_MODE_INTERRUPTS; + irqs &= ~VS_MODE_INTERRUPTS; + irqs |= vsbits >> 1; return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S, - irqs >> 1, env->hviprio); + (irqs | irqs_f_vs), env->hviprio); } static int riscv_cpu_local_irq_pending(CPURISCVState *env) { - uint64_t irqs, pending, mie, hsie, vsie, irqs_f; + uint64_t irqs, pending, mie, hsie, vsie, irqs_f, irqs_f_vs; + uint64_t vsbits, irq_delegated; int virq; /* Determine interrupt enable state of all privilege modes */ @@ -456,12 +464,26 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env) irqs, env->siprio); } + /* Check for virtual VS-mode interrupts. */ + irqs_f_vs = env->hvip & env->hvien & ~env->hideleg & env->vsie; + /* Check VS-mode interrupts */ - irqs = pending & env->mideleg & env->hideleg & -vsie; + irq_delegated = pending & env->mideleg & env->hideleg; + + /* Bring VS-level bits to correct position */ + vsbits = irq_delegated & VS_MODE_INTERRUPTS; + irq_delegated &= ~VS_MODE_INTERRUPTS; + irq_delegated |= vsbits >> 1; + + irqs = (irq_delegated | irqs_f_vs) & -vsie; if (irqs) { virq = riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S, - irqs >> 1, env->hviprio); - return (virq <= 0) ? virq : virq + 1; + irqs, env->hviprio); + if (virq <= 0 || (virq > 12 && virq <= 63)) { + return virq; + } else { + return virq + 1; + } } /* Indicate no pending interrupt */ @@ -638,6 +660,7 @@ void riscv_cpu_interrupt(CPURISCVState *env) if (env->virt_enabled) { gein = get_field(env->hstatus, HSTATUS_VGEIN); vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; + irqf = env->hvien & env->hvip & env->vsie; } else { irqf = env->mvien & env->mvip & env->sie; } @@ -1623,6 +1646,8 @@ void riscv_cpu_do_interrupt(CPUState *cs) uint64_t deleg = async ? env->mideleg : env->medeleg; bool s_injected = env->mvip & (1 << cause) & env->mvien && !(env->mip & (1 << cause)); + bool vs_injected = env->hvip & (1 << cause) & env->hvien && + !(env->mip & (1 << cause)); target_ulong tval = 0; target_ulong tinst = 0; target_ulong htval = 0; @@ -1712,12 +1737,13 @@ void riscv_cpu_do_interrupt(CPUState *cs) riscv_cpu_get_trap_name(cause, async)); if (env->priv <= PRV_S && cause < 64 && - (((deleg >> cause) & 1) || s_injected)) { + (((deleg >> cause) & 1) || s_injected || vs_injected)) { /* handle the trap in S-mode */ if (riscv_has_ext(env, RVH)) { uint64_t hdeleg = async ? env->hideleg : env->hedeleg; - if (env->virt_enabled && ((hdeleg >> cause) & 1)) { + if (env->virt_enabled && + (((hdeleg >> cause) & 1) || vs_injected)) { /* Trap to VS mode */ /* * See if we need to adjust cause. Yes if its VS mode interrupt diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 645f30f028..a5be1c202c 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -30,6 +30,7 @@ #include "qemu/guest-random.h" #include "qapi/error.h" + /* CSR function table public API */ void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops) { @@ -1180,6 +1181,8 @@ static const target_ulong sip_writable_mask = SIP_SSIP | LOCAL_INTERRUPTS; static const target_ulong hip_writable_mask = MIP_VSSIP; static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP | LOCAL_INTERRUPTS; +static const target_ulong hvien_writable_mask = LOCAL_INTERRUPTS; + static const target_ulong vsip_writable_mask = MIP_VSSIP | LOCAL_INTERRUPTS; const bool valid_vm_1_10_32[16] = { @@ -2608,16 +2611,36 @@ static RISCVException rmw_vsie64(CPURISCVState *env, int csrno, uint64_t *ret_val, uint64_t new_val, uint64_t wr_mask) { + uint64_t alias_mask = (LOCAL_INTERRUPTS | VS_MODE_INTERRUPTS) & + env->hideleg; + uint64_t nalias_mask = LOCAL_INTERRUPTS & (~env->hideleg & env->hvien); + uint64_t rval, rval_vs, vsbits; + uint64_t wr_mask_vsie; + uint64_t wr_mask_mie; RISCVException ret; - uint64_t rval, mask = env->hideleg & VS_MODE_INTERRUPTS; /* Bring VS-level bits to correct position */ - new_val = (new_val & (VS_MODE_INTERRUPTS >> 1)) << 1; - wr_mask = (wr_mask & (VS_MODE_INTERRUPTS >> 1)) << 1; + vsbits = new_val & (VS_MODE_INTERRUPTS >> 1); + new_val &= ~(VS_MODE_INTERRUPTS >> 1); + new_val |= vsbits << 1; + + vsbits = wr_mask & (VS_MODE_INTERRUPTS >> 1); + wr_mask &= ~(VS_MODE_INTERRUPTS >> 1); + wr_mask |= vsbits << 1; + + wr_mask_mie = wr_mask & alias_mask; + wr_mask_vsie = wr_mask & nalias_mask; + + ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask_mie); + + rval_vs = env->vsie & nalias_mask; + env->vsie = (env->vsie & ~wr_mask_vsie) | (new_val & wr_mask_vsie); - ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask & mask); if (ret_val) { - *ret_val = (rval & mask) >> 1; + rval &= alias_mask; + vsbits = rval & VS_MODE_INTERRUPTS; + rval &= ~VS_MODE_INTERRUPTS; + *ret_val = rval | (vsbits >> 1) | rval_vs; } return ret; @@ -2830,21 +2853,36 @@ static RISCVException write_stval(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException rmw_hvip64(CPURISCVState *env, int csrno, + uint64_t *ret_val, + uint64_t new_val, uint64_t wr_mask); + static RISCVException rmw_vsip64(CPURISCVState *env, int csrno, uint64_t *ret_val, uint64_t new_val, uint64_t wr_mask) { RISCVException ret; uint64_t rval, mask = env->hideleg & VS_MODE_INTERRUPTS; + uint64_t vsbits; + + /* Add virtualized bits into vsip mask. */ + mask |= env->hvien & ~env->hideleg; /* Bring VS-level bits to correct position */ - new_val = (new_val & (VS_MODE_INTERRUPTS >> 1)) << 1; - wr_mask = (wr_mask & (VS_MODE_INTERRUPTS >> 1)) << 1; + vsbits = new_val & (VS_MODE_INTERRUPTS >> 1); + new_val &= ~(VS_MODE_INTERRUPTS >> 1); + new_val |= vsbits << 1; + vsbits = wr_mask & (VS_MODE_INTERRUPTS >> 1); + wr_mask &= ~(VS_MODE_INTERRUPTS >> 1); + wr_mask |= vsbits << 1; - ret = rmw_mip64(env, csrno, &rval, new_val, - wr_mask & mask & vsip_writable_mask); + ret = rmw_hvip64(env, csrno, &rval, new_val, + wr_mask & mask & vsip_writable_mask); if (ret_val) { - *ret_val = (rval & mask) >> 1; + rval &= mask; + vsbits = rval & VS_MODE_INTERRUPTS; + rval &= ~VS_MODE_INTERRUPTS; + *ret_val = rval | (vsbits >> 1); } return ret; @@ -3136,6 +3174,52 @@ static RISCVException write_hedeleg(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException rmw_hvien64(CPURISCVState *env, int csrno, + uint64_t *ret_val, + uint64_t new_val, uint64_t wr_mask) +{ + uint64_t mask = wr_mask & hvien_writable_mask; + + if (ret_val) { + *ret_val = env->hvien; + } + + env->hvien = (env->hvien & ~mask) | (new_val & mask); + + return RISCV_EXCP_NONE; +} + +static RISCVException rmw_hvien(CPURISCVState *env, int csrno, + target_ulong *ret_val, + target_ulong new_val, target_ulong wr_mask) +{ + uint64_t rval; + RISCVException ret; + + ret = rmw_hvien64(env, csrno, &rval, new_val, wr_mask); + if (ret_val) { + *ret_val = rval; + } + + return ret; +} + +static RISCVException rmw_hvienh(CPURISCVState *env, int csrno, + target_ulong *ret_val, + target_ulong new_val, target_ulong wr_mask) +{ + uint64_t rval; + RISCVException ret; + + ret = rmw_hvien64(env, csrno, &rval, + ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32); + if (ret_val) { + *ret_val = rval >> 32; + } + + return ret; +} + static RISCVException rmw_hideleg64(CPURISCVState *env, int csrno, uint64_t *ret_val, uint64_t new_val, uint64_t wr_mask) @@ -3181,16 +3265,94 @@ static RISCVException rmw_hidelegh(CPURISCVState *env, int csrno, return ret; } +/* + * The function is written for two use-cases: + * 1- To access hvip csr as is for HS-mode access. + * 2- To access vsip as a combination of hvip, and mip for vs-mode. + * + * Both report bits 2, 6, 10 and 13:63. + * vsip needs to be read-only zero when both hideleg[i] and + * hvien[i] are zero. + */ static RISCVException rmw_hvip64(CPURISCVState *env, int csrno, uint64_t *ret_val, uint64_t new_val, uint64_t wr_mask) { RISCVException ret; + uint64_t old_hvip; + uint64_t ret_mip; + + /* + * For bits 10, 6 and 2, vsip[i] is an alias of hip[i]. These bits are + * present in hip, hvip and mip. Where mip[i] is alias of hip[i] and hvip[i] + * is OR'ed in hip[i] to inject virtual interrupts from hypervisor. These + * bits are actually being maintained in mip so we read them from there. + * This way we have a single source of truth and allows for easier + * implementation. + * + * For bits 13:63 we have: + * + * hideleg[i] hvien[i] + * 0 0 No delegation. vsip[i] readonly zero. + * 0 1 vsip[i] is alias of hvip[i], sip bypassed. + * 1 X vsip[i] is alias of sip[i], hvip bypassed. + * + * alias_mask denotes the bits that come from sip (mip here given we + * maintain all bits there). nalias_mask denotes bits that come from + * hvip. + */ + uint64_t alias_mask = (env->hideleg | ~env->hvien) | VS_MODE_INTERRUPTS; + uint64_t nalias_mask = (~env->hideleg & env->hvien); + uint64_t wr_mask_hvip; + uint64_t wr_mask_mip; + + /* + * Both alias and non-alias mask remain same for vsip except: + * 1- For VS* bits if they are zero in hideleg. + * 2- For 13:63 bits if they are zero in both hideleg and hvien. + */ + if (csrno == CSR_VSIP) { + /* zero-out VS* bits that are not delegated to VS mode. */ + alias_mask &= (env->hideleg | ~VS_MODE_INTERRUPTS); + + /* + * zero-out 13:63 bits that are zero in both hideleg and hvien. + * nalias_mask mask can not contain any VS* bits so only second + * condition applies on it. + */ + nalias_mask &= (env->hideleg | env->hvien); + alias_mask &= (env->hideleg | env->hvien); + } + + wr_mask_hvip = wr_mask & nalias_mask & hvip_writable_mask; + wr_mask_mip = wr_mask & alias_mask & hvip_writable_mask; + + /* Aliased bits, bits 10, 6, 2 need to come from mip. */ + ret = rmw_mip64(env, csrno, &ret_mip, new_val, wr_mask_mip); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + old_hvip = env->hvip; + + if (wr_mask_hvip) { + env->hvip = (env->hvip & ~wr_mask_hvip) | (new_val & wr_mask_hvip); + + /* + * Given hvip is separate source from mip, we need to trigger interrupt + * from here separately. Normally this happen from riscv_cpu_update_mip. + */ + riscv_cpu_interrupt(env); + } - ret = rmw_mip64(env, csrno, ret_val, new_val, - wr_mask & hvip_writable_mask); if (ret_val) { - *ret_val &= VS_MODE_INTERRUPTS; + /* Only take VS* bits from mip. */ + ret_mip &= alias_mask; + + /* Take in non-delegated 13:63 bits from hvip. */ + old_hvip &= nalias_mask; + + *ret_val = ret_mip | old_hvip; } return ret; @@ -4569,14 +4731,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { .min_priv_ver = PRIV_VERSION_1_12_0 }, /* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */ - [CSR_HVIEN] = { "hvien", aia_hmode, read_zero, write_ignore }, + [CSR_HVIEN] = { "hvien", aia_hmode, NULL, NULL, rmw_hvien }, [CSR_HVICTL] = { "hvictl", aia_hmode, read_hvictl, write_hvictl }, [CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1, write_hviprio1 }, [CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2, write_hviprio2 }, - /* * VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */ @@ -4591,8 +4752,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { /* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */ [CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, rmw_hidelegh }, - [CSR_HVIENH] = { "hvienh", aia_hmode32, read_zero, - write_ignore }, + [CSR_HVIENH] = { "hvienh", aia_hmode32, NULL, NULL, rmw_hvienh }, [CSR_HVIPH] = { "hviph", aia_hmode32, NULL, NULL, rmw_hviph }, [CSR_HVIPRIO1H] = { "hviprio1h", aia_hmode32, read_hviprio1h, write_hviprio1h }, diff --git a/target/riscv/machine.c b/target/riscv/machine.c index f65a95f9e7..14bb2d7819 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -79,8 +79,8 @@ static bool hyper_needed(void *opaque) static const VMStateDescription vmstate_hyper = { .name = "cpu/hyper", - .version_id = 2, - .minimum_version_id = 2, + .version_id = 3, + .minimum_version_id = 3, .needed = hyper_needed, .fields = (VMStateField[]) { VMSTATE_UINTTL(env.hstatus, RISCVCPU), @@ -92,6 +92,8 @@ static const VMStateDescription vmstate_hyper = { VMSTATE_UINTTL(env.hgatp, RISCVCPU), VMSTATE_UINTTL(env.hgeie, RISCVCPU), VMSTATE_UINTTL(env.hgeip, RISCVCPU), + VMSTATE_UINT64(env.hvien, RISCVCPU), + VMSTATE_UINT64(env.hvip, RISCVCPU), VMSTATE_UINT64(env.htimedelta, RISCVCPU), VMSTATE_UINT64(env.vstimecmp, RISCVCPU), @@ -106,6 +108,7 @@ static const VMStateDescription vmstate_hyper = { VMSTATE_UINTTL(env.vstval, RISCVCPU), VMSTATE_UINTTL(env.vsatp, RISCVCPU), VMSTATE_UINTTL(env.vsiselect, RISCVCPU), + VMSTATE_UINT64(env.vsie, RISCVCPU), VMSTATE_UINTTL(env.mtval2, RISCVCPU), VMSTATE_UINTTL(env.mtinst, RISCVCPU), From 4d84cc5887c5ed9a630f5af87e56d64ee0a98c4b Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 20 Oct 2023 04:45:01 -0300 Subject: [PATCH 11/49] linux-user/riscv: change default cpu to 'max' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit f57d5f8004 deprecated the 'any' CPU type but failed to change the default CPU for linux-user. The result is that all linux-users invocations that doesn't specify a different CPU started to show a deprecation warning: $ ./build/qemu-riscv64 ./foo-novect.out qemu-riscv64: warning: The 'any' CPU is deprecated and will be removed in the future. Change the default CPU for RISC-V linux-user from 'any' to 'max'. Reported-by: Richard Henderson Fixes: f57d5f8004 ("target/riscv: deprecate the 'any' CPU type") Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Richard Henderson Message-ID: <20231020074501.283063-1-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- linux-user/riscv/target_elf.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/linux-user/riscv/target_elf.h b/linux-user/riscv/target_elf.h index 9dd65652ee..dedd5956f3 100644 --- a/linux-user/riscv/target_elf.h +++ b/linux-user/riscv/target_elf.h @@ -9,7 +9,6 @@ #define RISCV_TARGET_ELF_H static inline const char *cpu_get_model(uint32_t eflags) { - /* TYPE_RISCV_CPU_ANY */ - return "any"; + return "max"; } #endif From 257cfaed47e3263ee3c379ec7a766f5050daa920 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 20 Oct 2023 17:02:47 -0300 Subject: [PATCH 12/49] docs/system/riscv: update 'virt' machine core limit The 'virt' RISC-V machine does not have a 8 core limit. The current limit is set in include/hw/riscv/virt.h, VIRT_CPUS_MAX, set to 512 at this moment. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1945 Signed-off-by: Daniel Henrique Barboza Message-ID: <20231020200247.334403-2-dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis Signed-off-by: Alistair Francis --- docs/system/riscv/virt.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst index f9a2eac544..f5fa7b8b29 100644 --- a/docs/system/riscv/virt.rst +++ b/docs/system/riscv/virt.rst @@ -12,7 +12,7 @@ Supported devices The ``virt`` machine supports the following devices: -* Up to 8 generic RV32GC/RV64GC cores, with optional extensions +* Up to 512 generic RV32GC/RV64GC cores, with optional extensions * Core Local Interruptor (CLINT) * Platform-Level Interrupt Controller (PLIC) * CFI parallel NOR flash memory From 456a65546f6761aab09275ed7055d113608e3bb2 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 18 Oct 2023 16:56:33 -0300 Subject: [PATCH 13/49] target/riscv/kvm/kvm-cpu.c: add missing property getters() We got along without property getters in the KVM driver because we never needed them. But the incoming query-cpu-model-expansion API will use property getters and setters to retrieve the CPU characteristics. Add the missing getters for the KVM driver for both MISA and multi-letter extension properties. We're also adding an special getter for absent multi-letter properties that KVM doesn't implement that always return false. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231018195638.211151-2-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/kvm/kvm-cpu.c | 40 +++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 6e1678542b..6bf035f39c 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -140,6 +140,19 @@ static KVMCPUConfig kvm_misa_ext_cfgs[] = { KVM_MISA_CFG(RVM, KVM_RISCV_ISA_EXT_M), }; +static void kvm_cpu_get_misa_ext_cfg(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) +{ + KVMCPUConfig *misa_ext_cfg = opaque; + target_ulong misa_bit = misa_ext_cfg->offset; + RISCVCPU *cpu = RISCV_CPU(obj); + CPURISCVState *env = &cpu->env; + bool value = env->misa_ext_mask & misa_bit; + + visit_type_bool(v, name, &value, errp); +} + static void kvm_cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -244,6 +257,17 @@ static uint32_t kvm_cpu_cfg_get(RISCVCPU *cpu, return *ext_enabled; } +static void kvm_cpu_get_multi_ext_cfg(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) +{ + KVMCPUConfig *multi_ext_cfg = opaque; + RISCVCPU *cpu = RISCV_CPU(obj); + bool value = kvm_cpu_cfg_get(cpu, multi_ext_cfg); + + visit_type_bool(v, name, &value, errp); +} + static void kvm_cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -346,6 +370,15 @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs) } } +static void cpu_get_cfg_unavailable(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) +{ + bool value = false; + + visit_type_bool(v, name, &value, errp); +} + static void cpu_set_cfg_unavailable(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) @@ -376,7 +409,8 @@ static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) * to enable any of them. */ object_property_add(obj, prop_name, "bool", - NULL, cpu_set_cfg_unavailable, + cpu_get_cfg_unavailable, + cpu_set_cfg_unavailable, NULL, (void *)prop_name); } @@ -406,7 +440,7 @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj) misa_cfg->description = riscv_get_misa_ext_description(bit); object_property_add(cpu_obj, misa_cfg->name, "bool", - NULL, + kvm_cpu_get_misa_ext_cfg, kvm_cpu_set_misa_ext_cfg, NULL, misa_cfg); object_property_set_description(cpu_obj, misa_cfg->name, @@ -422,7 +456,7 @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj) KVMCPUConfig *multi_cfg = &kvm_multi_ext_cfgs[i]; object_property_add(cpu_obj, multi_cfg->name, "bool", - NULL, + kvm_cpu_get_multi_ext_cfg, kvm_cpu_set_multi_ext_cfg, NULL, multi_cfg); } From aeb2bc5950bda70f97c6a7fcbdf1ab2b167d4fa4 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 18 Oct 2023 16:56:34 -0300 Subject: [PATCH 14/49] qapi,risc-v: add query-cpu-model-expansion This API is used to inspect the characteristics of a given CPU model. It also allows users to validate a CPU model with a certain configuration, e.g. if "-cpu X,a=true,b=false" is a valid setup for a given QEMU binary. We'll start implementing the first part. The second requires more changes in RISC-V CPU boot flow. The implementation is inspired by the existing ARM query-cpu-model-expansion impl in target/arm/arm-qmp-cmds.c. We'll create a RISCVCPU object with the required model, fetch its existing properties, add a couple of relevant boolean options (pmp and mmu) and display it to users. Here's an usage example: ./build/qemu-system-riscv64 -S -M virt -display none \ -qmp tcp:localhost:1234,server,wait=off ./scripts/qmp/qmp-shell localhost:1234 Welcome to the QMP low-level shell! Connected to QEMU 8.1.50 (QEMU) query-cpu-model-expansion type=full model={"name":"rv64"} {"return": {"model": {"name": "rv64", "props": {"zicond": false, "x-zvfh": false, "mmu": true, "x-zvfbfwma": false, "x-zvfbfmin": false, "xtheadbs": false, "xtheadbb": false, "xtheadba": false, "xtheadmemidx": false, "smstateen": false, "zfinx": false, "Zve64f": false, "Zve32f": false, "x-zvfhmin": false, "xventanacondops": false, "xtheadcondmov": false, "svpbmt": false, "zbs": true, "zbc": true, "zbb": true, "zba": true, "zicboz": true, "xtheadmac": false, "Zfh": false, "Zfa": true, "zbkx": false, "zbkc": false, "zbkb": false, "Zve64d": false, "x-zfbfmin": false, "zk": false, "x-epmp": false, "xtheadmempair": false, "zkt": false, "zks": false, "zkr": false, "zkn": false, "Zfhmin": false, "zksh": false, "zknh": false, "zkne": false, "zknd": false, "zhinx": false, "Zicsr": true, "sscofpmf": false, "Zihintntl": true, "sstc": true, "xtheadcmo": false, "x-zvbb": false, "zksed": false, "x-zvkned": false, "xtheadsync": false, "x-zvkg": false, "zhinxmin": false, "svadu": true, "xtheadfmv": false, "x-zvksed": false, "svnapot": false, "pmp": true, "x-zvknhb": false, "x-zvknha": false, "xtheadfmemidx": false, "x-zvksh": false, "zdinx": false, "zicbom": true, "Zihintpause": true, "svinval": false, "zcf": false, "zce": false, "zcd": false, "zcb": false, "zca": false, "x-ssaia": false, "x-smaia": false, "zmmul": false, "x-zvbc": false, "Zifencei": true, "zcmt": false, "zcmp": false, "Zawrs": true}}}} Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231018195638.211151-3-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- qapi/machine-target.json | 6 ++- target/riscv/riscv-qmp-cmds.c | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/qapi/machine-target.json b/qapi/machine-target.json index c8d7d9868d..7b7149f81c 100644 --- a/qapi/machine-target.json +++ b/qapi/machine-target.json @@ -231,7 +231,8 @@ 'if': { 'any': [ 'TARGET_S390X', 'TARGET_I386', 'TARGET_ARM', - 'TARGET_LOONGARCH64' ] } } + 'TARGET_LOONGARCH64', + 'TARGET_RISCV' ] } } ## # @query-cpu-model-expansion: @@ -277,7 +278,8 @@ 'if': { 'any': [ 'TARGET_S390X', 'TARGET_I386', 'TARGET_ARM', - 'TARGET_LOONGARCH64' ] } } + 'TARGET_LOONGARCH64', + 'TARGET_RISCV' ] } } ## # @CpuDefinitionInfo: diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c index 5ecff1afb3..2170562e3a 100644 --- a/target/riscv/riscv-qmp-cmds.c +++ b/target/riscv/riscv-qmp-cmds.c @@ -24,8 +24,12 @@ #include "qemu/osdep.h" +#include "qapi/error.h" #include "qapi/qapi-commands-machine-target.h" +#include "qapi/qmp/qdict.h" +#include "qom/qom-qobject.h" #include "cpu-qom.h" +#include "cpu.h" static void riscv_cpu_add_definition(gpointer data, gpointer user_data) { @@ -55,3 +59,74 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) return cpu_list; } + +static void riscv_obj_add_qdict_prop(Object *obj, QDict *qdict_out, + const char *name) +{ + ObjectProperty *prop = object_property_find(obj, name); + + if (prop) { + QObject *value; + + assert(prop->get); + value = object_property_get_qobject(obj, name, &error_abort); + + qdict_put_obj(qdict_out, name, value); + } +} + +static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out, + const RISCVCPUMultiExtConfig *arr) +{ + for (int i = 0; arr[i].name != NULL; i++) { + riscv_obj_add_qdict_prop(obj, qdict_out, arr[i].name); + } +} + +CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, + CpuModelInfo *model, + Error **errp) +{ + CpuModelExpansionInfo *expansion_info; + QDict *qdict_out; + ObjectClass *oc; + Object *obj; + + if (type != CPU_MODEL_EXPANSION_TYPE_FULL) { + error_setg(errp, "The requested expansion type is not supported"); + return NULL; + } + + oc = cpu_class_by_name(TYPE_RISCV_CPU, model->name); + if (!oc) { + error_setg(errp, "The CPU type '%s' is not a known RISC-V CPU type", + model->name); + return NULL; + } + + obj = object_new(object_class_get_name(oc)); + + expansion_info = g_new0(CpuModelExpansionInfo, 1); + expansion_info->model = g_malloc0(sizeof(*expansion_info->model)); + expansion_info->model->name = g_strdup(model->name); + + 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); + + /* Add our CPU boolean options too */ + riscv_obj_add_qdict_prop(obj, qdict_out, "mmu"); + riscv_obj_add_qdict_prop(obj, qdict_out, "pmp"); + + if (!qdict_size(qdict_out)) { + qobject_unref(qdict_out); + } else { + expansion_info->model->props = QOBJECT(qdict_out); + } + + object_unref(obj); + + return expansion_info; +} From a13a6082c7488d4393453d383676ae423b38b4d8 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 18 Oct 2023 16:56:35 -0300 Subject: [PATCH 15/49] target/riscv/tcg: add tcg_cpu_finalize_features() The query-cpu-model-expansion API is capable of passing extra properties to a given CPU model and tell callers if this custom configuration is valid. The RISC-V version of the API is not quite there yet. The reason is the realize() flow in the TCG driver, where most of the validation is done in tcg_cpu_realizefn(). riscv_cpu_finalize_features() is then used to validate satp_mode for both TCG and KVM CPUs. Our ARM friends uses a concept of 'finalize_features()', a step done in the end of realize() where the CPU features are validated. We have a riscv_cpu_finalize_features() helper that, at this moment, is only validating satp_mode. Re-use this existing helper to do all CPU extension validation we required after at the end of realize(). Make it public to allow APIs to use it. At this moment only the TCG driver requires a realize() time validation, thus, to avoid adding accelerator specific helpers in the API, riscv_cpu_finalize_features() uses riscv_tcg_cpu_finalize_features() if we are running TCG. The API will then use riscv_cpu_finalize_features() regardless of the current accelerator. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231018195638.211151-4-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 18 +++++++++-- target/riscv/cpu.h | 1 + target/riscv/tcg/tcg-cpu.c | 63 +++++++++++++++++++++----------------- target/riscv/tcg/tcg-cpu.h | 1 + 4 files changed, 53 insertions(+), 30 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 2f98ce56e0..02db0834dd 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -34,6 +34,7 @@ #include "sysemu/kvm.h" #include "sysemu/tcg.h" #include "kvm/kvm_riscv.h" +#include "tcg/tcg-cpu.h" #include "tcg/tcg.h" /* RISC-V CPU definitions */ @@ -998,11 +999,24 @@ static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) } #endif -static void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp) +void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp) { -#ifndef CONFIG_USER_ONLY Error *local_err = NULL; + /* + * KVM accel does not have a specialized finalize() + * callback because its extensions are validated + * in the get()/set() callbacks of each property. + */ + if (tcg_enabled()) { + riscv_tcg_cpu_finalize_features(cpu, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + } + +#ifndef CONFIG_USER_ONLY riscv_cpu_satp_mode_finalize(cpu, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 7f61e17202..8c9ec59d82 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -756,6 +756,7 @@ typedef struct isa_ext_data { extern const RISCVIsaExtData isa_edata_arr[]; char *riscv_cpu_get_name(RISCVCPU *cpu); +void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp); void riscv_add_satp_mode_properties(Object *obj); /* CSR function table */ diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index bbce254ee1..21a46f2a0e 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -548,6 +548,39 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) riscv_cpu_disable_priv_spec_isa_exts(cpu); } +void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) +{ + CPURISCVState *env = &cpu->env; + Error *local_err = NULL; + + riscv_cpu_validate_priv_spec(cpu, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + + riscv_cpu_validate_misa_priv(env, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } + + if (cpu->cfg.epmp && !cpu->cfg.pmp) { + /* + * Enhanced PMP should only be available + * on harts with PMP support + */ + error_setg(errp, "Invalid configuration: EPMP requires PMP support"); + return; + } + + riscv_cpu_validate_set_extensions(cpu, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } +} + static bool riscv_cpu_is_generic(Object *cpu_obj) { return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL; @@ -563,7 +596,6 @@ static bool riscv_cpu_is_generic(Object *cpu_obj) static bool tcg_cpu_realize(CPUState *cs, Error **errp) { RISCVCPU *cpu = RISCV_CPU(cs); - CPURISCVState *env = &cpu->env; Error *local_err = NULL; if (object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST)) { @@ -579,34 +611,9 @@ static bool tcg_cpu_realize(CPUState *cs, Error **errp) return false; } - riscv_cpu_validate_priv_spec(cpu, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return false; - } - - riscv_cpu_validate_misa_priv(env, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return false; - } - - if (cpu->cfg.epmp && !cpu->cfg.pmp) { - /* - * Enhanced PMP should only be available - * on harts with PMP support - */ - error_setg(errp, "Invalid configuration: EPMP requires PMP support"); - return false; - } - - riscv_cpu_validate_set_extensions(cpu, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return false; - } - #ifndef CONFIG_USER_ONLY + CPURISCVState *env = &cpu->env; + CPU(cs)->tcg_cflags |= CF_PCREL; if (cpu->cfg.ext_sstc) { diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h index 630184759d..aa00fbc253 100644 --- a/target/riscv/tcg/tcg-cpu.h +++ b/target/riscv/tcg/tcg-cpu.h @@ -23,5 +23,6 @@ #include "cpu.h" void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp); +void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp); #endif From 1df4f540d6352131cefa7ca48b637ccb774ce9e0 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 18 Oct 2023 16:56:36 -0300 Subject: [PATCH 16/49] target/riscv: handle custom props in qmp_query_cpu_model_expansion Callers can add 'props' when querying for a cpu model expansion to see if a given CPU model supports a certain criteria, and what's the resulting CPU object. If we have 'props' to handle, gather it in a QDict and use the new riscv_cpuobj_validate_qdict_in() helper to validate it. This helper will add the custom properties in the CPU object and validate it using riscv_cpu_finalize_features(). Users will be aware of validation errors if any occur, if not a CPU object with 'props' will be returned. Here's an example with the veyron-v1 vendor CPU. Disabling vendor CPU extensions is allowed, assuming the final config is valid. Disabling 'smstateen' is a valid expansion: (QEMU) query-cpu-model-expansion type=full model={"name":"veyron-v1","props":{"smstateen":false}} {"return": {"model": {"name": "veyron-v1", "props": {"zicond": false, ..., "smstateen": false, ...} But enabling extensions isn't allowed for vendor CPUs. E.g. enabling 'V' for the veyron-v1 CPU isn't allowed: (QEMU) query-cpu-model-expansion type=full model={"name":"veyron-v1","props":{"v":true}} {"error": {"class": "GenericError", "desc": "'veyron-v1' CPU does not allow enabling extensions"}} Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231018195638.211151-5-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/riscv-qmp-cmds.c | 65 +++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c index 2170562e3a..5b2d186c83 100644 --- a/target/riscv/riscv-qmp-cmds.c +++ b/target/riscv/riscv-qmp-cmds.c @@ -27,6 +27,9 @@ #include "qapi/error.h" #include "qapi/qapi-commands-machine-target.h" #include "qapi/qmp/qdict.h" +#include "qapi/qmp/qerror.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/visitor.h" #include "qom/qom-qobject.h" #include "cpu-qom.h" #include "cpu.h" @@ -83,14 +86,58 @@ static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out, } } +static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props, + const QDict *qdict_in, + Error **errp) +{ + const QDictEntry *qe; + Visitor *visitor; + Error *local_err = NULL; + + visitor = qobject_input_visitor_new(props); + if (!visit_start_struct(visitor, NULL, NULL, 0, &local_err)) { + goto err; + } + + for (qe = qdict_first(qdict_in); qe; qe = qdict_next(qdict_in, qe)) { + object_property_find_err(obj, qe->key, &local_err); + if (local_err) { + goto err; + } + + object_property_set(obj, qe->key, visitor, &local_err); + if (local_err) { + goto err; + } + } + + visit_check_struct(visitor, &local_err); + if (local_err) { + goto err; + } + + riscv_cpu_finalize_features(RISCV_CPU(obj), &local_err); + if (local_err) { + goto err; + } + + visit_end_struct(visitor, NULL); + +err: + error_propagate(errp, local_err); + visit_free(visitor); +} + CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, CpuModelInfo *model, Error **errp) { CpuModelExpansionInfo *expansion_info; + const QDict *qdict_in = NULL; QDict *qdict_out; ObjectClass *oc; Object *obj; + Error *local_err = NULL; if (type != CPU_MODEL_EXPANSION_TYPE_FULL) { error_setg(errp, "The requested expansion type is not supported"); @@ -104,8 +151,26 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, return NULL; } + if (model->props) { + qdict_in = qobject_to(QDict, model->props); + if (!qdict_in) { + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); + return NULL; + } + } + obj = object_new(object_class_get_name(oc)); + if (qdict_in) { + riscv_cpuobj_validate_qdict_in(obj, model->props, qdict_in, + &local_err); + if (local_err) { + error_propagate(errp, local_err); + object_unref(obj); + return NULL; + } + } + expansion_info = g_new0(CpuModelExpansionInfo, 1); expansion_info->model = g_malloc0(sizeof(*expansion_info->model)); expansion_info->model->name = g_strdup(model->name); From ef58fad0fdc7aba2c2196f9c35a89889286ef92b Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 18 Oct 2023 16:56:37 -0300 Subject: [PATCH 17/49] target/riscv: add riscv_cpu_accelerator_compatible() Add an API to check if a given CPU is compatible with the current accelerator. This will allow query-cpu-model-expansion to work properly in conditions where QEMU supports both accelerators (TCG and KVM), QEMU is then launched using TCG, and the API requests information about a KVM only CPU (e.g. 'host' CPU). KVM doesn't have such restrictions and, at least in theory, all CPUs models should work with KVM. We will revisit this API in case we decide to restrict the amount of KVM CPUs we support. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231018195638.211151-6-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 9 +++++++++ target/riscv/cpu.h | 1 + target/riscv/tcg/tcg-cpu.c | 7 ++++++- target/riscv/tcg/tcg-cpu.h | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 02db0834dd..8e0abe33d3 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1063,6 +1063,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) mcc->parent_realize(dev, errp); } +bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu) +{ + if (tcg_enabled()) { + return riscv_cpu_tcg_compatible(cpu); + } + + return true; +} + #ifndef CONFIG_USER_ONLY static void cpu_riscv_get_satp(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 8c9ec59d82..8efc4d83ec 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -758,6 +758,7 @@ char *riscv_cpu_get_name(RISCVCPU *cpu); void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp); void riscv_add_satp_mode_properties(Object *obj); +bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu); /* CSR function table */ extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE]; diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 21a46f2a0e..6771617226 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -581,6 +581,11 @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) } } +bool riscv_cpu_tcg_compatible(RISCVCPU *cpu) +{ + return object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST) == NULL; +} + static bool riscv_cpu_is_generic(Object *cpu_obj) { return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL; @@ -598,7 +603,7 @@ static bool tcg_cpu_realize(CPUState *cs, Error **errp) RISCVCPU *cpu = RISCV_CPU(cs); Error *local_err = NULL; - if (object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_CPU_HOST)) { + if (!riscv_cpu_tcg_compatible(cpu)) { g_autofree char *name = riscv_cpu_get_name(cpu); error_setg(errp, "'%s' CPU is not compatible with TCG acceleration", name); diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h index aa00fbc253..f7b32417f8 100644 --- a/target/riscv/tcg/tcg-cpu.h +++ b/target/riscv/tcg/tcg-cpu.h @@ -24,5 +24,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp); void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp); +bool riscv_cpu_tcg_compatible(RISCVCPU *cpu); #endif From a3abecbef0ad5e121c0d3f8f26568ab0466d9a6a Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 18 Oct 2023 16:56:38 -0300 Subject: [PATCH 18/49] target/riscv/riscv-qmp-cmds.c: check CPU accel in query-cpu-model-expansion Use the recently added riscv_cpu_accelerator_compatible() to filter unavailable CPUs for a given accelerator. At this moment this is the case for a QEMU built with KVM and TCG support querying a binary running with TCG: qemu-system-riscv64 -S -M virt,accel=tcg -display none -qmp tcp:localhost:1234,server,wait=off ./qemu/scripts/qmp/qmp-shell localhost:1234 (QEMU) query-cpu-model-expansion type=full model={"name":"host"} {"error": {"class": "GenericError", "desc": "'host' CPU not available with tcg"}} Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231018195638.211151-7-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/riscv-qmp-cmds.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c index 5b2d186c83..2f2dbae7c8 100644 --- a/target/riscv/riscv-qmp-cmds.c +++ b/target/riscv/riscv-qmp-cmds.c @@ -31,6 +31,8 @@ #include "qapi/qobject-input-visitor.h" #include "qapi/visitor.h" #include "qom/qom-qobject.h" +#include "sysemu/kvm.h" +#include "sysemu/tcg.h" #include "cpu-qom.h" #include "cpu.h" @@ -63,6 +65,17 @@ CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) return cpu_list; } +static void riscv_check_if_cpu_available(RISCVCPU *cpu, Error **errp) +{ + if (!riscv_cpu_accelerator_compatible(cpu)) { + g_autofree char *name = riscv_cpu_get_name(cpu); + const char *accel = kvm_enabled() ? "kvm" : "tcg"; + + error_setg(errp, "'%s' CPU not available with %s", name, accel); + return; + } +} + static void riscv_obj_add_qdict_prop(Object *obj, QDict *qdict_out, const char *name) { @@ -161,6 +174,13 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, obj = object_new(object_class_get_name(oc)); + riscv_check_if_cpu_available(RISCV_CPU(obj), &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + object_unref(obj); + return NULL; + } + if (qdict_in) { riscv_cpuobj_validate_qdict_in(obj, model->props, qdict_in, &local_err); From 095fe72a128b34d4f9317c2798c6fa7762a9e3e6 Mon Sep 17 00:00:00 2001 From: Himanshu Chauhan Date: Thu, 19 Oct 2023 12:25:46 +0530 Subject: [PATCH 19/49] Add epmp to extensions list and rename it to smepmp Smepmp is a ratified extension which qemu refers to as epmp. Rename epmp to smepmp and add it to extension list so that it is added to the isa string. Signed-off-by: Himanshu Chauhan Signed-off-by: Mayuresh Chitale Reviewed-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231019065546.1431579-1-mchitale@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 8 +++----- target/riscv/cpu_cfg.h | 2 +- target/riscv/csr.c | 6 +++--- target/riscv/pmp.c | 12 ++++++------ target/riscv/tcg/tcg-cpu.c | 4 ++-- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 8e0abe33d3..0c58c8571f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -134,7 +134,7 @@ 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(smaia, PRIV_VERSION_1_12_0, ext_smaia), - ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, epmp), + ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp), 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(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf), @@ -600,12 +600,11 @@ static void rv32_ibex_cpu_init(Object *obj) #ifndef CONFIG_USER_ONLY set_satp_mode_max_supported(cpu, VM_1_10_MBARE); #endif - cpu->cfg.epmp = true; - /* inherited from parent obj via riscv_cpu_init() */ cpu->cfg.ext_zifencei = true; cpu->cfg.ext_zicsr = true; cpu->cfg.pmp = true; + cpu->cfg.ext_smepmp = true; } static void rv32_imafcu_nommu_cpu_init(Object *obj) @@ -1280,6 +1279,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false), MULTI_EXT_CFG_BOOL("sstc", ext_sstc, true), + MULTI_EXT_CFG_BOOL("smepmp", ext_smepmp, false), MULTI_EXT_CFG_BOOL("smstateen", ext_smstateen, false), MULTI_EXT_CFG_BOOL("svadu", ext_svadu, true), MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false), @@ -1345,8 +1345,6 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { /* These are experimental so mark with 'x-' */ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { - /* ePMP 0.9.3 */ - MULTI_EXT_CFG_BOOL("x-epmp", epmp, false), MULTI_EXT_CFG_BOOL("x-smaia", ext_smaia, false), MULTI_EXT_CFG_BOOL("x-ssaia", ext_ssaia, false), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 208cac1c7c..e7ce977189 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -102,6 +102,7 @@ struct RISCVCPUConfig { bool ext_smaia; bool ext_ssaia; bool ext_sscofpmf; + bool ext_smepmp; bool rvv_ta_all_1s; bool rvv_ma_all_1s; @@ -134,7 +135,6 @@ struct RISCVCPUConfig { uint16_t cboz_blocksize; bool mmu; bool pmp; - bool epmp; bool debug; bool misa_w; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index a5be1c202c..f4e0a3962f 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -524,9 +524,9 @@ static RISCVException pmp(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } -static RISCVException epmp(CPURISCVState *env, int csrno) +static RISCVException smepmp(CPURISCVState *env, int csrno) { - if (riscv_cpu_cfg(env)->epmp) { + if (riscv_cpu_cfg(env)->ext_smepmp) { return RISCV_EXCP_NONE; } @@ -4762,7 +4762,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_VSIPH] = { "vsiph", aia_hmode32, NULL, NULL, rmw_vsiph }, /* Physical Memory Protection */ - [CSR_MSECCFG] = { "mseccfg", epmp, read_mseccfg, write_mseccfg, + [CSR_MSECCFG] = { "mseccfg", smepmp, read_mseccfg, write_mseccfg, .min_priv_ver = PRIV_VERSION_1_11_0 }, [CSR_PMPCFG0] = { "pmpcfg0", pmp, read_pmpcfg, write_pmpcfg }, [CSR_PMPCFG1] = { "pmpcfg1", pmp, read_pmpcfg, write_pmpcfg }, diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 5e60c26031..21d2489e27 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -91,7 +91,7 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val) if (pmp_index < MAX_RISCV_PMPS) { bool locked = true; - if (riscv_cpu_cfg(env)->epmp) { + if (riscv_cpu_cfg(env)->ext_smepmp) { /* mseccfg.RLB is set */ if (MSECCFG_RLB_ISSET(env)) { locked = false; @@ -340,9 +340,9 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, /* * Convert the PMP permissions to match the truth table in the - * ePMP spec. + * Smepmp spec. */ - const uint8_t epmp_operation = + const uint8_t smepmp_operation = ((env->pmp_state.pmp[i].cfg_reg & PMP_LOCK) >> 4) | ((env->pmp_state.pmp[i].cfg_reg & PMP_READ) << 2) | (env->pmp_state.pmp[i].cfg_reg & PMP_WRITE) | @@ -367,7 +367,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, * If mseccfg.MML Bit set, do the enhanced pmp priv check */ if (mode == PRV_M) { - switch (epmp_operation) { + switch (smepmp_operation) { case 0: case 1: case 4: @@ -398,7 +398,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, g_assert_not_reached(); } } else { - switch (epmp_operation) { + switch (smepmp_operation) { case 0: case 8: case 9: @@ -574,7 +574,7 @@ void mseccfg_csr_write(CPURISCVState *env, target_ulong val) } } - if (riscv_cpu_cfg(env)->epmp) { + if (riscv_cpu_cfg(env)->ext_smepmp) { /* Sticky bits */ val |= (env->mseccfg & (MSECCFG_MMWP | MSECCFG_MML)); if ((val ^ env->mseccfg) & (MSECCFG_MMWP | MSECCFG_MML)) { diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 6771617226..c5ff03efce 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -565,12 +565,12 @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) return; } - if (cpu->cfg.epmp && !cpu->cfg.pmp) { + if (cpu->cfg.ext_smepmp && !cpu->cfg.pmp) { /* * Enhanced PMP should only be available * on harts with PMP support */ - error_setg(errp, "Invalid configuration: EPMP requires PMP support"); + error_setg(errp, "Invalid configuration: Smepmp requires PMP support"); return; } From 4bf501dc0118a28699e28c01acb34e28ddeb0acc Mon Sep 17 00:00:00 2001 From: Mayuresh Chitale Date: Thu, 19 Oct 2023 12:26:44 +0530 Subject: [PATCH 20/49] target/riscv: pmp: Clear pmp/smepmp bits on reset As per the Priv and Smepmp specifications, certain bits such as the 'L' bit of pmp entries and mseccfg.MML can only be cleared upon reset and it is necessary to do so to allow 'M' mode firmware to correctly reinitialize the pmp/smpemp state across reboots. As required by the spec, also clear the 'A' field of pmp entries. Signed-off-by: Mayuresh Chitale Reviewed-by: Alistair Francis Message-ID: <20231019065644.1431798-1-mchitale@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 11 +++++++++++ target/riscv/pmp.c | 10 ++++++++++ target/riscv/pmp.h | 2 ++ 3 files changed, 23 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 0c58c8571f..a2881bfa38 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -884,6 +884,17 @@ static void riscv_cpu_reset_hold(Object *obj) } /* mmte is supposed to have pm.current hardwired to 1 */ env->mmte |= (EXT_STATUS_INITIAL | MMTE_M_PM_CURRENT); + + /* + * 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. + */ + if (riscv_cpu_cfg(env)->ext_smepmp) { + env->mseccfg = 0; + } + + pmp_unlock_entries(env); #endif env->xl = riscv_cpu_mxl(env); riscv_cpu_update_mask(env); diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 21d2489e27..4dfaa28fce 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -135,6 +135,16 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val) return false; } +void pmp_unlock_entries(CPURISCVState *env) +{ + uint32_t pmp_num = pmp_get_num_rules(env); + int i; + + for (i = 0; i < pmp_num; i++) { + env->pmp_state.pmp[i].cfg_reg &= ~(PMP_LOCK | PMP_AMATCH); + } +} + static void pmp_decode_napot(target_ulong a, target_ulong *sa, target_ulong *ea) { diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h index cf5c99f8e6..9af8614cd4 100644 --- a/target/riscv/pmp.h +++ b/target/riscv/pmp.h @@ -28,6 +28,7 @@ typedef enum { PMP_READ = 1 << 0, PMP_WRITE = 1 << 1, PMP_EXEC = 1 << 2, + PMP_AMATCH = (3 << 3), PMP_LOCK = 1 << 7 } pmp_priv_t; @@ -81,6 +82,7 @@ void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index); void pmp_update_rule_nums(CPURISCVState *env); uint32_t pmp_get_num_rules(CPURISCVState *env); int pmp_priv_to_page_prot(pmp_priv_t pmp_priv); +void pmp_unlock_entries(CPURISCVState *env); #define MSECCFG_MML_ISSET(env) get_field(env->mseccfg, MSECCFG_MML) #define MSECCFG_MMWP_ISSET(env) get_field(env->mseccfg, MSECCFG_MMWP) From ac66f2f0d12d7ebb69bb45d5eb7f73fb0542bae5 Mon Sep 17 00:00:00 2001 From: Mayuresh Chitale Date: Thu, 19 Oct 2023 12:27:05 +0530 Subject: [PATCH 21/49] target/riscv: pmp: Ignore writes when RW=01 As per the Priv spec: "The R, W, and X fields form a collective WARL field for which the combinations with R=0 and W=1 are reserved." However currently such writes are not ignored as ought to be. The combinations with RW=01 are allowed only when the Smepmp extension is enabled and mseccfg.MML is set. Signed-off-by: Mayuresh Chitale Reviewed-by: Alistair Francis Message-ID: <20231019065705.1431868-1-mchitale@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/pmp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 4dfaa28fce..162e88a90a 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -123,6 +123,11 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val) if (locked) { qemu_log_mask(LOG_GUEST_ERROR, "ignoring pmpcfg write - locked\n"); } else if (env->pmp_state.pmp[pmp_index].cfg_reg != val) { + /* If !mseccfg.MML then ignore writes with encoding RW=01 */ + if ((val & PMP_WRITE) && !(val & PMP_READ) && + !MSECCFG_MML_ISSET(env)) { + val &= ~(PMP_WRITE | PMP_READ); + } env->pmp_state.pmp[pmp_index].cfg_reg = val; pmp_update_rule_addr(env, pmp_index); return true; From c004099330c2bb9c94984ac917815572fcd55bd0 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 23 Oct 2023 12:39:24 -0300 Subject: [PATCH 22/49] target/riscv: add zicntr extension flag for TCG zicntr is the Base Counters and Timers extension described in chapter 12 of the unprivileged spec. It describes support for RDCYCLE, RDTIME and RDINSTRET. QEMU already implements it in TCG way before it was a discrete extension. zicntr is part of the RVA22 profile, so let's add it to QEMU to make the future profile implementation flag complete. Given than it represents an already existing feature, default it to 'true' for all CPUs. For TCG, we need a way to disable zicntr if the user wants to. This is done by restricting access to the CYCLE, TIME, and INSTRET counters via the 'ctr()' predicate when we're about to access them. Disabling zicntr happens via the command line or if its dependency, zicsr, happens to be disabled. We'll check for zicsr during realize() and, in case it's absent, disable zicntr. However, if the user was explicit about having zicntr support, error out instead of disabling it. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231023153927.435083-2-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 12 ++++++++++++ target/riscv/cpu_cfg.h | 1 + target/riscv/csr.c | 4 ++++ target/riscv/tcg/tcg-cpu.c | 8 ++++++++ 4 files changed, 25 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index a2881bfa38..69d64ec4ca 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -80,6 +80,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_zicbom), ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_zicboz), ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond), + ISA_EXT_DATA_ENTRY(zicntr, PRIV_VERSION_1_12_0, ext_zicntr), ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_zicsr), ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_zifencei), ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl), @@ -1208,6 +1209,15 @@ static void riscv_cpu_init(Object *obj) qdev_init_gpio_in(DEVICE(obj), riscv_cpu_set_irq, IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX); #endif /* CONFIG_USER_ONLY */ + + /* + * The timer and performance counters extensions were supported + * in QEMU before they were added as discrete extensions in the + * ISA. To keep compatibility we'll always default them to 'true' + * for all CPUs. Each accelerator will decide what to do when + * users disable them. + */ + RISCV_CPU(obj)->cfg.ext_zicntr = true; } typedef struct misa_ext_info { @@ -1297,6 +1307,8 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false), MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false), + MULTI_EXT_CFG_BOOL("zicntr", ext_zicntr, true), + MULTI_EXT_CFG_BOOL("zba", ext_zba, true), MULTI_EXT_CFG_BOOL("zbb", ext_zbb, true), MULTI_EXT_CFG_BOOL("zbc", ext_zbc, true), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index e7ce977189..73fd4b3231 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -62,6 +62,7 @@ struct RISCVCPUConfig { bool ext_zksh; bool ext_zkt; bool ext_zifencei; + bool ext_zicntr; bool ext_zicsr; bool ext_zicbom; bool ext_zicboz; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index f4e0a3962f..4ca96ddd1d 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -122,6 +122,10 @@ static RISCVException ctr(CPURISCVState *env, int csrno) if ((csrno >= CSR_CYCLE && csrno <= CSR_INSTRET) || (csrno >= CSR_CYCLEH && csrno <= CSR_INSTRETH)) { + if (!riscv_cpu_cfg(env)->ext_zicntr) { + return RISCV_EXCP_ILLEGAL_INST; + } + goto skip_ext_pmu_check; } diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index c5ff03efce..a1e4ed2e24 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -541,6 +541,14 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksh), true); } + if (cpu->cfg.ext_zicntr && !cpu->cfg.ext_zicsr) { + if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zicntr))) { + error_setg(errp, "zicntr requires zicsr"); + return; + } + cpu->cfg.ext_zicntr = false; + } + /* * Disable isa extensions based on priv spec after we * validated and set everything we need. From b31dee8a7d3e515b5129f8ec57fb38cc193fac6e Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 23 Oct 2023 12:39:25 -0300 Subject: [PATCH 23/49] target/riscv/kvm: add zicntr reg Add zicntr support in the KVM driver now that QEMU supports it. This reg was added in Linux 6.6. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231023153927.435083-3-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/kvm/kvm-cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 6bf035f39c..0c5c0e957b 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -228,6 +228,7 @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu, CPUState *cs) static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zicbom", ext_zicbom, KVM_RISCV_ISA_EXT_ZICBOM), KVM_EXT_CFG("zicboz", ext_zicboz, KVM_RISCV_ISA_EXT_ZICBOZ), + KVM_EXT_CFG("zicntr", ext_zicntr, KVM_RISCV_ISA_EXT_ZICNTR), KVM_EXT_CFG("zihintpause", ext_zihintpause, KVM_RISCV_ISA_EXT_ZIHINTPAUSE), KVM_EXT_CFG("zbb", ext_zbb, KVM_RISCV_ISA_EXT_ZBB), KVM_EXT_CFG("ssaia", ext_ssaia, KVM_RISCV_ISA_EXT_SSAIA), From 082412166044a96c69c174e262f282cc6d73f019 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 23 Oct 2023 12:39:26 -0300 Subject: [PATCH 24/49] target/riscv: add zihpm extension flag for TCG zihpm is the Hardware Performance Counters extension described in chapter 12 of the unprivileged spec. It describes support for 29 unprivileged performance counters, hpmcounter3-hpmcounter31. As with zicntr, QEMU already implements zihpm before it was even an extension. zihpm is also part of the RVA22 profile, so add it to QEMU to complement the future profile implementation. Default it to 'true' for all existing CPUs since it was always present in the code. As for disabling it, there is already code in place in target/riscv/csr.c in all predicates for these counters (ctr() and mctr()) that disables them if cpu->cfg.pmu_num is zero. Thus, setting cpu->cfg.pmu_num to zero if 'zihpm=false' is enough to disable the extension. Set cpu->pmu_avail_ctrs mask to zero as well since this is also checked to verify if the counters exist. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231023153927.435083-4-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 3 +++ target/riscv/cpu_cfg.h | 1 + target/riscv/tcg/tcg-cpu.c | 13 +++++++++++++ 3 files changed, 17 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 69d64ec4ca..f40da4c661 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -85,6 +85,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_zifencei), ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl), ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause), + ISA_EXT_DATA_ENTRY(zihpm, PRIV_VERSION_1_12_0, ext_zihpm), ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul), ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs), ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa), @@ -1218,6 +1219,7 @@ static void riscv_cpu_init(Object *obj) * users disable them. */ RISCV_CPU(obj)->cfg.ext_zicntr = true; + RISCV_CPU(obj)->cfg.ext_zihpm = true; } typedef struct misa_ext_info { @@ -1308,6 +1310,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false), MULTI_EXT_CFG_BOOL("zicntr", ext_zicntr, true), + MULTI_EXT_CFG_BOOL("zihpm", ext_zihpm, true), MULTI_EXT_CFG_BOOL("zba", ext_zba, true), MULTI_EXT_CFG_BOOL("zbb", ext_zbb, true), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 73fd4b3231..6eef4a51ea 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -69,6 +69,7 @@ struct RISCVCPUConfig { bool ext_zicond; bool ext_zihintntl; bool ext_zihintpause; + bool ext_zihpm; bool ext_smstateen; bool ext_sstc; bool ext_svadu; diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index a1e4ed2e24..093bda2e75 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -549,6 +549,19 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) cpu->cfg.ext_zicntr = false; } + if (cpu->cfg.ext_zihpm && !cpu->cfg.ext_zicsr) { + if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zihpm))) { + error_setg(errp, "zihpm requires zicsr"); + return; + } + cpu->cfg.ext_zihpm = false; + } + + if (!cpu->cfg.ext_zihpm) { + cpu->cfg.pmu_num = 0; + cpu->pmu_avail_ctrs = 0; + } + /* * Disable isa extensions based on priv spec after we * validated and set everything we need. From b4ceb3f2f37bffab379c8aa531730d6ec31b9930 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 23 Oct 2023 12:39:27 -0300 Subject: [PATCH 25/49] target/riscv/kvm: add zihpm reg Add zihpm support in the KVM driver now that QEMU supports it. This reg was added in Linux 6.6. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20231023153927.435083-5-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/kvm/kvm-cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 0c5c0e957b..a11c0e4a99 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -230,6 +230,7 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zicboz", ext_zicboz, KVM_RISCV_ISA_EXT_ZICBOZ), KVM_EXT_CFG("zicntr", ext_zicntr, KVM_RISCV_ISA_EXT_ZICNTR), KVM_EXT_CFG("zihintpause", ext_zihintpause, KVM_RISCV_ISA_EXT_ZIHINTPAUSE), + KVM_EXT_CFG("zihpm", ext_zihpm, KVM_RISCV_ISA_EXT_ZIHPM), KVM_EXT_CFG("zbb", ext_zbb, KVM_RISCV_ISA_EXT_ZBB), KVM_EXT_CFG("ssaia", ext_ssaia, KVM_RISCV_ISA_EXT_SSAIA), KVM_EXT_CFG("sstc", ext_sstc, KVM_RISCV_ISA_EXT_SSTC), From 672ec6061f13af21cbfa560ab2c0eea1a600d950 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 31 Oct 2023 17:51:50 -0300 Subject: [PATCH 26/49] target/riscv/kvm: add zicsr, zifencei, zba, zbs, svnapot These regs were added in Linux 6.6. Signed-off-by: Daniel Henrique Barboza Acked-by: Alistair Francis Message-ID: <20231031205150.208405-1-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/kvm/kvm-cpu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index a11c0e4a99..78fa1fa162 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -229,12 +229,17 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zicbom", ext_zicbom, KVM_RISCV_ISA_EXT_ZICBOM), KVM_EXT_CFG("zicboz", ext_zicboz, KVM_RISCV_ISA_EXT_ZICBOZ), KVM_EXT_CFG("zicntr", ext_zicntr, KVM_RISCV_ISA_EXT_ZICNTR), + KVM_EXT_CFG("zicsr", ext_zicsr, KVM_RISCV_ISA_EXT_ZICSR), + KVM_EXT_CFG("zifencei", ext_zifencei, KVM_RISCV_ISA_EXT_ZIFENCEI), KVM_EXT_CFG("zihintpause", ext_zihintpause, KVM_RISCV_ISA_EXT_ZIHINTPAUSE), KVM_EXT_CFG("zihpm", ext_zihpm, KVM_RISCV_ISA_EXT_ZIHPM), + KVM_EXT_CFG("zba", ext_zba, KVM_RISCV_ISA_EXT_ZBA), KVM_EXT_CFG("zbb", ext_zbb, KVM_RISCV_ISA_EXT_ZBB), + KVM_EXT_CFG("zbs", ext_zbs, KVM_RISCV_ISA_EXT_ZBS), KVM_EXT_CFG("ssaia", ext_ssaia, KVM_RISCV_ISA_EXT_SSAIA), KVM_EXT_CFG("sstc", ext_sstc, KVM_RISCV_ISA_EXT_SSTC), KVM_EXT_CFG("svinval", ext_svinval, KVM_RISCV_ISA_EXT_SVINVAL), + KVM_EXT_CFG("svnapot", ext_svnapot, KVM_RISCV_ISA_EXT_SVNAPOT), KVM_EXT_CFG("svpbmt", ext_svpbmt, KVM_RISCV_ISA_EXT_SVPBMT), }; From 2f32dcabc2f0dfe7ee8c604dafb8ef450d78f452 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 30 Oct 2023 12:21:05 +0200 Subject: [PATCH 27/49] target/riscv: correct csr_ops[CSR_MSECCFG] The CSR register mseccfg is used by multiple extensions: Smepm and Zkr. Consider this when checking the existence of the register. Fixes: 77442380ecbe ("target/riscv: rvk: add CSR support for Zkr") Signed-off-by: Heinrich Schuchardt Reviewed-by: Alistair Francis Message-ID: <20231030102105.19501-1-heinrich.schuchardt@canonical.com> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 4ca96ddd1d..fc26b52c88 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -528,11 +528,14 @@ static RISCVException pmp(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } -static RISCVException smepmp(CPURISCVState *env, int csrno) +static RISCVException have_mseccfg(CPURISCVState *env, int csrno) { if (riscv_cpu_cfg(env)->ext_smepmp) { return RISCV_EXCP_NONE; } + if (riscv_cpu_cfg(env)->ext_zkr) { + return RISCV_EXCP_NONE; + } return RISCV_EXCP_ILLEGAL_INST; } @@ -4766,7 +4769,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_VSIPH] = { "vsiph", aia_hmode32, NULL, NULL, rmw_vsiph }, /* Physical Memory Protection */ - [CSR_MSECCFG] = { "mseccfg", smepmp, read_mseccfg, write_mseccfg, + [CSR_MSECCFG] = { "mseccfg", have_mseccfg, read_mseccfg, write_mseccfg, .min_priv_ver = PRIV_VERSION_1_11_0 }, [CSR_PMPCFG0] = { "pmpcfg0", pmp, read_pmpcfg, write_pmpcfg }, [CSR_PMPCFG1] = { "pmpcfg1", pmp, read_pmpcfg, write_pmpcfg }, From c0ce1f2a88c7fb7c923e1764d7af53f4cc815486 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Mon, 30 Oct 2023 16:16:07 +0800 Subject: [PATCH 28/49] MAINTAINERS: update mail address for Weiwei Li MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit My Iscas mail account will be disabled soon, change to my personal gmail account. Signed-off-by: Weiwei Li Reviewed-by: Bin Meng Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-ID: <20231030081607.115118-2-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 8e8a7d5be5..1de7f381e8 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -323,7 +323,7 @@ RISC-V TCG CPUs M: Palmer Dabbelt M: Alistair Francis M: Bin Meng -R: Weiwei Li +R: Weiwei Li R: Daniel Henrique Barboza R: Liu Zhiwei L: qemu-riscv@nongnu.org From 5ddbc83ff2f830f2e96c933d78ccf59c1507eab6 Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:08 +0800 Subject: [PATCH 29/49] target/riscv: Add cfg property for Zvkt extension Vector crypto spec defines the Zvkt extension that included all of the instructions of Zvbb & Zvbc extensions and some vector instructions. Signed-off-by: Max Chou Acked-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231026151828.754279-2-max.chou@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/cpu_cfg.h | 1 + target/riscv/tcg/tcg-cpu.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 6eef4a51ea..1f0dac5c8a 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -96,6 +96,7 @@ struct RISCVCPUConfig { bool ext_zvknhb; bool ext_zvksed; bool ext_zvksh; + bool ext_zvkt; bool ext_zmmul; bool ext_zvfbfmin; bool ext_zvfbfwma; diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 093bda2e75..87baae56a1 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -499,6 +499,11 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) return; } + if (cpu->cfg.ext_zvkt) { + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbb), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true); + } + /* * In principle Zve*x would also suffice here, were they supported * in qemu From 1c32b6306648ad46002a0ec13ec6719f5e9e82cb Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:09 +0800 Subject: [PATCH 30/49] target/riscv: Expose Zvkt extension property Signed-off-by: Max Chou Acked-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231026151828.754279-3-max.chou@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index f40da4c661..9604ba6171 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -133,6 +133,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zvknhb, PRIV_VERSION_1_12_0, ext_zvknhb), ISA_EXT_DATA_ENTRY(zvksed, PRIV_VERSION_1_12_0, ext_zvksed), ISA_EXT_DATA_ENTRY(zvksh, PRIV_VERSION_1_12_0, ext_zvksh), + ISA_EXT_DATA_ENTRY(zvkt, PRIV_VERSION_1_12_0, ext_zvkt), 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(smaia, PRIV_VERSION_1_12_0, ext_smaia), @@ -1390,6 +1391,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { MULTI_EXT_CFG_BOOL("x-zvknhb", ext_zvknhb, false), MULTI_EXT_CFG_BOOL("x-zvksed", ext_zvksed, false), MULTI_EXT_CFG_BOOL("x-zvksh", ext_zvksh, false), + MULTI_EXT_CFG_BOOL("x-zvkt", ext_zvkt, false), DEFINE_PROP_END_OF_LIST(), }; From 389b2e70141fda7009bcd7c2755fd84176d543b1 Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:10 +0800 Subject: [PATCH 31/49] target/riscv: Add cfg property for Zvkb extension After vector crypto spec v1.0.0-rc3 release, the Zvkb extension is defined as a proper subset of the Zvbb extension. And both the Zvkn and Zvks shorthand extensions replace the included Zvbb extension by Zvkb extnesion. Signed-off-by: Max Chou Acked-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231026151828.754279-4-max.chou@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/cpu_cfg.h | 1 + target/riscv/tcg/tcg-cpu.c | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 1f0dac5c8a..c4b2fec024 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -90,6 +90,7 @@ struct RISCVCPUConfig { bool ext_zve64d; bool ext_zvbb; bool ext_zvbc; + bool ext_zvkb; bool ext_zvkg; bool ext_zvkned; bool ext_zvknha; diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 87baae56a1..ad7a183a74 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -508,9 +508,9 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) * In principle Zve*x would also suffice here, were they supported * in qemu */ - if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkg || cpu->cfg.ext_zvkned || - cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed || cpu->cfg.ext_zvksh) && - !cpu->cfg.ext_zve32f) { + if ((cpu->cfg.ext_zvbb || cpu->cfg.ext_zvkb || cpu->cfg.ext_zvkg || + cpu->cfg.ext_zvkned || cpu->cfg.ext_zvknha || cpu->cfg.ext_zvksed || + cpu->cfg.ext_zvksh) && !cpu->cfg.ext_zve32f) { error_setg(errp, "Vector crypto extensions require V or Zve* extensions"); return; From 1db699f8c2a4c42def5a1ad2d5b48371d28b6278 Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:11 +0800 Subject: [PATCH 32/49] target/riscv: Replace Zvbb checking by Zvkb The Zvkb extension is a proper subset of the Zvbb extension and includes following instructions: * vandn.[vv,vx] * vbrev8.v * vrev8.v * vrol.[vv,vx] * vror.[vv,vx,vi] Signed-off-by: Max Chou Reviewed-by: Daniel Henrique Barboza Message-ID: <20231026151828.754279-5-max.chou@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvvk.c.inc | 37 +++++++++++++++--------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvvk.c.inc b/target/riscv/insn_trans/trans_rvvk.c.inc index e691519ed7..3801c16829 100644 --- a/target/riscv/insn_trans/trans_rvvk.c.inc +++ b/target/riscv/insn_trans/trans_rvvk.c.inc @@ -112,24 +112,27 @@ GEN_VX_MASKED_TRANS(vclmulh_vx, vclmul_vx_check) return false; \ } -static bool zvbb_vv_check(DisasContext *s, arg_rmrr *a) +static bool zvkb_vv_check(DisasContext *s, arg_rmrr *a) { - return opivv_check(s, a) && s->cfg_ptr->ext_zvbb == true; + return opivv_check(s, a) && + (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true); } -static bool zvbb_vx_check(DisasContext *s, arg_rmrr *a) +static bool zvkb_vx_check(DisasContext *s, arg_rmrr *a) { - return opivx_check(s, a) && s->cfg_ptr->ext_zvbb == true; + return opivx_check(s, a) && + (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true); } /* vrol.v[vx] */ -GEN_OPIVV_GVEC_TRANS_CHECK(vrol_vv, rotlv, zvbb_vv_check) -GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vrol_vx, rotls, zvbb_vx_check) +GEN_OPIVV_GVEC_TRANS_CHECK(vrol_vv, rotlv, zvkb_vv_check) +GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vrol_vx, rotls, zvkb_vx_check) /* vror.v[vxi] */ -GEN_OPIVV_GVEC_TRANS_CHECK(vror_vv, rotrv, zvbb_vv_check) -GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vror_vx, rotrs, zvbb_vx_check) -GEN_OPIVI_GVEC_TRANS_CHECK(vror_vi, IMM_TRUNC_SEW, vror_vx, rotri, zvbb_vx_check) +GEN_OPIVV_GVEC_TRANS_CHECK(vror_vv, rotrv, zvkb_vv_check) +GEN_OPIVX_GVEC_SHIFT_TRANS_CHECK(vror_vx, rotrs, zvkb_vx_check) +GEN_OPIVI_GVEC_TRANS_CHECK(vror_vi, IMM_TRUNC_SEW, vror_vx, rotri, + zvkb_vx_check) #define GEN_OPIVX_GVEC_TRANS_CHECK(NAME, SUF, CHECK) \ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ @@ -147,8 +150,8 @@ GEN_OPIVI_GVEC_TRANS_CHECK(vror_vi, IMM_TRUNC_SEW, vror_vx, rotri, zvbb_vx_check } /* vandn.v[vx] */ -GEN_OPIVV_GVEC_TRANS_CHECK(vandn_vv, andc, zvbb_vv_check) -GEN_OPIVX_GVEC_TRANS_CHECK(vandn_vx, andcs, zvbb_vx_check) +GEN_OPIVV_GVEC_TRANS_CHECK(vandn_vv, andc, zvkb_vv_check) +GEN_OPIVX_GVEC_TRANS_CHECK(vandn_vx, andcs, zvkb_vx_check) #define GEN_OPIV_TRANS(NAME, CHECK) \ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ @@ -188,8 +191,16 @@ static bool zvbb_opiv_check(DisasContext *s, arg_rmr *a) vext_check_ss(s, a->rd, a->rs2, a->vm); } -GEN_OPIV_TRANS(vbrev8_v, zvbb_opiv_check) -GEN_OPIV_TRANS(vrev8_v, zvbb_opiv_check) +static bool zvkb_opiv_check(DisasContext *s, arg_rmr *a) +{ + return (s->cfg_ptr->ext_zvbb == true || s->cfg_ptr->ext_zvkb == true) && + require_rvv(s) && + vext_check_isa_ill(s) && + vext_check_ss(s, a->rd, a->rs2, a->vm); +} + +GEN_OPIV_TRANS(vbrev8_v, zvkb_opiv_check) +GEN_OPIV_TRANS(vrev8_v, zvkb_opiv_check) GEN_OPIV_TRANS(vbrev_v, zvbb_opiv_check) GEN_OPIV_TRANS(vclz_v, zvbb_opiv_check) GEN_OPIV_TRANS(vctz_v, zvbb_opiv_check) From f209cb0a83cc57bb172bff4b862932a408d46b58 Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:12 +0800 Subject: [PATCH 33/49] target/riscv: Expose Zvkb extension property Signed-off-by: Max Chou Acked-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231026151828.754279-6-max.chou@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 9604ba6171..3eedf8b7ce 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -127,6 +127,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zvfbfwma, PRIV_VERSION_1_12_0, ext_zvfbfwma), ISA_EXT_DATA_ENTRY(zvfh, PRIV_VERSION_1_12_0, ext_zvfh), ISA_EXT_DATA_ENTRY(zvfhmin, PRIV_VERSION_1_12_0, ext_zvfhmin), + ISA_EXT_DATA_ENTRY(zvkb, PRIV_VERSION_1_12_0, ext_zvkb), ISA_EXT_DATA_ENTRY(zvkg, PRIV_VERSION_1_12_0, ext_zvkg), ISA_EXT_DATA_ENTRY(zvkned, PRIV_VERSION_1_12_0, ext_zvkned), ISA_EXT_DATA_ENTRY(zvknha, PRIV_VERSION_1_12_0, ext_zvknha), @@ -1385,6 +1386,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { /* Vector cryptography extensions */ MULTI_EXT_CFG_BOOL("x-zvbb", ext_zvbb, false), MULTI_EXT_CFG_BOOL("x-zvbc", ext_zvbc, false), + MULTI_EXT_CFG_BOOL("x-zvkb", ext_zvkg, false), MULTI_EXT_CFG_BOOL("x-zvkg", ext_zvkg, false), MULTI_EXT_CFG_BOOL("x-zvkned", ext_zvkned, false), MULTI_EXT_CFG_BOOL("x-zvknha", ext_zvknha, false), From 7cdc8ddb080863c7883762961e5012f08487ce98 Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:13 +0800 Subject: [PATCH 34/49] target/riscv: Add cfg properties for Zvkn[c|g] extensions Vector crypto spec defines the NIST algorithm suite related extensions (Zvkn, Zvknc, Zvkng) combined by several vector crypto extensions. Signed-off-by: Max Chou Acked-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231026151828.754279-7-max.chou@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/cpu_cfg.h | 3 +++ target/riscv/tcg/tcg-cpu.c | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index c4b2fec024..08733002a7 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -98,6 +98,9 @@ struct RISCVCPUConfig { bool ext_zvksed; bool ext_zvksh; bool ext_zvkt; + bool ext_zvkn; + bool ext_zvknc; + bool ext_zvkng; bool ext_zmmul; bool ext_zvfbfmin; bool ext_zvfbfwma; diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index ad7a183a74..9540d1df4e 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -499,6 +499,26 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) return; } + /* + * Shorthand vector crypto extensions + */ + if (cpu->cfg.ext_zvknc) { + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkn), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true); + } + + if (cpu->cfg.ext_zvkng) { + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkn), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkg), true); + } + + if (cpu->cfg.ext_zvkn) { + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkned), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvknhb), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkb), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkt), true); + } + if (cpu->cfg.ext_zvkt) { cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbb), true); cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true); From 23aaefb9c9900c385c74b3490e60da2040f8200e Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:14 +0800 Subject: [PATCH 35/49] target/riscv: Expose Zvkn[c|g] extnesion properties Expose the properties of NIST Algorithm Suite related extensions (Zvkn, Zvknc, Zvkng). Signed-off-by: Max Chou Acked-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231026151828.754279-8-max.chou@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 3eedf8b7ce..208faffbbf 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -129,7 +129,10 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zvfhmin, PRIV_VERSION_1_12_0, ext_zvfhmin), ISA_EXT_DATA_ENTRY(zvkb, PRIV_VERSION_1_12_0, ext_zvkb), ISA_EXT_DATA_ENTRY(zvkg, PRIV_VERSION_1_12_0, ext_zvkg), + ISA_EXT_DATA_ENTRY(zvkn, PRIV_VERSION_1_12_0, ext_zvkn), + ISA_EXT_DATA_ENTRY(zvknc, PRIV_VERSION_1_12_0, ext_zvknc), ISA_EXT_DATA_ENTRY(zvkned, PRIV_VERSION_1_12_0, ext_zvkned), + ISA_EXT_DATA_ENTRY(zvkng, PRIV_VERSION_1_12_0, ext_zvkng), ISA_EXT_DATA_ENTRY(zvknha, PRIV_VERSION_1_12_0, ext_zvknha), ISA_EXT_DATA_ENTRY(zvknhb, PRIV_VERSION_1_12_0, ext_zvknhb), ISA_EXT_DATA_ENTRY(zvksed, PRIV_VERSION_1_12_0, ext_zvksed), @@ -1394,6 +1397,9 @@ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { MULTI_EXT_CFG_BOOL("x-zvksed", ext_zvksed, false), MULTI_EXT_CFG_BOOL("x-zvksh", ext_zvksh, false), MULTI_EXT_CFG_BOOL("x-zvkt", ext_zvkt, false), + MULTI_EXT_CFG_BOOL("x-zvkn", ext_zvkn, false), + MULTI_EXT_CFG_BOOL("x-zvknc", ext_zvknc, false), + MULTI_EXT_CFG_BOOL("x-zvkng", ext_zvkng, false), DEFINE_PROP_END_OF_LIST(), }; From 8f913d1004766c8ee96bcab78a6c39764aa5ee52 Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:15 +0800 Subject: [PATCH 36/49] target/riscv: Add cfg properties for Zvks[c|g] extensions Vector crypto spec defines the ShangMi algorithm suite related extensions (Zvks, Zvksc, Zvksg) combined by several vector crypto extensions. Signed-off-by: Max Chou Acked-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231026151828.754279-9-max.chou@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/cpu_cfg.h | 3 +++ target/riscv/tcg/tcg-cpu.c | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 08733002a7..634ff673b3 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -101,6 +101,9 @@ struct RISCVCPUConfig { bool ext_zvkn; bool ext_zvknc; bool ext_zvkng; + bool ext_zvks; + bool ext_zvksc; + bool ext_zvksg; bool ext_zmmul; bool ext_zvfbfmin; bool ext_zvfbfwma; diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 9540d1df4e..1a3351b142 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -519,6 +519,23 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkt), true); } + if (cpu->cfg.ext_zvksc) { + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvks), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true); + } + + if (cpu->cfg.ext_zvksg) { + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvks), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkg), true); + } + + if (cpu->cfg.ext_zvks) { + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvksed), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvksh), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkb), true); + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvkt), true); + } + if (cpu->cfg.ext_zvkt) { cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbb), true); cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvbc), true); From b43419f2dc5a95f6861156ecff5654ad48fec010 Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:16 +0800 Subject: [PATCH 37/49] target/riscv: Expose Zvks[c|g] extnesion properties Expose the properties of ShangMi Algorithm Suite related extensions (Zvks, Zvksc, Zvksg). Signed-off-by: Max Chou Acked-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231026151828.754279-10-max.chou@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 208faffbbf..f61ed7cf60 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -135,7 +135,10 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zvkng, PRIV_VERSION_1_12_0, ext_zvkng), ISA_EXT_DATA_ENTRY(zvknha, PRIV_VERSION_1_12_0, ext_zvknha), ISA_EXT_DATA_ENTRY(zvknhb, PRIV_VERSION_1_12_0, ext_zvknhb), + ISA_EXT_DATA_ENTRY(zvks, PRIV_VERSION_1_12_0, ext_zvks), + ISA_EXT_DATA_ENTRY(zvksc, PRIV_VERSION_1_12_0, ext_zvksc), ISA_EXT_DATA_ENTRY(zvksed, PRIV_VERSION_1_12_0, ext_zvksed), + ISA_EXT_DATA_ENTRY(zvksg, PRIV_VERSION_1_12_0, ext_zvksg), ISA_EXT_DATA_ENTRY(zvksh, PRIV_VERSION_1_12_0, ext_zvksh), ISA_EXT_DATA_ENTRY(zvkt, PRIV_VERSION_1_12_0, ext_zvkt), ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx), @@ -1400,6 +1403,9 @@ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { MULTI_EXT_CFG_BOOL("x-zvkn", ext_zvkn, false), MULTI_EXT_CFG_BOOL("x-zvknc", ext_zvknc, false), MULTI_EXT_CFG_BOOL("x-zvkng", ext_zvkng, false), + MULTI_EXT_CFG_BOOL("x-zvks", ext_zvks, false), + MULTI_EXT_CFG_BOOL("x-zvksc", ext_zvksc, false), + MULTI_EXT_CFG_BOOL("x-zvksg", ext_zvksg, false), DEFINE_PROP_END_OF_LIST(), }; From ea61ef7097d05b55cc0ff3e8826eea7fbbe0c0a9 Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:17 +0800 Subject: [PATCH 38/49] target/riscv: Move vector crypto extensions to riscv_cpu_extensions Because the vector crypto specification is ratified, so move theses extensions from riscv_cpu_experimental_exts to riscv_cpu_extensions. Signed-off-by: Max Chou Acked-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231026151828.754279-11-max.chou@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index f61ed7cf60..d73e1da2a2 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1357,6 +1357,24 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { MULTI_EXT_CFG_BOOL("zcmt", ext_zcmt, false), MULTI_EXT_CFG_BOOL("zicond", ext_zicond, 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_zvkg, 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), + DEFINE_PROP_END_OF_LIST(), }; @@ -1389,24 +1407,6 @@ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { MULTI_EXT_CFG_BOOL("x-zvfbfmin", ext_zvfbfmin, false), MULTI_EXT_CFG_BOOL("x-zvfbfwma", ext_zvfbfwma, false), - /* Vector cryptography extensions */ - MULTI_EXT_CFG_BOOL("x-zvbb", ext_zvbb, false), - MULTI_EXT_CFG_BOOL("x-zvbc", ext_zvbc, false), - MULTI_EXT_CFG_BOOL("x-zvkb", ext_zvkg, false), - MULTI_EXT_CFG_BOOL("x-zvkg", ext_zvkg, false), - MULTI_EXT_CFG_BOOL("x-zvkned", ext_zvkned, false), - MULTI_EXT_CFG_BOOL("x-zvknha", ext_zvknha, false), - MULTI_EXT_CFG_BOOL("x-zvknhb", ext_zvknhb, false), - MULTI_EXT_CFG_BOOL("x-zvksed", ext_zvksed, false), - MULTI_EXT_CFG_BOOL("x-zvksh", ext_zvksh, false), - MULTI_EXT_CFG_BOOL("x-zvkt", ext_zvkt, false), - MULTI_EXT_CFG_BOOL("x-zvkn", ext_zvkn, false), - MULTI_EXT_CFG_BOOL("x-zvknc", ext_zvknc, false), - MULTI_EXT_CFG_BOOL("x-zvkng", ext_zvkng, false), - MULTI_EXT_CFG_BOOL("x-zvks", ext_zvks, false), - MULTI_EXT_CFG_BOOL("x-zvksc", ext_zvksc, false), - MULTI_EXT_CFG_BOOL("x-zvksg", ext_zvksg, false), - DEFINE_PROP_END_OF_LIST(), }; From ea363626ff65b2b8e6c590812f89546d5779612f Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:18 +0800 Subject: [PATCH 39/49] disas/riscv: Add rv_fmt_vd_vs2_uimm format Add rv_fmt_vd_vs2_uimm format for vector crypto instructions. Signed-off-by: Max Chou Acked-by: Alistair Francis Message-ID: <20231026151828.754279-12-max.chou@sifive.com> Signed-off-by: Alistair Francis --- disas/riscv.h | 1 + 1 file changed, 1 insertion(+) diff --git a/disas/riscv.h b/disas/riscv.h index 8abb578b51..b242d73b25 100644 --- a/disas/riscv.h +++ b/disas/riscv.h @@ -274,6 +274,7 @@ enum { #define rv_fmt_vd_vs2_fs1_vm "O\tD,F,4m" #define rv_fmt_vd_vs2_imm_vl "O\tD,F,il" #define rv_fmt_vd_vs2_imm_vm "O\tD,F,im" +#define rv_fmt_vd_vs2_uimm "O\tD,F,u" #define rv_fmt_vd_vs2_uimm_vm "O\tD,F,um" #define rv_fmt_vd_vs1_vs2_vm "O\tD,E,Fm" #define rv_fmt_vd_rs1_vs2_vm "O\tD,1,Fm" From 434c609bef445e0dd13d514c5b12f8e47a73cd1d Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:19 +0800 Subject: [PATCH 40/49] disas/riscv: Add rv_codec_vror_vi for vror.vi Add rv_codec_vror_vi for the vector crypto instruction - vror.vi. The rotate amount of vror.vi is defined by combining seperated bits. Signed-off-by: Max Chou Acked-by: Alistair Francis Message-ID: <20231026151828.754279-13-max.chou@sifive.com> Signed-off-by: Alistair Francis --- disas/riscv.c | 14 +++++++++++++- disas/riscv.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/disas/riscv.c b/disas/riscv.c index 8e89e1d115..ec33e447f5 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -4011,6 +4011,12 @@ static uint32_t operand_vzimm10(rv_inst inst) return (inst << 34) >> 54; } +static uint32_t operand_vzimm6(rv_inst inst) +{ + return ((inst << 37) >> 63) << 5 | + ((inst << 44) >> 59); +} + static uint32_t operand_bs(rv_inst inst) { return (inst << 32) >> 62; @@ -4393,6 +4399,12 @@ static void decode_inst_operands(rv_decode *dec, rv_isa isa) dec->imm = operand_vimm(inst); dec->vm = operand_vm(inst); break; + case rv_codec_vror_vi: + dec->rd = operand_rd(inst); + dec->rs2 = operand_rs2(inst); + dec->imm = operand_vzimm6(inst); + dec->vm = operand_vm(inst); + break; case rv_codec_vsetvli: dec->rd = operand_rd(inst); dec->rs1 = operand_rs1(inst); @@ -4677,7 +4689,7 @@ static void format_inst(char *buf, size_t buflen, size_t tab, rv_decode *dec) append(buf, tmp, buflen); break; case 'u': - snprintf(tmp, sizeof(tmp), "%u", ((uint32_t)dec->imm & 0b11111)); + snprintf(tmp, sizeof(tmp), "%u", ((uint32_t)dec->imm & 0b111111)); append(buf, tmp, buflen); break; case 'j': diff --git a/disas/riscv.h b/disas/riscv.h index b242d73b25..19e5ed2ce6 100644 --- a/disas/riscv.h +++ b/disas/riscv.h @@ -152,6 +152,7 @@ typedef enum { rv_codec_v_i, rv_codec_vsetvli, rv_codec_vsetivli, + rv_codec_vror_vi, rv_codec_zcb_ext, rv_codec_zcb_mul, rv_codec_zcb_lb, From 9d92f56d4a44a14ec099e9af5148c4c9c85fd59e Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:20 +0800 Subject: [PATCH 41/49] disas/riscv: Add support for vector crypto extensions This patch adds following v1.0.0 ratified vector crypto extensions support to the RISC-V disassembler. - Zvbb - Zvbc - Zvkb - Zvkg - Zvkned - Zvknha - Zvknhb - Zvksed - Zvksh Signed-off-by: Max Chou Message-ID: <20231026151828.754279-14-max.chou@sifive.com> Signed-off-by: Alistair Francis --- disas/riscv.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/disas/riscv.c b/disas/riscv.c index ec33e447f5..7ea6ea050e 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -862,6 +862,47 @@ typedef enum { rv_op_fltq_q = 831, rv_op_fleq_h = 832, rv_op_fltq_h = 833, + rv_op_vaesdf_vv = 834, + rv_op_vaesdf_vs = 835, + rv_op_vaesdm_vv = 836, + rv_op_vaesdm_vs = 837, + rv_op_vaesef_vv = 838, + rv_op_vaesef_vs = 839, + rv_op_vaesem_vv = 840, + rv_op_vaesem_vs = 841, + rv_op_vaeskf1_vi = 842, + rv_op_vaeskf2_vi = 843, + rv_op_vaesz_vs = 844, + rv_op_vandn_vv = 845, + rv_op_vandn_vx = 846, + rv_op_vbrev_v = 847, + rv_op_vbrev8_v = 848, + rv_op_vclmul_vv = 849, + rv_op_vclmul_vx = 850, + rv_op_vclmulh_vv = 851, + rv_op_vclmulh_vx = 852, + rv_op_vclz_v = 853, + rv_op_vcpop_v = 854, + rv_op_vctz_v = 855, + rv_op_vghsh_vv = 856, + rv_op_vgmul_vv = 857, + rv_op_vrev8_v = 858, + rv_op_vrol_vv = 859, + rv_op_vrol_vx = 860, + rv_op_vror_vv = 861, + rv_op_vror_vx = 862, + rv_op_vror_vi = 863, + rv_op_vsha2ch_vv = 864, + rv_op_vsha2cl_vv = 865, + rv_op_vsha2ms_vv = 866, + rv_op_vsm3c_vi = 867, + rv_op_vsm3me_vv = 868, + rv_op_vsm4k_vi = 869, + rv_op_vsm4r_vv = 870, + rv_op_vsm4r_vs = 871, + rv_op_vwsll_vv = 872, + rv_op_vwsll_vx = 873, + rv_op_vwsll_vi = 874, } rv_op; /* register names */ @@ -2008,6 +2049,47 @@ const rv_opcode_data rvi_opcode_data[] = { { "fltq.q", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, { "fleq.h", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, { "fltq.h", rv_codec_r, rv_fmt_rd_frs1_frs2, NULL, 0, 0, 0 }, + { "vaesdf.vv", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vaesdf.vs", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vaesdm.vv", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vaesdm.vs", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vaesef.vv", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vaesef.vs", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vaesem.vv", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vaesem.vs", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vaeskf1.vi", rv_codec_v_i, rv_fmt_vd_vs2_uimm, NULL, 0, 0, 0 }, + { "vaeskf2.vi", rv_codec_v_i, rv_fmt_vd_vs2_uimm, NULL, 0, 0, 0 }, + { "vaesz.vs", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vandn.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1_vm, NULL, 0, 0, 0 }, + { "vandn.vx", rv_codec_v_r, rv_fmt_vd_vs2_rs1_vm, NULL, 0, 0, 0 }, + { "vbrev.v", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, 0, 0, 0 }, + { "vbrev8.v", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, 0, 0, 0 }, + { "vclmul.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1_vm, NULL, 0, 0, 0 }, + { "vclmul.vx", rv_codec_v_r, rv_fmt_vd_vs2_rs1_vm, NULL, 0, 0, 0 }, + { "vclmulh.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1_vm, NULL, 0, 0, 0 }, + { "vclmulh.vx", rv_codec_v_r, rv_fmt_vd_vs2_rs1_vm, NULL, 0, 0, 0 }, + { "vclz.v", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, 0, 0, 0 }, + { "vcpop.v", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, 0, 0, 0 }, + { "vctz.v", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, 0, 0, 0 }, + { "vghsh.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1, NULL, 0, 0, 0 }, + { "vgmul.vv", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vrev8.v", rv_codec_v_r, rv_fmt_vd_vs2_vm, NULL, 0, 0, 0 }, + { "vrol.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1_vm, NULL, 0, 0, 0 }, + { "vrol.vx", rv_codec_v_r, rv_fmt_vd_vs2_rs1_vm, NULL, 0, 0, 0 }, + { "vror.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1_vm, NULL, 0, 0, 0 }, + { "vror.vx", rv_codec_v_r, rv_fmt_vd_vs2_rs1_vm, NULL, 0, 0, 0 }, + { "vror.vi", rv_codec_vror_vi, rv_fmt_vd_vs2_uimm_vm, NULL, 0, 0, 0 }, + { "vsha2ch.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1, NULL, 0, 0, 0 }, + { "vsha2cl.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1, NULL, 0, 0, 0 }, + { "vsha2ms.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1, NULL, 0, 0, 0 }, + { "vsm3c.vi", rv_codec_v_i, rv_fmt_vd_vs2_uimm, NULL, 0, 0, 0 }, + { "vsm3me.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1, NULL, 0, 0, 0 }, + { "vsm4k.vi", rv_codec_v_i, rv_fmt_vd_vs2_uimm, NULL, 0, 0, 0 }, + { "vsm4r.vv", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vsm4r.vs", rv_codec_v_r, rv_fmt_vd_vs2, NULL, 0, 0, 0 }, + { "vwsll.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1_vm, NULL, 0, 0, 0 }, + { "vwsll.vx", rv_codec_v_r, rv_fmt_vd_vs2_rs1_vm, NULL, 0, 0, 0 }, + { "vwsll.vi", rv_codec_v_i, rv_fmt_vd_vs2_uimm_vm, NULL, 0, 0, 0 }, }; /* CSR names */ @@ -3176,6 +3258,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 0: switch ((inst >> 26) & 0b111111) { case 0: op = rv_op_vadd_vv; break; + case 1: op = rv_op_vandn_vv; break; case 2: op = rv_op_vsub_vv; break; case 4: op = rv_op_vminu_vv; break; case 5: op = rv_op_vmin_vv; break; @@ -3198,6 +3281,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) } break; case 19: op = rv_op_vmsbc_vvm; break; + case 20: op = rv_op_vror_vv; break; + case 21: op = rv_op_vrol_vv; break; case 23: if (((inst >> 20) & 0b111111) == 32) op = rv_op_vmv_v_v; @@ -3226,6 +3311,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 47: op = rv_op_vnclip_wv; break; case 48: op = rv_op_vwredsumu_vs; break; case 49: op = rv_op_vwredsum_vs; break; + case 53: op = rv_op_vwsll_vv; break; } break; case 1: @@ -3323,6 +3409,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 9: op = rv_op_vaadd_vv; break; case 10: op = rv_op_vasubu_vv; break; case 11: op = rv_op_vasub_vv; break; + case 12: op = rv_op_vclmul_vv; break; + case 13: op = rv_op_vclmulh_vv; break; case 16: switch ((inst >> 15) & 0b11111) { case 0: if ((inst >> 25) & 1) op = rv_op_vmv_x_s; break; @@ -3338,6 +3426,12 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 5: op = rv_op_vsext_vf4; break; case 6: op = rv_op_vzext_vf2; break; case 7: op = rv_op_vsext_vf2; break; + case 8: op = rv_op_vbrev8_v; break; + case 9: op = rv_op_vrev8_v; break; + case 10: op = rv_op_vbrev_v; break; + case 12: op = rv_op_vclz_v; break; + case 13: op = rv_op_vctz_v; break; + case 14: op = rv_op_vcpop_v; break; } break; case 20: @@ -3406,6 +3500,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) } break; case 17: op = rv_op_vmadc_vim; break; + case 20: case 21: op = rv_op_vror_vi; break; case 23: if (((inst >> 20) & 0b111111) == 32) op = rv_op_vmv_v_i; @@ -3437,11 +3532,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 45: op = rv_op_vnsra_wi; break; case 46: op = rv_op_vnclipu_wi; break; case 47: op = rv_op_vnclip_wi; break; + case 53: op = rv_op_vwsll_vi; break; } break; case 4: switch ((inst >> 26) & 0b111111) { case 0: op = rv_op_vadd_vx; break; + case 1: op = rv_op_vandn_vx; break; case 2: op = rv_op_vsub_vx; break; case 3: op = rv_op_vrsub_vx; break; case 4: op = rv_op_vminu_vx; break; @@ -3466,6 +3563,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) } break; case 19: op = rv_op_vmsbc_vxm; break; + case 20: op = rv_op_vror_vx; break; + case 21: op = rv_op_vrol_vx; break; case 23: if (((inst >> 20) & 0b111111) == 32) op = rv_op_vmv_v_x; @@ -3494,6 +3593,7 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 45: op = rv_op_vnsra_wx; break; case 46: op = rv_op_vnclipu_wx; break; case 47: op = rv_op_vnclip_wx; break; + case 53: op = rv_op_vwsll_vx; break; } break; case 5: @@ -3554,6 +3654,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 9: op = rv_op_vaadd_vx; break; case 10: op = rv_op_vasubu_vx; break; case 11: op = rv_op_vasub_vx; break; + case 12: op = rv_op_vclmul_vx; break; + case 13: op = rv_op_vclmulh_vx; break; case 14: op = rv_op_vslide1up_vx; break; case 15: op = rv_op_vslide1down_vx; break; case 16: @@ -3686,6 +3788,41 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 7: op = rv_op_csrrci; break; } break; + case 29: + if (((inst >> 25) & 1) == 1 && ((inst >> 12) & 0b111) == 2) { + switch ((inst >> 26) & 0b111111) { + case 32: op = rv_op_vsm3me_vv; break; + case 33: op = rv_op_vsm4k_vi; break; + case 34: op = rv_op_vaeskf1_vi; break; + case 40: + switch ((inst >> 15) & 0b11111) { + case 0: op = rv_op_vaesdm_vv; break; + case 1: op = rv_op_vaesdf_vv; break; + case 2: op = rv_op_vaesem_vv; break; + case 3: op = rv_op_vaesef_vv; break; + case 16: op = rv_op_vsm4r_vv; break; + case 17: op = rv_op_vgmul_vv; break; + } + break; + case 41: + switch ((inst >> 15) & 0b11111) { + case 0: op = rv_op_vaesdm_vs; break; + case 1: op = rv_op_vaesdf_vs; break; + case 2: op = rv_op_vaesem_vs; break; + case 3: op = rv_op_vaesef_vs; break; + case 7: op = rv_op_vaesz_vs; break; + case 16: op = rv_op_vsm4r_vs; break; + } + break; + case 42: op = rv_op_vaeskf2_vi; break; + case 43: op = rv_op_vsm3c_vi; break; + case 44: op = rv_op_vghsh_vv; break; + case 45: op = rv_op_vsha2ms_vv; break; + case 46: op = rv_op_vsha2ch_vv; break; + case 47: op = rv_op_vsha2cl_vv; break; + } + } + break; case 30: switch (((inst >> 22) & 0b1111111000) | ((inst >> 12) & 0b0000000111)) { From 251385fd4480c0715f3d2c76a3c76534a42570fc Mon Sep 17 00:00:00 2001 From: Max Chou Date: Thu, 26 Oct 2023 23:18:21 +0800 Subject: [PATCH 42/49] disas/riscv: Replace TABs with space Replaces TABs with spaces, making sure to have a consistent coding style of 4 space indentations. Signed-off-by: Max Chou Acked-by: Alistair Francis Message-ID: <20231026151828.754279-15-max.chou@sifive.com> Signed-off-by: Alistair Francis --- disas/riscv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/disas/riscv.c b/disas/riscv.c index 7ea6ea050e..e9458e574b 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -3136,12 +3136,12 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) } break; case 89: - switch (((inst >> 12) & 0b111)) { + switch (((inst >> 12) & 0b111)) { case 0: op = rv_op_fmvp_d_x; break; } break; case 91: - switch (((inst >> 12) & 0b111)) { + switch (((inst >> 12) & 0b111)) { case 0: op = rv_op_fmvp_q_x; break; } break; @@ -4579,7 +4579,7 @@ static void decode_inst_operands(rv_decode *dec, rv_isa isa) break; case rv_codec_zcmt_jt: dec->imm = operand_tbl_index(inst); - break; + break; case rv_codec_fli: dec->rd = operand_rd(inst); dec->imm = operand_rs1(inst); From d53ead72066b1502bc3989dd11f1565d472e431d Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 2 Nov 2023 10:34:23 +1000 Subject: [PATCH 43/49] hw/ssi: ibex_spi_host: Clear the interrupt even if disabled We currently don't clear the interrupts if they are disabled. This means that if an interrupt occurs and the guest disables interrupts the QEMU IRQ will remain high. This doesn't immediately affect guests, but if the guest re-enables interrupts it's possible that we will miss an interrupt as it always remains set. Let's update the logic to always call qemu_set_irq() even if the interrupts are disabled to ensure we set the level low. The level will never be high unless interrupts are enabled, so we won't generate interrupts when we shouldn't. Signed-off-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231102003424.2003428-2-alistair.francis@wdc.com> Signed-off-by: Alistair Francis --- hw/ssi/ibex_spi_host.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/ssi/ibex_spi_host.c b/hw/ssi/ibex_spi_host.c index 1ee7d88c22..c300ec294d 100644 --- a/hw/ssi/ibex_spi_host.c +++ b/hw/ssi/ibex_spi_host.c @@ -205,9 +205,10 @@ static void ibex_spi_host_irq(IbexSPIHostState *s) if (err_irq) { s->regs[IBEX_SPI_HOST_INTR_STATE] |= R_INTR_STATE_ERROR_MASK; } - qemu_set_irq(s->host_err, err_irq); } + qemu_set_irq(s->host_err, err_irq); + /* Event IRQ Enabled and Event IRQ Cleared */ if (event_en && !status_pending) { if (FIELD_EX32(intr_test_reg, INTR_STATE, SPI_EVENT)) { @@ -229,8 +230,9 @@ static void ibex_spi_host_irq(IbexSPIHostState *s) if (event_irq) { s->regs[IBEX_SPI_HOST_INTR_STATE] |= R_INTR_STATE_SPI_EVENT_MASK; } - qemu_set_irq(s->event, event_irq); } + + qemu_set_irq(s->event, event_irq); } static void ibex_spi_host_transfer(IbexSPIHostState *s) From c541b07de79daa293e9ccc07f3c98f575ad09f2a Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 2 Nov 2023 10:34:24 +1000 Subject: [PATCH 44/49] target/riscv: cpu: Set the OpenTitan priv to 1.12.0 Set the Ibex CPU priv to 1.12.0 to ensure that smepmp/epmp is correctly enabled. Signed-off-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20231102003424.2003428-3-alistair.francis@wdc.com> Signed-off-by: Alistair Francis --- 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 d73e1da2a2..70c0a78c6c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -606,7 +606,7 @@ static void rv32_ibex_cpu_init(Object *obj) RISCVCPU *cpu = RISCV_CPU(obj); riscv_cpu_set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU); - env->priv_ver = PRIV_VERSION_1_11_0; + env->priv_ver = PRIV_VERSION_1_12_0; #ifndef CONFIG_USER_ONLY set_satp_mode_max_supported(cpu, VM_1_10_MBARE); #endif From 755b41d09f516109f5ddc49aae86358c72e656d5 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 31 Oct 2023 15:37:13 +0000 Subject: [PATCH 45/49] target/riscv: Propagate error from PMU setup More closely follow the QEMU style by returning an Error and propagating it there is an error relating to the PMU setup. Further simplify the function by removing the num_counters parameter as this is available from the passed in cpu pointer. Signed-off-by: Rob Bradford Reviewed-by: Alistair Francis Reviewed-by: LIU Zhiwei Reviewed-by: Atish Patra Message-ID: <20231031154000.18134-2-rbradford@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/pmu.c | 19 +++++++++---------- target/riscv/pmu.h | 3 ++- target/riscv/tcg/tcg-cpu.c | 8 +++++++- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 36f6307d28..13801ccb78 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -434,22 +434,21 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx) } -int riscv_pmu_init(RISCVCPU *cpu, int num_counters) +void riscv_pmu_init(RISCVCPU *cpu, Error **errp) { - if (num_counters > (RV_MAX_MHPMCOUNTERS - 3)) { - return -1; + uint8_t pmu_num = cpu->cfg.pmu_num; + + if (pmu_num > (RV_MAX_MHPMCOUNTERS - 3)) { + error_setg(errp, "Number of counters exceeds maximum available"); + return; } cpu->pmu_event_ctr_map = g_hash_table_new(g_direct_hash, g_direct_equal); if (!cpu->pmu_event_ctr_map) { - /* PMU support can not be enabled */ - qemu_log_mask(LOG_UNIMP, "PMU events can't be supported\n"); - cpu->cfg.pmu_num = 0; - return -1; + error_setg(errp, "Unable to allocate PMU event hash table"); + return; } /* Create a bitmask of available programmable counters */ - cpu->pmu_avail_ctrs = MAKE_32BIT_MASK(3, num_counters); - - return 0; + cpu->pmu_avail_ctrs = MAKE_32BIT_MASK(3, pmu_num); } diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 2bfb71ba87..88e0713296 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -17,13 +17,14 @@ */ #include "cpu.h" +#include "qapi/error.h" bool riscv_pmu_ctr_monitor_instructions(CPURISCVState *env, uint32_t target_ctr); bool riscv_pmu_ctr_monitor_cycles(CPURISCVState *env, uint32_t target_ctr); void riscv_pmu_timer_cb(void *priv); -int riscv_pmu_init(RISCVCPU *cpu, int num_counters); +void riscv_pmu_init(RISCVCPU *cpu, Error **errp); int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx); diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 1a3351b142..144bdac1b2 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -689,7 +689,13 @@ static bool tcg_cpu_realize(CPUState *cs, Error **errp) } if (cpu->cfg.pmu_num) { - if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) { + riscv_pmu_init(cpu, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return false; + } + + if (cpu->cfg.ext_sscofpmf) { cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, riscv_pmu_timer_cb, cpu); } From 7c1bb1d8d412f03ec7d6042971892bd0dff222b7 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 31 Oct 2023 15:37:14 +0000 Subject: [PATCH 46/49] target/riscv: Don't assume PMU counters are continuous Check the PMU available bitmask when checking if a counter is valid rather than comparing the index against the number of PMUs. Signed-off-by: Rob Bradford Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Reviewed-by: Atish Patra Message-ID: <20231031154000.18134-3-rbradford@rivosinc.com> Signed-off-by: Alistair Francis --- 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 fc26b52c88..fde7ce1a53 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -188,7 +188,8 @@ static RISCVException zcmt(CPURISCVState *env, int csrno) #if !defined(CONFIG_USER_ONLY) static RISCVException mctr(CPURISCVState *env, int csrno) { - int pmu_num = riscv_cpu_cfg(env)->pmu_num; + RISCVCPU *cpu = env_archcpu(env); + uint32_t pmu_avail_ctrs = cpu->pmu_avail_ctrs; int ctr_index; int base_csrno = CSR_MHPMCOUNTER3; @@ -197,7 +198,7 @@ static RISCVException mctr(CPURISCVState *env, int csrno) base_csrno += 0x80; } ctr_index = csrno - base_csrno; - if (!pmu_num || ctr_index >= pmu_num) { + if ((BIT(ctr_index) & pmu_avail_ctrs >> 3) == 0) { /* The PMU is not enabled or counter is out of range */ return RISCV_EXCP_ILLEGAL_INST; } From 2571a6427c4ded57e44d4c6cf92376d869a75a5c Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 31 Oct 2023 15:37:15 +0000 Subject: [PATCH 47/49] target/riscv: Use existing PMU counter mask in FDT generation During the FDT generation use the existing mask containing the enabled counters rather then generating a new one. Using the existing mask will support the use of discontinuous counters. Signed-off-by: Rob Bradford Reviewed-by: LIU Zhiwei Reviewed-by: Alistair Francis Reviewed-by: Atish Patra Message-ID: <20231031154000.18134-4-rbradford@rivosinc.com> Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 2 +- target/riscv/pmu.c | 6 +----- target/riscv/pmu.h | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 1732c42915..c7fc97e273 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -722,7 +722,7 @@ static void create_fdt_pmu(RISCVVirtState *s) pmu_name = g_strdup_printf("/pmu"); 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.cfg.pmu_num, pmu_name); + riscv_pmu_generate_fdt_node(ms->fdt, hart.pmu_avail_ctrs, pmu_name); g_free(pmu_name); } diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 13801ccb78..7ddf4977b1 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -34,13 +34,9 @@ * to provide the correct value as well. Heterogeneous PMU per hart is not * supported yet. Thus, number of counters are same across all harts. */ -void riscv_pmu_generate_fdt_node(void *fdt, int num_ctrs, char *pmu_name) +void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name) { uint32_t fdt_event_ctr_map[15] = {}; - uint32_t cmask; - - /* All the programmable counters can map to any event */ - cmask = MAKE_32BIT_MASK(3, num_ctrs); /* * The event encoding is specified in the SBI specification diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 88e0713296..505fc850d3 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -28,6 +28,6 @@ void riscv_pmu_init(RISCVCPU *cpu, Error **errp); int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx); -void riscv_pmu_generate_fdt_node(void *fdt, int num_counters, char *pmu_name); +void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name); int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); From 69b3849bff4bd5ab82241ad09426cd9ff7078449 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 31 Oct 2023 15:37:16 +0000 Subject: [PATCH 48/49] target/riscv: Add "pmu-mask" property to replace "pmu-num" Using a mask instead of the number of PMU devices supports the accurate emulation of platforms that have a discontinuous set of PMU counters. The "pmu-num" property now generates a warning when used by the user on the command line. Rather than storing the value for "pmu-num" convert it directly to the mask if it is specified (overwriting the default "pmu-mask" value) likewise the value is calculated from the mask if the property value is obtained. In the unusual situation that both "pmu-mask" and "pmu-num" are provided then then the order on the command line determines which takes precedence (later overwriting earlier.) Signed-off-by: Rob Bradford Reviewed-by: Alistair Francis Message-ID: <20231031154000.18134-5-rbradford@rivosinc.com> [Changes by AF - Fixup ext_zihpm logic after rebase ] Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 40 +++++++++++++++++++++++++++++++++++++- target/riscv/cpu_cfg.h | 2 +- target/riscv/machine.c | 2 +- target/riscv/pmu.c | 15 +++++++------- target/riscv/tcg/tcg-cpu.c | 4 ++-- 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 70c0a78c6c..02db2760d1 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1427,8 +1427,46 @@ const RISCVCPUMultiExtConfig riscv_cpu_deprecated_exts[] = { DEFINE_PROP_END_OF_LIST(), }; +static void prop_pmu_num_set(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + RISCVCPU *cpu = RISCV_CPU(obj); + uint8_t pmu_num; + + visit_type_uint8(v, name, &pmu_num, errp); + + if (pmu_num > (RV_MAX_MHPMCOUNTERS - 3)) { + error_setg(errp, "Number of counters exceeds maximum available"); + return; + } + + if (pmu_num == 0) { + cpu->cfg.pmu_mask = 0; + } else { + cpu->cfg.pmu_mask = MAKE_64BIT_MASK(3, pmu_num); + } + + warn_report("\"pmu-num\" property is deprecated; use \"pmu-mask\""); +} + +static void prop_pmu_num_get(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + RISCVCPU *cpu = RISCV_CPU(obj); + uint8_t pmu_num = ctpop32(cpu->cfg.pmu_mask); + + visit_type_uint8(v, name, &pmu_num, errp); +} + +const PropertyInfo prop_pmu_num = { + .name = "pmu-num", + .get = prop_pmu_num_get, + .set = prop_pmu_num_set, +}; + Property riscv_cpu_options[] = { - DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), + DEFINE_PROP_UINT32("pmu-mask", RISCVCPU, cfg.pmu_mask, MAKE_64BIT_MASK(3, 16)), + {.name = "pmu-num", .info = &prop_pmu_num}, /* Deprecated */ DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 634ff673b3..f4605fb190 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -134,7 +134,7 @@ struct RISCVCPUConfig { bool ext_xtheadsync; bool ext_XVentanaCondOps; - uint8_t pmu_num; + uint32_t pmu_mask; char *priv_spec; char *user_spec; char *bext_spec; diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 14bb2d7819..fdde243e04 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -316,7 +316,7 @@ static bool pmu_needed(void *opaque) { RISCVCPU *cpu = opaque; - return cpu->cfg.pmu_num; + return (cpu->cfg.pmu_mask > 0); } static const VMStateDescription vmstate_pmu_ctr_state = { diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 7ddf4977b1..0e7d58b8a5 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -18,14 +18,13 @@ #include "qemu/osdep.h" #include "qemu/log.h" +#include "qemu/error-report.h" #include "cpu.h" #include "pmu.h" #include "sysemu/cpu-timers.h" #include "sysemu/device_tree.h" #define RISCV_TIMEBASE_FREQ 1000000000 /* 1Ghz */ -#define MAKE_32BIT_MASK(shift, length) \ - (((uint32_t)(~0UL) >> (32 - (length))) << (shift)) /* * To keep it simple, any event can be mapped to any programmable counters in @@ -184,7 +183,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx) CPURISCVState *env = &cpu->env; gpointer value; - if (!cpu->cfg.pmu_num) { + if (!cpu->cfg.pmu_mask) { return 0; } value = g_hash_table_lookup(cpu->pmu_event_ctr_map, @@ -432,9 +431,12 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx) void riscv_pmu_init(RISCVCPU *cpu, Error **errp) { - uint8_t pmu_num = cpu->cfg.pmu_num; + if (cpu->cfg.pmu_mask & (COUNTEREN_CY | COUNTEREN_TM | COUNTEREN_IR)) { + error_setg(errp, "\"pmu-mask\" contains invalid bits (0-2) set"); + return; + } - if (pmu_num > (RV_MAX_MHPMCOUNTERS - 3)) { + if (ctpop32(cpu->cfg.pmu_mask) > (RV_MAX_MHPMCOUNTERS - 3)) { error_setg(errp, "Number of counters exceeds maximum available"); return; } @@ -445,6 +447,5 @@ void riscv_pmu_init(RISCVCPU *cpu, Error **errp) return; } - /* Create a bitmask of available programmable counters */ - cpu->pmu_avail_ctrs = MAKE_32BIT_MASK(3, pmu_num); + cpu->pmu_avail_ctrs = cpu->cfg.pmu_mask; } diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 144bdac1b2..08adad304d 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -600,7 +600,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) } if (!cpu->cfg.ext_zihpm) { - cpu->cfg.pmu_num = 0; + cpu->cfg.pmu_mask = 0; cpu->pmu_avail_ctrs = 0; } @@ -688,7 +688,7 @@ static bool tcg_cpu_realize(CPUState *cs, Error **errp) riscv_timer_init(cpu); } - if (cpu->cfg.pmu_num) { + if (cpu->cfg.pmu_mask) { riscv_pmu_init(cpu, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); From bc5e8445342fee35b35f2ed9a9f2249e060b8776 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 31 Oct 2023 15:37:17 +0000 Subject: [PATCH 49/49] docs/about/deprecated: Document RISC-V "pmu-num" deprecation This has been replaced by a "pmu-mask" property that provides much more flexibility. Signed-off-by: Rob Bradford Acked-by: LIU Zhiwei Reviewed-by: Alistair Francis Reviewed-by: Atish Patra Message-ID: <20231031154000.18134-6-rbradford@rivosinc.com> Signed-off-by: Alistair Francis --- docs/about/deprecated.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index ecccd5d3fc..78550c07bf 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -413,6 +413,18 @@ Specifying the iSCSI password in plain text on the command line using the used instead, to refer to a ``--object secret...`` instance that provides a password via a file, or encrypted. +CPU device properties +''''''''''''''''''''' + +``pmu-num=n`` on RISC-V CPUs (since 8.2) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In order to support more flexible counter configurations this has been replaced +by a ``pmu-mask`` property. If set of counters is continuous then the mask can +be calculated with ``((2 ^ n) - 1) << 3``. The least significant three bits +must be left clear. + + Backwards compatibility -----------------------