diff options
-rw-r--r-- | target/riscv/cpu.c | 70 | ||||
-rw-r--r-- | target/riscv/cpu.h | 11 |
2 files changed, 79 insertions, 2 deletions
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6f2b644..0632ac0 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -24,6 +24,7 @@ #include "cpu.h" #include "exec/exec-all.h" #include "qapi/error.h" +#include "qemu/error-report.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" @@ -119,7 +120,8 @@ static void riscv_any_cpu_init(Object *obj) static void riscv_base32_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); + /* We set this in the realise function */ + set_misa(env, 0); } static void rv32gcsu_priv1_09_1_cpu_init(Object *obj) @@ -156,7 +158,8 @@ static void rv32imacu_nommu_cpu_init(Object *obj) static void riscv_base64_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; - set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); + /* We set this in the realise function */ + set_misa(env, 0); } static void rv64gcsu_priv1_09_1_cpu_init(Object *obj) @@ -315,6 +318,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); int priv_version = PRIV_VERSION_1_10_0; int user_version = USER_VERSION_2_02_0; + target_ulong target_misa = 0; Error *local_err = NULL; cpu_exec_realizefn(cs, &local_err); @@ -358,6 +362,58 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) set_feature(env, RISCV_FEATURE_PMP); } + /* If misa isn't set (rv32 and rv64 machines) set it here */ + if (!env->misa) { + /* Do some ISA extension error checking */ + if (cpu->cfg.ext_i && cpu->cfg.ext_e) { + error_setg(errp, + "I and E extensions are incompatible"); + return; + } + + if (cpu->cfg.ext_g && !(cpu->cfg.ext_i & cpu->cfg.ext_m & + cpu->cfg.ext_a & cpu->cfg.ext_f & + cpu->cfg.ext_d)) { + warn_report("Setting G will also set IMAFD"); + cpu->cfg.ext_i = true; + cpu->cfg.ext_m = true; + cpu->cfg.ext_a = true; + cpu->cfg.ext_f = true; + cpu->cfg.ext_d = true; + } + + /* Set the ISA extensions, checks should have happened above */ + if (cpu->cfg.ext_i) { + target_misa |= RVI; + } + if (cpu->cfg.ext_e) { + target_misa |= RVE; + } + if (cpu->cfg.ext_m) { + target_misa |= RVM; + } + if (cpu->cfg.ext_a) { + target_misa |= RVA; + } + if (cpu->cfg.ext_f) { + target_misa |= RVF; + } + if (cpu->cfg.ext_d) { + target_misa |= RVD; + } + if (cpu->cfg.ext_c) { + target_misa |= RVC; + } + if (cpu->cfg.ext_s) { + target_misa |= RVS; + } + if (cpu->cfg.ext_u) { + target_misa |= RVU; + } + + set_misa(env, RVXLEN | target_misa); + } + riscv_cpu_register_gdb_regs_for_features(cs); qemu_init_vcpu(cs); @@ -379,6 +435,16 @@ static const VMStateDescription vmstate_riscv_cpu = { }; static Property riscv_cpu_properties[] = { + DEFINE_PROP_BOOL("i", RISCVCPU, cfg.ext_i, true), + DEFINE_PROP_BOOL("e", RISCVCPU, cfg.ext_e, false), + DEFINE_PROP_BOOL("g", RISCVCPU, cfg.ext_g, true), + DEFINE_PROP_BOOL("m", RISCVCPU, cfg.ext_m, true), + DEFINE_PROP_BOOL("a", RISCVCPU, cfg.ext_a, true), + DEFINE_PROP_BOOL("f", RISCVCPU, cfg.ext_f, true), + DEFINE_PROP_BOOL("d", RISCVCPU, cfg.ext_d, true), + DEFINE_PROP_BOOL("c", RISCVCPU, cfg.ext_c, true), + DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true), + DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true), DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), DEFINE_PROP_STRING("user_spec", RISCVCPU, cfg.user_spec), DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6c5de37..b47cde5 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -211,6 +211,17 @@ typedef struct RISCVCPU { /* Configuration Settings */ struct { + bool ext_i; + bool ext_e; + bool ext_g; + bool ext_m; + bool ext_a; + bool ext_f; + bool ext_d; + bool ext_c; + bool ext_s; + bool ext_u; + char *priv_spec; char *user_spec; bool mmu; |