mirror of https://github.com/xemu-project/xemu.git
target/riscv/cpu.c: do not skip misa logic in riscv_cpu_realize()
All RISCV CPUs are setting cpu->cfg during their cpu_init() functions, meaning that there's no reason to skip all the misa validation and setup if misa_ext was set beforehand - especially since we're setting an updated value in set_misa() in the end. Put this code chunk into a new riscv_cpu_validate_set_extensions() helper and always execute it regardless of what the board set in env->misa_ext. This will put more responsibility in how each board is going to init their attributes and extensions if they're not using the defaults. It'll also allow realize() to do its job looking only at the extensions enabled per se, not corner cases that some CPUs might have, and we won't have to change multiple code paths to fix or change how extensions work. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Bin Meng <bmeng@tinylab.org> Message-Id: <20230113175230.473975-3-dbarboza@ventanamicro.com> [ Changes by AF: - Rebase ] Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
c66ffcd535
commit
5ab1095213
|
@ -625,103 +625,13 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
RISCVCPU *cpu = RISCV_CPU(dev);
|
||||
CPURISCVState *env = &cpu->env;
|
||||
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
|
||||
CPUClass *cc = CPU_CLASS(mcc);
|
||||
int i, priv_version = -1;
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv_version >= PRIV_VERSION_1_10_0) {
|
||||
set_priv_version(env, priv_version);
|
||||
}
|
||||
|
||||
/* 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%lx because "
|
||||
"privilege spec version does not match",
|
||||
isa_edata_arr[i].name, (unsigned long)env->mhartid);
|
||||
#else
|
||||
warn_report("disabling %s extension because "
|
||||
"privilege spec version does not match",
|
||||
isa_edata_arr[i].name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->cfg.mmu) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_MMU);
|
||||
}
|
||||
|
||||
if (cpu->cfg.pmp) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_PMP);
|
||||
|
||||
/*
|
||||
* Enhanced PMP should only be available
|
||||
* on harts with PMP support
|
||||
/*
|
||||
* Check consistency between chosen extensions while setting
|
||||
* cpu->cfg accordingly, doing a set_misa() in the end.
|
||||
*/
|
||||
if (cpu->cfg.epmp) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_EPMP);
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->cfg.debug) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_DEBUG);
|
||||
}
|
||||
|
||||
|
||||
#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);
|
||||
|
||||
/* If only MISA_EXT is unset for misa, then set it from properties */
|
||||
if (env->misa_ext == 0) {
|
||||
static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
||||
{
|
||||
CPURISCVState *env = &cpu->env;
|
||||
uint32_t ext = 0;
|
||||
|
||||
/* Do some ISA extension error checking */
|
||||
|
@ -914,6 +824,107 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
|||
}
|
||||
|
||||
set_misa(env, env->misa_mxl, ext);
|
||||
}
|
||||
|
||||
static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CPUState *cs = CPU(dev);
|
||||
RISCVCPU *cpu = RISCV_CPU(dev);
|
||||
CPURISCVState *env = &cpu->env;
|
||||
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
|
||||
CPUClass *cc = CPU_CLASS(mcc);
|
||||
int i, priv_version = -1;
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (priv_version >= PRIV_VERSION_1_10_0) {
|
||||
set_priv_version(env, priv_version);
|
||||
}
|
||||
|
||||
/* 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%lx because "
|
||||
"privilege spec version does not match",
|
||||
isa_edata_arr[i].name, (unsigned long)env->mhartid);
|
||||
#else
|
||||
warn_report("disabling %s extension because "
|
||||
"privilege spec version does not match",
|
||||
isa_edata_arr[i].name);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->cfg.mmu) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_MMU);
|
||||
}
|
||||
|
||||
if (cpu->cfg.pmp) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_PMP);
|
||||
|
||||
/*
|
||||
* Enhanced PMP should only be available
|
||||
* on harts with PMP support
|
||||
*/
|
||||
if (cpu->cfg.epmp) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_EPMP);
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->cfg.debug) {
|
||||
riscv_set_feature(env, RISCV_FEATURE_DEBUG);
|
||||
}
|
||||
|
||||
|
||||
#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);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
|
Loading…
Reference in New Issue