|
@@ -119,6 +119,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
|
|
ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
|
|
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(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
|
|
ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
|
|
ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
|
|
|
|
+ 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(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
|
|
ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf),
|
|
ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf),
|
|
ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc),
|
|
ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc),
|
|
@@ -247,16 +248,6 @@ static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
|
|
env->misa_ext_mask = env->misa_ext = ext;
|
|
env->misa_ext_mask = env->misa_ext = ext;
|
|
}
|
|
}
|
|
|
|
|
|
-static void set_priv_version(CPURISCVState *env, int priv_ver)
|
|
|
|
-{
|
|
|
|
- env->priv_ver = priv_ver;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void set_vext_version(CPURISCVState *env, int vext_ver)
|
|
|
|
-{
|
|
|
|
- env->vext_ver = vext_ver;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
static uint8_t satp_mode_from_str(const char *satp_mode_str)
|
|
static uint8_t satp_mode_from_str(const char *satp_mode_str)
|
|
{
|
|
{
|
|
@@ -342,7 +333,8 @@ static void set_satp_mode_default_map(RISCVCPU *cpu)
|
|
|
|
|
|
static void riscv_any_cpu_init(Object *obj)
|
|
static void riscv_any_cpu_init(Object *obj)
|
|
{
|
|
{
|
|
- CPURISCVState *env = &RISCV_CPU(obj)->env;
|
|
|
|
|
|
+ RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
+ CPURISCVState *env = &cpu->env;
|
|
#if defined(TARGET_RISCV32)
|
|
#if defined(TARGET_RISCV32)
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
|
|
#elif defined(TARGET_RISCV64)
|
|
#elif defined(TARGET_RISCV64)
|
|
@@ -355,7 +347,13 @@ static void riscv_any_cpu_init(Object *obj)
|
|
VM_1_10_SV32 : VM_1_10_SV57);
|
|
VM_1_10_SV32 : VM_1_10_SV57);
|
|
#endif
|
|
#endif
|
|
|
|
|
|
- set_priv_version(env, PRIV_VERSION_1_12_0);
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_LATEST;
|
|
|
|
+
|
|
|
|
+ /* inherited from parent obj via riscv_cpu_init() */
|
|
|
|
+ cpu->cfg.ext_ifencei = true;
|
|
|
|
+ cpu->cfg.ext_icsr = true;
|
|
|
|
+ cpu->cfg.mmu = true;
|
|
|
|
+ cpu->cfg.pmp = true;
|
|
}
|
|
}
|
|
|
|
|
|
#if defined(TARGET_RISCV64)
|
|
#if defined(TARGET_RISCV64)
|
|
@@ -366,7 +364,7 @@ static void rv64_base_cpu_init(Object *obj)
|
|
set_misa(env, MXL_RV64, 0);
|
|
set_misa(env, MXL_RV64, 0);
|
|
riscv_cpu_add_user_properties(obj);
|
|
riscv_cpu_add_user_properties(obj);
|
|
/* Set latest version of privileged specification */
|
|
/* Set latest version of privileged specification */
|
|
- set_priv_version(env, PRIV_VERSION_1_12_0);
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_LATEST;
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
|
|
#endif
|
|
#endif
|
|
@@ -374,12 +372,19 @@ static void rv64_base_cpu_init(Object *obj)
|
|
|
|
|
|
static void rv64_sifive_u_cpu_init(Object *obj)
|
|
static void rv64_sifive_u_cpu_init(Object *obj)
|
|
{
|
|
{
|
|
- CPURISCVState *env = &RISCV_CPU(obj)->env;
|
|
|
|
|
|
+ RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
+ CPURISCVState *env = &cpu->env;
|
|
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
|
|
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
|
|
- set_priv_version(env, PRIV_VERSION_1_10_0);
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_1_10_0;
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39);
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39);
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
|
|
+ /* inherited from parent obj via riscv_cpu_init() */
|
|
|
|
+ cpu->cfg.ext_ifencei = true;
|
|
|
|
+ cpu->cfg.ext_icsr = true;
|
|
|
|
+ cpu->cfg.mmu = true;
|
|
|
|
+ cpu->cfg.pmp = true;
|
|
}
|
|
}
|
|
|
|
|
|
static void rv64_sifive_e_cpu_init(Object *obj)
|
|
static void rv64_sifive_e_cpu_init(Object *obj)
|
|
@@ -388,11 +393,15 @@ static void rv64_sifive_e_cpu_init(Object *obj)
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
|
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
|
|
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
|
|
- set_priv_version(env, PRIV_VERSION_1_10_0);
|
|
|
|
- cpu->cfg.mmu = false;
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_1_10_0;
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
|
|
+ /* inherited from parent obj via riscv_cpu_init() */
|
|
|
|
+ cpu->cfg.ext_ifencei = true;
|
|
|
|
+ cpu->cfg.ext_icsr = true;
|
|
|
|
+ cpu->cfg.pmp = true;
|
|
}
|
|
}
|
|
|
|
|
|
static void rv64_thead_c906_cpu_init(Object *obj)
|
|
static void rv64_thead_c906_cpu_init(Object *obj)
|
|
@@ -401,7 +410,7 @@ static void rv64_thead_c906_cpu_init(Object *obj)
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
|
set_misa(env, MXL_RV64, RVG | RVC | RVS | RVU);
|
|
set_misa(env, MXL_RV64, RVG | RVC | RVS | RVU);
|
|
- set_priv_version(env, PRIV_VERSION_1_11_0);
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_1_11_0;
|
|
|
|
|
|
cpu->cfg.ext_zfh = true;
|
|
cpu->cfg.ext_zfh = true;
|
|
cpu->cfg.mmu = true;
|
|
cpu->cfg.mmu = true;
|
|
@@ -420,6 +429,9 @@ static void rv64_thead_c906_cpu_init(Object *obj)
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
set_satp_mode_max_supported(cpu, VM_1_10_SV39);
|
|
set_satp_mode_max_supported(cpu, VM_1_10_SV39);
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
|
|
+ /* inherited from parent obj via riscv_cpu_init() */
|
|
|
|
+ cpu->cfg.pmp = true;
|
|
}
|
|
}
|
|
|
|
|
|
static void rv64_veyron_v1_cpu_init(Object *obj)
|
|
static void rv64_veyron_v1_cpu_init(Object *obj)
|
|
@@ -472,7 +484,7 @@ static void rv128_base_cpu_init(Object *obj)
|
|
set_misa(env, MXL_RV128, 0);
|
|
set_misa(env, MXL_RV128, 0);
|
|
riscv_cpu_add_user_properties(obj);
|
|
riscv_cpu_add_user_properties(obj);
|
|
/* Set latest version of privileged specification */
|
|
/* Set latest version of privileged specification */
|
|
- set_priv_version(env, PRIV_VERSION_1_12_0);
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_LATEST;
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
|
|
#endif
|
|
#endif
|
|
@@ -485,7 +497,7 @@ static void rv32_base_cpu_init(Object *obj)
|
|
set_misa(env, MXL_RV32, 0);
|
|
set_misa(env, MXL_RV32, 0);
|
|
riscv_cpu_add_user_properties(obj);
|
|
riscv_cpu_add_user_properties(obj);
|
|
/* Set latest version of privileged specification */
|
|
/* Set latest version of privileged specification */
|
|
- set_priv_version(env, PRIV_VERSION_1_12_0);
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_LATEST;
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
|
|
#endif
|
|
#endif
|
|
@@ -493,12 +505,19 @@ static void rv32_base_cpu_init(Object *obj)
|
|
|
|
|
|
static void rv32_sifive_u_cpu_init(Object *obj)
|
|
static void rv32_sifive_u_cpu_init(Object *obj)
|
|
{
|
|
{
|
|
- CPURISCVState *env = &RISCV_CPU(obj)->env;
|
|
|
|
|
|
+ RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
+ CPURISCVState *env = &cpu->env;
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
|
|
- set_priv_version(env, PRIV_VERSION_1_10_0);
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_1_10_0;
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
|
|
+ /* inherited from parent obj via riscv_cpu_init() */
|
|
|
|
+ cpu->cfg.ext_ifencei = true;
|
|
|
|
+ cpu->cfg.ext_icsr = true;
|
|
|
|
+ cpu->cfg.mmu = true;
|
|
|
|
+ cpu->cfg.pmp = true;
|
|
}
|
|
}
|
|
|
|
|
|
static void rv32_sifive_e_cpu_init(Object *obj)
|
|
static void rv32_sifive_e_cpu_init(Object *obj)
|
|
@@ -507,11 +526,15 @@ static void rv32_sifive_e_cpu_init(Object *obj)
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
|
|
- set_priv_version(env, PRIV_VERSION_1_10_0);
|
|
|
|
- cpu->cfg.mmu = false;
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_1_10_0;
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
|
|
+ /* inherited from parent obj via riscv_cpu_init() */
|
|
|
|
+ cpu->cfg.ext_ifencei = true;
|
|
|
|
+ cpu->cfg.ext_icsr = true;
|
|
|
|
+ cpu->cfg.pmp = true;
|
|
}
|
|
}
|
|
|
|
|
|
static void rv32_ibex_cpu_init(Object *obj)
|
|
static void rv32_ibex_cpu_init(Object *obj)
|
|
@@ -520,12 +543,16 @@ static void rv32_ibex_cpu_init(Object *obj)
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
|
|
- set_priv_version(env, PRIV_VERSION_1_11_0);
|
|
|
|
- cpu->cfg.mmu = false;
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_1_11_0;
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
#endif
|
|
#endif
|
|
cpu->cfg.epmp = true;
|
|
cpu->cfg.epmp = true;
|
|
|
|
+
|
|
|
|
+ /* inherited from parent obj via riscv_cpu_init() */
|
|
|
|
+ cpu->cfg.ext_ifencei = true;
|
|
|
|
+ cpu->cfg.ext_icsr = true;
|
|
|
|
+ cpu->cfg.pmp = true;
|
|
}
|
|
}
|
|
|
|
|
|
static void rv32_imafcu_nommu_cpu_init(Object *obj)
|
|
static void rv32_imafcu_nommu_cpu_init(Object *obj)
|
|
@@ -534,11 +561,15 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
|
|
- set_priv_version(env, PRIV_VERSION_1_10_0);
|
|
|
|
- cpu->cfg.mmu = false;
|
|
|
|
|
|
+ env->priv_ver = PRIV_VERSION_1_10_0;
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
|
|
+ /* inherited from parent obj via riscv_cpu_init() */
|
|
|
|
+ cpu->cfg.ext_ifencei = true;
|
|
|
|
+ cpu->cfg.ext_icsr = true;
|
|
|
|
+ cpu->cfg.pmp = true;
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
@@ -690,16 +721,18 @@ static vaddr riscv_cpu_get_pc(CPUState *cs)
|
|
static void riscv_cpu_synchronize_from_tb(CPUState *cs,
|
|
static void riscv_cpu_synchronize_from_tb(CPUState *cs,
|
|
const TranslationBlock *tb)
|
|
const TranslationBlock *tb)
|
|
{
|
|
{
|
|
- RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
- CPURISCVState *env = &cpu->env;
|
|
|
|
- RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
|
|
|
|
|
|
+ if (!(tb_cflags(tb) & CF_PCREL)) {
|
|
|
|
+ RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
+ CPURISCVState *env = &cpu->env;
|
|
|
|
+ RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
|
|
|
|
|
|
- tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
|
|
|
|
|
|
+ tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
|
|
|
|
|
|
- if (xl == MXL_RV32) {
|
|
|
|
- env->pc = (int32_t) tb->pc;
|
|
|
|
- } else {
|
|
|
|
- env->pc = tb->pc;
|
|
|
|
|
|
+ if (xl == MXL_RV32) {
|
|
|
|
+ env->pc = (int32_t) tb->pc;
|
|
|
|
+ } else {
|
|
|
|
+ env->pc = tb->pc;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -725,11 +758,18 @@ static void riscv_restore_state_to_opc(CPUState *cs,
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
CPURISCVState *env = &cpu->env;
|
|
CPURISCVState *env = &cpu->env;
|
|
RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
|
|
RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
|
|
|
|
+ target_ulong pc;
|
|
|
|
+
|
|
|
|
+ if (tb_cflags(tb) & CF_PCREL) {
|
|
|
|
+ pc = (env->pc & TARGET_PAGE_MASK) | data[0];
|
|
|
|
+ } else {
|
|
|
|
+ pc = data[0];
|
|
|
|
+ }
|
|
|
|
|
|
if (xl == MXL_RV32) {
|
|
if (xl == MXL_RV32) {
|
|
- env->pc = (int32_t)data[0];
|
|
|
|
|
|
+ env->pc = (int32_t)pc;
|
|
} else {
|
|
} else {
|
|
- env->pc = data[0];
|
|
|
|
|
|
+ env->pc = pc;
|
|
}
|
|
}
|
|
env->bins = data[1];
|
|
env->bins = data[1];
|
|
}
|
|
}
|
|
@@ -818,6 +858,7 @@ static void riscv_cpu_reset_hold(Object *obj)
|
|
static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
|
|
static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
|
|
{
|
|
{
|
|
RISCVCPU *cpu = RISCV_CPU(s);
|
|
RISCVCPU *cpu = RISCV_CPU(s);
|
|
|
|
+ info->target_info = &cpu->cfg;
|
|
|
|
|
|
switch (riscv_cpu_mxl(&cpu->env)) {
|
|
switch (riscv_cpu_mxl(&cpu->env)) {
|
|
case MXL_RV32:
|
|
case MXL_RV32:
|
|
@@ -834,13 +875,127 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg,
|
|
|
|
+ Error **errp)
|
|
|
|
+{
|
|
|
|
+ int vext_version = VEXT_VERSION_1_00_0;
|
|
|
|
+
|
|
|
|
+ if (!is_power_of_2(cfg->vlen)) {
|
|
|
|
+ error_setg(errp, "Vector extension VLEN must be power of 2");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (cfg->vlen > RV_VLEN_MAX || cfg->vlen < 128) {
|
|
|
|
+ error_setg(errp,
|
|
|
|
+ "Vector extension implementation only supports VLEN "
|
|
|
|
+ "in the range [128, %d]", RV_VLEN_MAX);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (!is_power_of_2(cfg->elen)) {
|
|
|
|
+ error_setg(errp, "Vector extension ELEN must be power of 2");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (cfg->elen > 64 || cfg->elen < 8) {
|
|
|
|
+ error_setg(errp,
|
|
|
|
+ "Vector extension implementation only supports ELEN "
|
|
|
|
+ "in the range [8, 64]");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (cfg->vext_spec) {
|
|
|
|
+ if (!g_strcmp0(cfg->vext_spec, "v1.0")) {
|
|
|
|
+ vext_version = VEXT_VERSION_1_00_0;
|
|
|
|
+ } else {
|
|
|
|
+ error_setg(errp, "Unsupported vector spec version '%s'",
|
|
|
|
+ cfg->vext_spec);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ qemu_log("vector version is not specified, "
|
|
|
|
+ "use the default value v1.0\n");
|
|
|
|
+ }
|
|
|
|
+ env->vext_ver = vext_version;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp)
|
|
|
|
+{
|
|
|
|
+ CPURISCVState *env = &cpu->env;
|
|
|
|
+ int priv_version = -1;
|
|
|
|
+
|
|
|
|
+ if (cpu->cfg.priv_spec) {
|
|
|
|
+ if (!g_strcmp0(cpu->cfg.priv_spec, "v1.12.0")) {
|
|
|
|
+ priv_version = PRIV_VERSION_1_12_0;
|
|
|
|
+ } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) {
|
|
|
|
+ priv_version = PRIV_VERSION_1_11_0;
|
|
|
|
+ } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
|
|
|
|
+ priv_version = PRIV_VERSION_1_10_0;
|
|
|
|
+ } else {
|
|
|
|
+ error_setg(errp,
|
|
|
|
+ "Unsupported privilege spec version '%s'",
|
|
|
|
+ cpu->cfg.priv_spec);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ env->priv_ver = priv_version;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu)
|
|
|
|
+{
|
|
|
|
+ CPURISCVState *env = &cpu->env;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ /* Force disable extensions if priv spec version does not match */
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
|
|
|
|
+ if (isa_ext_is_enabled(cpu, &isa_edata_arr[i]) &&
|
|
|
|
+ (env->priv_ver < isa_edata_arr[i].min_version)) {
|
|
|
|
+ isa_ext_update_enabled(cpu, &isa_edata_arr[i], false);
|
|
|
|
+#ifndef CONFIG_USER_ONLY
|
|
|
|
+ warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
|
|
|
|
+ " because privilege spec version does not match",
|
|
|
|
+ isa_edata_arr[i].name, env->mhartid);
|
|
|
|
+#else
|
|
|
|
+ warn_report("disabling %s extension because "
|
|
|
|
+ "privilege spec version does not match",
|
|
|
|
+ isa_edata_arr[i].name);
|
|
|
|
+#endif
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp)
|
|
|
|
+{
|
|
|
|
+ RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
|
|
|
|
+ CPUClass *cc = CPU_CLASS(mcc);
|
|
|
|
+ CPURISCVState *env = &cpu->env;
|
|
|
|
+
|
|
|
|
+ /* Validate that MISA_MXL is set properly. */
|
|
|
|
+ switch (env->misa_mxl_max) {
|
|
|
|
+#ifdef TARGET_RISCV64
|
|
|
|
+ case MXL_RV64:
|
|
|
|
+ case MXL_RV128:
|
|
|
|
+ cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
|
|
|
|
+ break;
|
|
|
|
+#endif
|
|
|
|
+ case MXL_RV32:
|
|
|
|
+ cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ g_assert_not_reached();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (env->misa_mxl_max != env->misa_mxl) {
|
|
|
|
+ error_setg(errp, "misa_mxl_max must be equal to misa_mxl");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Check consistency between chosen extensions while setting
|
|
* Check consistency between chosen extensions while setting
|
|
* cpu->cfg accordingly.
|
|
* cpu->cfg accordingly.
|
|
*/
|
|
*/
|
|
-static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
|
|
|
|
+void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
{
|
|
{
|
|
CPURISCVState *env = &cpu->env;
|
|
CPURISCVState *env = &cpu->env;
|
|
|
|
+ Error *local_err = NULL;
|
|
|
|
|
|
/* Do some ISA extension error checking */
|
|
/* Do some ISA extension error checking */
|
|
if (riscv_has_ext(env, RVG) &&
|
|
if (riscv_has_ext(env, RVG) &&
|
|
@@ -853,7 +1008,7 @@ static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
cpu->cfg.ext_ifencei = true;
|
|
cpu->cfg.ext_ifencei = true;
|
|
|
|
|
|
env->misa_ext |= RVI | RVM | RVA | RVF | RVD;
|
|
env->misa_ext |= RVI | RVM | RVA | RVF | RVD;
|
|
- env->misa_ext_mask = env->misa_ext;
|
|
|
|
|
|
+ env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD;
|
|
}
|
|
}
|
|
|
|
|
|
if (riscv_has_ext(env, RVI) && riscv_has_ext(env, RVE)) {
|
|
if (riscv_has_ext(env, RVI) && riscv_has_ext(env, RVE)) {
|
|
@@ -909,8 +1064,14 @@ static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- /* The V vector extension depends on the Zve64d extension */
|
|
|
|
if (riscv_has_ext(env, RVV)) {
|
|
if (riscv_has_ext(env, RVV)) {
|
|
|
|
+ riscv_cpu_validate_v(env, &cpu->cfg, &local_err);
|
|
|
|
+ if (local_err != NULL) {
|
|
|
|
+ error_propagate(errp, local_err);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* The V vector extension depends on the Zve64d extension */
|
|
cpu->cfg.ext_zve64d = true;
|
|
cpu->cfg.ext_zve64d = true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1046,45 +1207,11 @@ static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
cpu->cfg.ext_zksh = true;
|
|
cpu->cfg.ext_zksh = true;
|
|
}
|
|
}
|
|
|
|
|
|
- if (riscv_has_ext(env, RVV)) {
|
|
|
|
- int vext_version = VEXT_VERSION_1_00_0;
|
|
|
|
- if (!is_power_of_2(cpu->cfg.vlen)) {
|
|
|
|
- error_setg(errp,
|
|
|
|
- "Vector extension VLEN must be power of 2");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- if (cpu->cfg.vlen > RV_VLEN_MAX || cpu->cfg.vlen < 128) {
|
|
|
|
- error_setg(errp,
|
|
|
|
- "Vector extension implementation only supports VLEN "
|
|
|
|
- "in the range [128, %d]", RV_VLEN_MAX);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- if (!is_power_of_2(cpu->cfg.elen)) {
|
|
|
|
- error_setg(errp,
|
|
|
|
- "Vector extension ELEN must be power of 2");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- if (cpu->cfg.elen > 64 || cpu->cfg.elen < 8) {
|
|
|
|
- error_setg(errp,
|
|
|
|
- "Vector extension implementation only supports ELEN "
|
|
|
|
- "in the range [8, 64]");
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- if (cpu->cfg.vext_spec) {
|
|
|
|
- if (!g_strcmp0(cpu->cfg.vext_spec, "v1.0")) {
|
|
|
|
- vext_version = VEXT_VERSION_1_00_0;
|
|
|
|
- } else {
|
|
|
|
- error_setg(errp,
|
|
|
|
- "Unsupported vector spec version '%s'",
|
|
|
|
- cpu->cfg.vext_spec);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- qemu_log("vector version is not specified, "
|
|
|
|
- "use the default value v1.0\n");
|
|
|
|
- }
|
|
|
|
- set_vext_version(env, vext_version);
|
|
|
|
- }
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Disable isa extensions based on priv spec after we
|
|
|
|
+ * validated and set everything we need.
|
|
|
|
+ */
|
|
|
|
+ riscv_cpu_disable_priv_spec_isa_exts(cpu);
|
|
}
|
|
}
|
|
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
@@ -1183,8 +1310,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
|
RISCVCPU *cpu = RISCV_CPU(dev);
|
|
RISCVCPU *cpu = RISCV_CPU(dev);
|
|
CPURISCVState *env = &cpu->env;
|
|
CPURISCVState *env = &cpu->env;
|
|
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
|
|
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
|
|
- CPUClass *cc = CPU_CLASS(mcc);
|
|
|
|
- int i, priv_version = -1;
|
|
|
|
Error *local_err = NULL;
|
|
Error *local_err = NULL;
|
|
|
|
|
|
cpu_exec_realizefn(cs, &local_err);
|
|
cpu_exec_realizefn(cs, &local_err);
|
|
@@ -1193,23 +1318,16 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- if (cpu->cfg.priv_spec) {
|
|
|
|
- if (!g_strcmp0(cpu->cfg.priv_spec, "v1.12.0")) {
|
|
|
|
- priv_version = PRIV_VERSION_1_12_0;
|
|
|
|
- } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) {
|
|
|
|
- priv_version = PRIV_VERSION_1_11_0;
|
|
|
|
- } else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
|
|
|
|
- priv_version = PRIV_VERSION_1_10_0;
|
|
|
|
- } else {
|
|
|
|
- error_setg(errp,
|
|
|
|
- "Unsupported privilege spec version '%s'",
|
|
|
|
- cpu->cfg.priv_spec);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ riscv_cpu_validate_misa_mxl(cpu, &local_err);
|
|
|
|
+ if (local_err != NULL) {
|
|
|
|
+ error_propagate(errp, local_err);
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
|
|
|
|
- if (priv_version >= PRIV_VERSION_1_10_0) {
|
|
|
|
- set_priv_version(env, priv_version);
|
|
|
|
|
|
+ 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);
|
|
riscv_cpu_validate_misa_priv(env, &local_err);
|
|
@@ -1218,23 +1336,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- /* Force disable extensions if priv spec version does not match */
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
|
|
|
|
- if (isa_ext_is_enabled(cpu, &isa_edata_arr[i]) &&
|
|
|
|
- (env->priv_ver < isa_edata_arr[i].min_version)) {
|
|
|
|
- isa_ext_update_enabled(cpu, &isa_edata_arr[i], false);
|
|
|
|
-#ifndef CONFIG_USER_ONLY
|
|
|
|
- warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
|
|
|
|
- " because privilege spec version does not match",
|
|
|
|
- isa_edata_arr[i].name, env->mhartid);
|
|
|
|
-#else
|
|
|
|
- warn_report("disabling %s extension because "
|
|
|
|
- "privilege spec version does not match",
|
|
|
|
- isa_edata_arr[i].name);
|
|
|
|
-#endif
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if (cpu->cfg.epmp && !cpu->cfg.pmp) {
|
|
if (cpu->cfg.epmp && !cpu->cfg.pmp) {
|
|
/*
|
|
/*
|
|
* Enhanced PMP should only be available
|
|
* Enhanced PMP should only be available
|
|
@@ -1244,29 +1345,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
-#ifndef CONFIG_USER_ONLY
|
|
|
|
- if (cpu->cfg.ext_sstc) {
|
|
|
|
- riscv_timer_init(cpu);
|
|
|
|
- }
|
|
|
|
-#endif /* CONFIG_USER_ONLY */
|
|
|
|
-
|
|
|
|
- /* Validate that MISA_MXL is set properly. */
|
|
|
|
- switch (env->misa_mxl_max) {
|
|
|
|
-#ifdef TARGET_RISCV64
|
|
|
|
- case MXL_RV64:
|
|
|
|
- case MXL_RV128:
|
|
|
|
- cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
|
|
|
|
- break;
|
|
|
|
-#endif
|
|
|
|
- case MXL_RV32:
|
|
|
|
- cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- g_assert_not_reached();
|
|
|
|
- }
|
|
|
|
- assert(env->misa_mxl_max == env->misa_mxl);
|
|
|
|
-
|
|
|
|
riscv_cpu_validate_set_extensions(cpu, &local_err);
|
|
riscv_cpu_validate_set_extensions(cpu, &local_err);
|
|
if (local_err != NULL) {
|
|
if (local_err != NULL) {
|
|
error_propagate(errp, local_err);
|
|
error_propagate(errp, local_err);
|
|
@@ -1274,6 +1352,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
|
}
|
|
}
|
|
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
+ cs->tcg_cflags |= CF_PCREL;
|
|
|
|
+
|
|
|
|
+ if (cpu->cfg.ext_sstc) {
|
|
|
|
+ riscv_timer_init(cpu);
|
|
|
|
+ }
|
|
|
|
+
|
|
if (cpu->cfg.pmu_num) {
|
|
if (cpu->cfg.pmu_num) {
|
|
if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) {
|
|
if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) {
|
|
cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
|
cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
|
@@ -1410,11 +1494,6 @@ static void riscv_cpu_init(Object *obj)
|
|
{
|
|
{
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
|
- cpu->cfg.ext_ifencei = true;
|
|
|
|
- cpu->cfg.ext_icsr = true;
|
|
|
|
- cpu->cfg.mmu = true;
|
|
|
|
- cpu->cfg.pmp = true;
|
|
|
|
-
|
|
|
|
cpu_set_cpustate_pointers(cpu);
|
|
cpu_set_cpustate_pointers(cpu);
|
|
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
#ifndef CONFIG_USER_ONLY
|
|
@@ -1535,8 +1614,8 @@ static Property riscv_cpu_extensions[] = {
|
|
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
|
|
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
|
|
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
|
|
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
|
|
|
|
|
|
|
|
+ DEFINE_PROP_BOOL("smstateen", RISCVCPU, cfg.ext_smstateen, false),
|
|
DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true),
|
|
DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true),
|
|
-
|
|
|
|
DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
|
|
DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
|
|
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
|
|
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
|
|
DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
|
|
DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
|
|
@@ -1571,6 +1650,14 @@ static Property riscv_cpu_extensions[] = {
|
|
|
|
|
|
DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false),
|
|
DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false),
|
|
|
|
|
|
|
|
+ DEFINE_PROP_BOOL("zca", RISCVCPU, cfg.ext_zca, false),
|
|
|
|
+ DEFINE_PROP_BOOL("zcb", RISCVCPU, cfg.ext_zcb, false),
|
|
|
|
+ DEFINE_PROP_BOOL("zcd", RISCVCPU, cfg.ext_zcd, false),
|
|
|
|
+ DEFINE_PROP_BOOL("zce", RISCVCPU, cfg.ext_zce, false),
|
|
|
|
+ DEFINE_PROP_BOOL("zcf", RISCVCPU, cfg.ext_zcf, false),
|
|
|
|
+ DEFINE_PROP_BOOL("zcmp", RISCVCPU, cfg.ext_zcmp, false),
|
|
|
|
+ DEFINE_PROP_BOOL("zcmt", RISCVCPU, cfg.ext_zcmt, false),
|
|
|
|
+
|
|
/* Vendor-specific custom extensions */
|
|
/* Vendor-specific custom extensions */
|
|
DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false),
|
|
DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false),
|
|
DEFINE_PROP_BOOL("xtheadbb", RISCVCPU, cfg.ext_xtheadbb, false),
|
|
DEFINE_PROP_BOOL("xtheadbb", RISCVCPU, cfg.ext_xtheadbb, false),
|
|
@@ -1588,14 +1675,6 @@ static Property riscv_cpu_extensions[] = {
|
|
/* These are experimental so mark with 'x-' */
|
|
/* These are experimental so mark with 'x-' */
|
|
DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false),
|
|
DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false),
|
|
|
|
|
|
- DEFINE_PROP_BOOL("x-zca", RISCVCPU, cfg.ext_zca, false),
|
|
|
|
- DEFINE_PROP_BOOL("x-zcb", RISCVCPU, cfg.ext_zcb, false),
|
|
|
|
- DEFINE_PROP_BOOL("x-zcd", RISCVCPU, cfg.ext_zcd, false),
|
|
|
|
- DEFINE_PROP_BOOL("x-zce", RISCVCPU, cfg.ext_zce, false),
|
|
|
|
- DEFINE_PROP_BOOL("x-zcf", RISCVCPU, cfg.ext_zcf, false),
|
|
|
|
- DEFINE_PROP_BOOL("x-zcmp", RISCVCPU, cfg.ext_zcmp, false),
|
|
|
|
- DEFINE_PROP_BOOL("x-zcmt", RISCVCPU, cfg.ext_zcmt, false),
|
|
|
|
-
|
|
|
|
/* ePMP 0.9.3 */
|
|
/* ePMP 0.9.3 */
|
|
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
|
|
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
|
|
DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
|
|
DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
|
|
@@ -1761,7 +1840,8 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str,
|
|
int i;
|
|
int i;
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
|
|
for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
|
|
- if (isa_ext_is_enabled(cpu, &isa_edata_arr[i])) {
|
|
|
|
|
|
+ if (cpu->env.priv_ver >= isa_edata_arr[i].min_version &&
|
|
|
|
+ isa_ext_is_enabled(cpu, &isa_edata_arr[i])) {
|
|
new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
|
|
new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
|
|
g_free(old);
|
|
g_free(old);
|
|
old = new;
|
|
old = new;
|