From 997e71952d1eb8d60b0807d01cf3956d84728067 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 12 Sep 2023 10:24:18 -0300 Subject: [PATCH] target/riscv/cpu.c: introduce cpu_cfg_ext_auto_update() During realize() time we're activating a lot of extensions based on some criteria, e.g.: if (cpu->cfg.ext_zk) { cpu->cfg.ext_zkn = true; cpu->cfg.ext_zkr = true; cpu->cfg.ext_zkt = true; } This practice resulted in at least one case where we ended up enabling something we shouldn't: RVC enabling zca/zcd/zcf when using a CPU that has priv_spec older than 1.12.0. We're also not considering user choice. There's no way of doing it now but this is about to change in the next few patches. cpu_cfg_ext_auto_update() will check for priv version mismatches before enabling extensions. If we have a mismatch between the current priv version and the extension we want to enable, do not enable it. In the near future, this same function will also consider user choice when deciding if we're going to enable/disable an extension or not. For now let's use it to handle zca/zcd/zcf enablement if RVC is enabled. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-ID: <20230912132423.268494-16-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 43 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 7544fff392..bd73b61d3c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -177,6 +177,43 @@ static void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, *ext_enabled = en; } +static int cpu_cfg_ext_get_min_version(uint32_t ext_offset) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) { + if (isa_edata_arr[i].ext_enable_offset != ext_offset) { + continue; + } + + return isa_edata_arr[i].min_version; + } + + g_assert_not_reached(); +} + +static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset, + bool value) +{ + CPURISCVState *env = &cpu->env; + bool prev_val = isa_ext_is_enabled(cpu, ext_offset); + int min_version; + + if (prev_val == value) { + return; + } + + if (value && env->priv_ver != PRIV_VERSION_LATEST) { + /* Do not enable it if priv_ver is older than min_version */ + min_version = cpu_cfg_ext_get_min_version(ext_offset); + if (env->priv_ver < min_version) { + return; + } + } + + isa_ext_update_enabled(cpu, ext_offset, value); +} + const char * const riscv_int_regnames[] = { "x0/zero", "x1/ra", "x2/sp", "x3/gp", "x4/tp", "x5/t0", "x6/t1", "x7/t2", "x8/s0", "x9/s1", "x10/a0", "x11/a1", "x12/a2", "x13/a3", @@ -1268,12 +1305,12 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) /* zca, zcd and zcf has a PRIV 1.12.0 restriction */ if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) { - cpu->cfg.ext_zca = true; + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true); if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) { - cpu->cfg.ext_zcf = true; + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true); } if (riscv_has_ext(env, RVD)) { - cpu->cfg.ext_zcd = true; + cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcd), true); } }