@@ -42,6 +42,12 @@ static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
GUINT_TO_POINTER(ext_offset));
}
+static bool cpu_misa_ext_is_user_set(uint32_t misa_bit)
+{
+ return g_hash_table_contains(misa_ext_user_opts,
+ GUINT_TO_POINTER(misa_bit));
+}
+
static void cpu_cfg_ext_add_user_opt(uint32_t ext_offset, bool value)
{
g_hash_table_insert(multi_ext_user_opts, GUINT_TO_POINTER(ext_offset),
@@ -336,6 +342,46 @@ static void riscv_cpu_validate_named_features(RISCVCPU *cpu)
riscv_cpu_validate_zic64b(cpu);
}
+static void riscv_cpu_validate_g(RISCVCPU *cpu)
+{
+ const char *warn_msg = "RVG mandates disabled extension %s";
+ uint32_t g_misa_bits[] = {RVI, RVM, RVA, RVF, RVD};
+ bool send_warn = cpu_misa_ext_is_user_set(RVG);
+
+ for (int i = 0; i < ARRAY_SIZE(g_misa_bits); i++) {
+ uint32_t bit = g_misa_bits[i];
+
+ if (riscv_has_ext(&cpu->env, bit)) {
+ continue;
+ }
+
+ if (!cpu_misa_ext_is_user_set(bit)) {
+ riscv_cpu_write_misa_bit(cpu, bit, true);
+ continue;
+ }
+
+ if (send_warn) {
+ warn_report(warn_msg, riscv_get_misa_ext_name(bit));
+ }
+ }
+
+ if (!cpu->cfg.ext_zicsr) {
+ if (!cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zicsr))) {
+ cpu->cfg.ext_zicsr = true;
+ } else if (send_warn) {
+ warn_report(warn_msg, "zicsr");
+ }
+ }
+
+ if (!cpu->cfg.ext_zifencei) {
+ if (!cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zifencei))) {
+ cpu->cfg.ext_zifencei = true;
+ } else if (send_warn) {
+ warn_report(warn_msg, "zifencei");
+ }
+ }
+}
+
/*
* Check consistency between chosen extensions while setting
* cpu->cfg accordingly.
@@ -345,31 +391,8 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
CPURISCVState *env = &cpu->env;
Error *local_err = NULL;
- /* Do some ISA extension error checking */
- if (riscv_has_ext(env, RVG) &&
- !(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_zicsr && cpu->cfg.ext_zifencei)) {
-
- 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;
- }
-
- 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_zicsr), 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;
+ if (riscv_has_ext(env, RVG)) {
+ riscv_cpu_validate_g(cpu);
}
if (riscv_has_ext(env, RVI) && riscv_has_ext(env, RVE)) {