#include "sysemu/kvm.h"
#include "sysemu/tcg.h"
#include "kvm/kvm_riscv.h"
+#include "tcg/tcg-cpu.h"
#include "tcg/tcg.h"
/* RISC-V CPU definitions */
static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
-
-struct isa_ext_data {
- const char *name;
- int min_version;
- int ext_enable_offset;
-};
-
-#define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \
- {#_name, _min_ver, CPU_CFG_OFFSET(_prop)}
+const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV,
+ RVC, RVS, RVU, RVH, RVJ, RVG, 0};
/*
* From vector_helper.c
#define BYTE(x) (x)
#endif
+#define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \
+ {#_name, _min_ver, CPU_CFG_OFFSET(_prop)}
+
/*
* Here are the ordering rules of extension naming defined by RISC-V
* specification :
* Single letter extensions are checked in riscv_cpu_validate_misa_priv()
* instead.
*/
-static const struct isa_ext_data isa_edata_arr[] = {
- ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_icbom),
- ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_icboz),
+const RISCVIsaExtData isa_edata_arr[] = {
+ ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_zicbom),
+ ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_zicboz),
ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond),
- ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_icsr),
- ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_ifencei),
+ ISA_EXT_DATA_ENTRY(zicntr, PRIV_VERSION_1_12_0, ext_zicntr),
+ ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_zicsr),
+ ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_zifencei),
ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl),
ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
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(smaia, PRIV_VERSION_1_12_0, ext_smaia),
- ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, epmp),
+ ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
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(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf),
ISA_EXT_DATA_ENTRY(xtheadmempair, PRIV_VERSION_1_11_0, ext_xtheadmempair),
ISA_EXT_DATA_ENTRY(xtheadsync, PRIV_VERSION_1_11_0, ext_xtheadsync),
ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
-};
-/* Hash that stores user set extensions */
-static GHashTable *multi_ext_user_opts;
+ DEFINE_PROP_END_OF_LIST(),
+};
bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset)
{
*ext_enabled = en;
}
-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();
-}
-
-bool cpu_cfg_ext_is_user_set(uint32_t ext_offset)
-{
- return g_hash_table_contains(multi_ext_user_opts,
- GUINT_TO_POINTER(ext_offset));
-}
-
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",
"reserved"
};
-static void riscv_cpu_add_user_properties(Object *obj);
-static void riscv_init_max_cpu_extensions(Object *obj);
-
const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
{
if (async) {
}
}
-static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
+void riscv_cpu_set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
{
env->misa_mxl_max = env->misa_mxl = mxl;
env->misa_ext_mask = env->misa_ext = ext;
RISCVCPU *cpu = RISCV_CPU(obj);
CPURISCVState *env = &cpu->env;
#if defined(TARGET_RISCV32)
- set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+ riscv_cpu_set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
#elif defined(TARGET_RISCV64)
- set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+ riscv_cpu_set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
#endif
#ifndef CONFIG_USER_ONLY
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.ext_zifencei = true;
+ cpu->cfg.ext_zicsr = true;
cpu->cfg.mmu = true;
cpu->cfg.pmp = true;
}
#ifdef TARGET_RISCV32
mlx = MXL_RV32;
#endif
- set_misa(env, mlx, 0);
+ riscv_cpu_set_misa(env, mlx, 0);
env->priv_ver = PRIV_VERSION_LATEST;
#ifndef CONFIG_USER_ONLY
set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ?
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
- set_misa(env, MXL_RV64, 0);
+ riscv_cpu_set_misa(env, MXL_RV64, 0);
/* Set latest version of privileged specification */
env->priv_ver = PRIV_VERSION_LATEST;
#ifndef CONFIG_USER_ONLY
{
RISCVCPU *cpu = RISCV_CPU(obj);
CPURISCVState *env = &cpu->env;
- set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+ riscv_cpu_set_misa(env, MXL_RV64,
+ RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
env->priv_ver = PRIV_VERSION_1_10_0;
#ifndef CONFIG_USER_ONLY
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39);
#endif
/* inherited from parent obj via riscv_cpu_init() */
- cpu->cfg.ext_ifencei = true;
- cpu->cfg.ext_icsr = true;
+ cpu->cfg.ext_zifencei = true;
+ cpu->cfg.ext_zicsr = true;
cpu->cfg.mmu = true;
cpu->cfg.pmp = true;
}
CPURISCVState *env = &RISCV_CPU(obj)->env;
RISCVCPU *cpu = RISCV_CPU(obj);
- set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
+ riscv_cpu_set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
env->priv_ver = PRIV_VERSION_1_10_0;
#ifndef CONFIG_USER_ONLY
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
#endif
/* inherited from parent obj via riscv_cpu_init() */
- cpu->cfg.ext_ifencei = true;
- cpu->cfg.ext_icsr = true;
+ cpu->cfg.ext_zifencei = true;
+ cpu->cfg.ext_zicsr = true;
cpu->cfg.pmp = true;
}
CPURISCVState *env = &RISCV_CPU(obj)->env;
RISCVCPU *cpu = RISCV_CPU(obj);
- set_misa(env, MXL_RV64, RVG | RVC | RVS | RVU);
+ riscv_cpu_set_misa(env, MXL_RV64, RVG | RVC | RVS | RVU);
env->priv_ver = PRIV_VERSION_1_11_0;
cpu->cfg.ext_zfa = true;
CPURISCVState *env = &RISCV_CPU(obj)->env;
RISCVCPU *cpu = RISCV_CPU(obj);
- set_misa(env, MXL_RV64, RVG | RVC | RVS | RVU | RVH);
+ riscv_cpu_set_misa(env, MXL_RV64, RVG | RVC | RVS | RVU | RVH);
env->priv_ver = PRIV_VERSION_1_12_0;
/* Enable ISA extensions */
cpu->cfg.mmu = true;
- cpu->cfg.ext_ifencei = true;
- cpu->cfg.ext_icsr = true;
+ cpu->cfg.ext_zifencei = true;
+ cpu->cfg.ext_zicsr = true;
cpu->cfg.pmp = true;
- cpu->cfg.ext_icbom = true;
+ cpu->cfg.ext_zicbom = true;
cpu->cfg.cbom_blocksize = 64;
cpu->cfg.cboz_blocksize = 64;
- cpu->cfg.ext_icboz = true;
+ cpu->cfg.ext_zicboz = true;
cpu->cfg.ext_smaia = true;
cpu->cfg.ext_ssaia = true;
cpu->cfg.ext_sscofpmf = true;
}
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
- set_misa(env, MXL_RV128, 0);
+ riscv_cpu_set_misa(env, MXL_RV128, 0);
/* Set latest version of privileged specification */
env->priv_ver = PRIV_VERSION_LATEST;
#ifndef CONFIG_USER_ONLY
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
- set_misa(env, MXL_RV32, 0);
+ riscv_cpu_set_misa(env, MXL_RV32, 0);
/* Set latest version of privileged specification */
env->priv_ver = PRIV_VERSION_LATEST;
#ifndef CONFIG_USER_ONLY
{
RISCVCPU *cpu = RISCV_CPU(obj);
CPURISCVState *env = &cpu->env;
- set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
+ riscv_cpu_set_misa(env, MXL_RV32,
+ RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
env->priv_ver = PRIV_VERSION_1_10_0;
#ifndef CONFIG_USER_ONLY
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
#endif
/* inherited from parent obj via riscv_cpu_init() */
- cpu->cfg.ext_ifencei = true;
- cpu->cfg.ext_icsr = true;
+ cpu->cfg.ext_zifencei = true;
+ cpu->cfg.ext_zicsr = true;
cpu->cfg.mmu = true;
cpu->cfg.pmp = true;
}
CPURISCVState *env = &RISCV_CPU(obj)->env;
RISCVCPU *cpu = RISCV_CPU(obj);
- set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
+ riscv_cpu_set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
env->priv_ver = PRIV_VERSION_1_10_0;
#ifndef CONFIG_USER_ONLY
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
#endif
/* inherited from parent obj via riscv_cpu_init() */
- cpu->cfg.ext_ifencei = true;
- cpu->cfg.ext_icsr = true;
+ cpu->cfg.ext_zifencei = true;
+ cpu->cfg.ext_zicsr = true;
cpu->cfg.pmp = true;
}
CPURISCVState *env = &RISCV_CPU(obj)->env;
RISCVCPU *cpu = RISCV_CPU(obj);
- set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
+ riscv_cpu_set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
env->priv_ver = PRIV_VERSION_1_11_0;
#ifndef CONFIG_USER_ONLY
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
#endif
- cpu->cfg.epmp = true;
-
/* inherited from parent obj via riscv_cpu_init() */
- cpu->cfg.ext_ifencei = true;
- cpu->cfg.ext_icsr = true;
+ cpu->cfg.ext_zifencei = true;
+ cpu->cfg.ext_zicsr = true;
cpu->cfg.pmp = true;
+ cpu->cfg.ext_smepmp = true;
}
static void rv32_imafcu_nommu_cpu_init(Object *obj)
CPURISCVState *env = &RISCV_CPU(obj)->env;
RISCVCPU *cpu = RISCV_CPU(obj);
- set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
+ riscv_cpu_set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
env->priv_ver = PRIV_VERSION_1_10_0;
#ifndef CONFIG_USER_ONLY
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
#endif
/* inherited from parent obj via riscv_cpu_init() */
- cpu->cfg.ext_ifencei = true;
- cpu->cfg.ext_icsr = true;
+ cpu->cfg.ext_zifencei = true;
+ cpu->cfg.ext_zicsr = true;
cpu->cfg.pmp = true;
}
#endif
return oc;
}
+char *riscv_cpu_get_name(RISCVCPU *cpu)
+{
+ RISCVCPUClass *rcc = RISCV_CPU_GET_CLASS(cpu);
+ const char *typename = object_class_get_name(OBJECT_CLASS(rcc));
+
+ g_assert(g_str_has_suffix(typename, RISCV_CPU_TYPE_SUFFIX));
+
+ return g_strndup(typename,
+ strlen(typename) - strlen(RISCV_CPU_TYPE_SUFFIX));
+}
+
static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{
RISCVCPU *cpu = RISCV_CPU(cs);
* Definition of the WFI instruction requires it to ignore the privilege
* mode and delegation registers, but respect individual enables
*/
- return riscv_cpu_all_pending(env) != 0;
+ return riscv_cpu_all_pending(env) != 0 ||
+ riscv_cpu_sirq_pending(env) != RISCV_EXCP_NONE ||
+ riscv_cpu_vsirq_pending(env) != RISCV_EXCP_NONE;
#else
return true;
#endif
}
/* mmte is supposed to have pm.current hardwired to 1 */
env->mmte |= (EXT_STATUS_INITIAL | MMTE_M_PM_CURRENT);
+
+ /*
+ * Clear mseccfg and unlock all the PMP entries upon reset.
+ * This is allowed as per the priv and smepmp specifications
+ * and is needed to clear stale entries across reboots.
+ */
+ if (riscv_cpu_cfg(env)->ext_smepmp) {
+ env->mseccfg = 0;
+ }
+
+ pmp_unlock_entries(env);
#endif
env->xl = riscv_cpu_mxl(env);
riscv_cpu_update_mask(env);
}
}
-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].ext_enable_offset) &&
- (env->priv_ver < isa_edata_arr[i].min_version)) {
- isa_ext_update_enabled(cpu, isa_edata_arr[i].ext_enable_offset,
- 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
- }
- }
-}
-
#ifndef CONFIG_USER_ONLY
static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
{
}
#endif
-static void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
+void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
{
-#ifndef CONFIG_USER_ONLY
Error *local_err = NULL;
+ /*
+ * KVM accel does not have a specialized finalize()
+ * callback because its extensions are validated
+ * in the get()/set() callbacks of each property.
+ */
+ if (tcg_enabled()) {
+ riscv_tcg_cpu_finalize_features(cpu, &local_err);
+ if (local_err != NULL) {
+ error_propagate(errp, local_err);
+ return;
+ }
+ }
+
+#ifndef CONFIG_USER_ONLY
riscv_cpu_satp_mode_finalize(cpu, &local_err);
if (local_err != NULL) {
error_propagate(errp, local_err);
mcc->parent_realize(dev, errp);
}
+bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu)
+{
+ if (tcg_enabled()) {
+ return riscv_cpu_tcg_compatible(cpu);
+ }
+
+ return true;
+}
+
#ifndef CONFIG_USER_ONLY
static void cpu_riscv_get_satp(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL;
}
-static bool riscv_cpu_has_max_extensions(Object *cpu_obj)
-{
- return object_dynamic_cast(cpu_obj, TYPE_RISCV_CPU_MAX) != NULL;
-}
-
-static bool riscv_cpu_has_user_properties(Object *cpu_obj)
-{
- if (kvm_enabled() &&
- object_dynamic_cast(cpu_obj, TYPE_RISCV_CPU_HOST) != NULL) {
- return true;
- }
-
- return riscv_cpu_is_dynamic(cpu_obj);
-}
-
static void riscv_cpu_post_init(Object *obj)
{
accel_cpu_instance_init(CPU(obj));
-
- if (tcg_enabled() && riscv_cpu_has_user_properties(obj)) {
- riscv_cpu_add_user_properties(obj);
- }
-
- if (riscv_cpu_has_max_extensions(obj)) {
- riscv_init_max_cpu_extensions(obj);
- }
}
static void riscv_cpu_init(Object *obj)
IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
#endif /* CONFIG_USER_ONLY */
- multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal);
-}
-
-typedef struct RISCVCPUMisaExtConfig {
- const char *name;
- const char *description;
- target_ulong misa_bit;
- bool enabled;
-} RISCVCPUMisaExtConfig;
-
-static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
- target_ulong misa_bit = misa_ext_cfg->misa_bit;
- RISCVCPU *cpu = RISCV_CPU(obj);
- CPURISCVState *env = &cpu->env;
- bool value;
-
- if (!visit_type_bool(v, name, &value, errp)) {
- return;
- }
-
- if (value) {
- env->misa_ext |= misa_bit;
- env->misa_ext_mask |= misa_bit;
- } else {
- env->misa_ext &= ~misa_bit;
- env->misa_ext_mask &= ~misa_bit;
- }
-}
-
-static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- const RISCVCPUMisaExtConfig *misa_ext_cfg = opaque;
- target_ulong misa_bit = misa_ext_cfg->misa_bit;
- RISCVCPU *cpu = RISCV_CPU(obj);
- CPURISCVState *env = &cpu->env;
- bool value;
-
- value = env->misa_ext & misa_bit;
-
- visit_type_bool(v, name, &value, errp);
+ /*
+ * The timer and performance counters extensions were supported
+ * in QEMU before they were added as discrete extensions in the
+ * ISA. To keep compatibility we'll always default them to 'true'
+ * for all CPUs. Each accelerator will decide what to do when
+ * users disable them.
+ */
+ RISCV_CPU(obj)->cfg.ext_zicntr = true;
}
typedef struct misa_ext_info {
return val;
}
-#define MISA_CFG(_bit, _enabled) \
- {.misa_bit = _bit, .enabled = _enabled}
-
-static RISCVCPUMisaExtConfig misa_ext_cfgs[] = {
- MISA_CFG(RVA, true),
- MISA_CFG(RVC, true),
- MISA_CFG(RVD, true),
- MISA_CFG(RVF, true),
- MISA_CFG(RVI, true),
- MISA_CFG(RVE, false),
- MISA_CFG(RVM, true),
- MISA_CFG(RVS, true),
- MISA_CFG(RVU, true),
- MISA_CFG(RVH, true),
- MISA_CFG(RVJ, false),
- MISA_CFG(RVV, false),
- MISA_CFG(RVG, false),
-};
-
-/*
- * We do not support user choice tracking for MISA
- * extensions yet because, so far, we do not silently
- * change MISA bits during realize() (RVG enables MISA
- * bits but the user is warned about it).
- */
-void riscv_cpu_add_misa_properties(Object *cpu_obj)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(misa_ext_cfgs); i++) {
- RISCVCPUMisaExtConfig *misa_cfg = &misa_ext_cfgs[i];
- int bit = misa_cfg->misa_bit;
-
- misa_cfg->name = riscv_get_misa_ext_name(bit);
- misa_cfg->description = riscv_get_misa_ext_description(bit);
-
- /* Check if KVM already created the property */
- if (object_property_find(cpu_obj, misa_cfg->name)) {
- continue;
- }
-
- object_property_add(cpu_obj, misa_cfg->name, "bool",
- cpu_get_misa_ext_cfg,
- cpu_set_misa_ext_cfg,
- NULL, (void *)misa_cfg);
- object_property_set_description(cpu_obj, misa_cfg->name,
- misa_cfg->description);
- object_property_set_bool(cpu_obj, misa_cfg->name,
- misa_cfg->enabled, NULL);
- }
-}
-
#define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \
{.name = _name, .offset = CPU_CFG_OFFSET(_prop), \
.enabled = _defval}
const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
/* Defaults for standard extensions */
MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false),
- MULTI_EXT_CFG_BOOL("Zifencei", ext_ifencei, true),
- MULTI_EXT_CFG_BOOL("Zicsr", ext_icsr, true),
- MULTI_EXT_CFG_BOOL("Zihintntl", ext_zihintntl, true),
- MULTI_EXT_CFG_BOOL("Zihintpause", ext_zihintpause, true),
- MULTI_EXT_CFG_BOOL("Zawrs", ext_zawrs, true),
- MULTI_EXT_CFG_BOOL("Zfa", ext_zfa, true),
- MULTI_EXT_CFG_BOOL("Zfh", ext_zfh, false),
- MULTI_EXT_CFG_BOOL("Zfhmin", ext_zfhmin, false),
- MULTI_EXT_CFG_BOOL("Zve32f", ext_zve32f, false),
- MULTI_EXT_CFG_BOOL("Zve64f", ext_zve64f, false),
- MULTI_EXT_CFG_BOOL("Zve64d", ext_zve64d, false),
+ MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true),
+ MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
+ MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
+ MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
+ MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
+ MULTI_EXT_CFG_BOOL("zfa", ext_zfa, true),
+ MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false),
+ MULTI_EXT_CFG_BOOL("zfhmin", ext_zfhmin, false),
+ MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false),
+ MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false),
+ MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false),
MULTI_EXT_CFG_BOOL("sstc", ext_sstc, true),
+ MULTI_EXT_CFG_BOOL("smepmp", ext_smepmp, false),
MULTI_EXT_CFG_BOOL("smstateen", ext_smstateen, false),
MULTI_EXT_CFG_BOOL("svadu", ext_svadu, true),
MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false),
MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false),
MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false),
+ MULTI_EXT_CFG_BOOL("zicntr", ext_zicntr, true),
+
MULTI_EXT_CFG_BOOL("zba", ext_zba, true),
MULTI_EXT_CFG_BOOL("zbb", ext_zbb, true),
MULTI_EXT_CFG_BOOL("zbc", ext_zbc, true),
MULTI_EXT_CFG_BOOL("zhinx", ext_zhinx, false),
MULTI_EXT_CFG_BOOL("zhinxmin", ext_zhinxmin, false),
- MULTI_EXT_CFG_BOOL("zicbom", ext_icbom, true),
- MULTI_EXT_CFG_BOOL("zicboz", ext_icboz, true),
+ MULTI_EXT_CFG_BOOL("zicbom", ext_zicbom, true),
+ MULTI_EXT_CFG_BOOL("zicboz", ext_zicboz, true),
MULTI_EXT_CFG_BOOL("zmmul", ext_zmmul, false),
/* These are experimental so mark with 'x-' */
const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
- /* ePMP 0.9.3 */
- MULTI_EXT_CFG_BOOL("x-epmp", epmp, false),
MULTI_EXT_CFG_BOOL("x-smaia", ext_smaia, false),
MULTI_EXT_CFG_BOOL("x-ssaia", ext_ssaia, false),
DEFINE_PROP_END_OF_LIST(),
};
+/* Deprecated entries marked for future removal */
+const RISCVCPUMultiExtConfig riscv_cpu_deprecated_exts[] = {
+ MULTI_EXT_CFG_BOOL("Zifencei", ext_zifencei, true),
+ MULTI_EXT_CFG_BOOL("Zicsr", ext_zicsr, true),
+ MULTI_EXT_CFG_BOOL("Zihintntl", ext_zihintntl, true),
+ MULTI_EXT_CFG_BOOL("Zihintpause", ext_zihintpause, true),
+ MULTI_EXT_CFG_BOOL("Zawrs", ext_zawrs, true),
+ MULTI_EXT_CFG_BOOL("Zfa", ext_zfa, true),
+ MULTI_EXT_CFG_BOOL("Zfh", ext_zfh, false),
+ MULTI_EXT_CFG_BOOL("Zfhmin", ext_zfhmin, false),
+ MULTI_EXT_CFG_BOOL("Zve32f", ext_zve32f, false),
+ MULTI_EXT_CFG_BOOL("Zve64f", ext_zve64f, false),
+ MULTI_EXT_CFG_BOOL("Zve64d", ext_zve64d, false),
+
+ DEFINE_PROP_END_OF_LIST(),
+};
+
Property riscv_cpu_options[] = {
DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
DEFINE_PROP_END_OF_LIST(),
};
-static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
- bool value;
-
- if (!visit_type_bool(v, name, &value, errp)) {
- return;
- }
-
- isa_ext_update_enabled(RISCV_CPU(obj), multi_ext_cfg->offset, value);
-
- g_hash_table_insert(multi_ext_user_opts,
- GUINT_TO_POINTER(multi_ext_cfg->offset),
- (gpointer)value);
-}
-
-static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name,
- void *opaque, Error **errp)
-{
- const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque;
- bool value = isa_ext_is_enabled(RISCV_CPU(obj), multi_ext_cfg->offset);
-
- visit_type_bool(v, name, &value, errp);
-}
-
-static void cpu_add_multi_ext_prop(Object *cpu_obj,
- const RISCVCPUMultiExtConfig *multi_cfg)
-{
- object_property_add(cpu_obj, multi_cfg->name, "bool",
- cpu_get_multi_ext_cfg,
- cpu_set_multi_ext_cfg,
- NULL, (void *)multi_cfg);
-
- /*
- * Set def val directly instead of using
- * object_property_set_bool() to save the set()
- * callback hash for user inputs.
- */
- isa_ext_update_enabled(RISCV_CPU(cpu_obj), multi_cfg->offset,
- multi_cfg->enabled);
-}
-
-static void riscv_cpu_add_multiext_prop_array(Object *obj,
- const RISCVCPUMultiExtConfig *array)
-{
- const RISCVCPUMultiExtConfig *prop;
-
- g_assert(array);
-
- for (prop = array; prop && prop->name; prop++) {
- cpu_add_multi_ext_prop(obj, prop);
- }
-}
-
-/*
- * Add CPU properties with user-facing flags.
- *
- * This will overwrite existing env->misa_ext values with the
- * defaults set via riscv_cpu_add_misa_properties().
- */
-static void riscv_cpu_add_user_properties(Object *obj)
-{
-#ifndef CONFIG_USER_ONLY
- riscv_add_satp_mode_properties(obj);
-#endif
-
- riscv_cpu_add_misa_properties(obj);
-
- riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_extensions);
- riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_vendor_exts);
- riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_experimental_exts);
-
- for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) {
- qdev_property_add_static(DEVICE(obj), prop);
- }
-}
-
-/*
- * The 'max' type CPU will have all possible ratified
- * non-vendor extensions enabled.
- */
-static void riscv_init_max_cpu_extensions(Object *obj)
-{
- RISCVCPU *cpu = RISCV_CPU(obj);
- CPURISCVState *env = &cpu->env;
- const RISCVCPUMultiExtConfig *prop;
-
- /* Enable RVG, RVJ and RVV that are disabled by default */
- set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV);
-
- for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
- isa_ext_update_enabled(cpu, prop->offset, true);
- }
-
- /* set vector version */
- env->vext_ver = VEXT_VERSION_1_00_0;
-
- /* Zfinx is not compatible with F. Disable it */
- isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zfinx), false);
- isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zdinx), false);
- isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinx), false);
- isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinxmin), false);
-
- isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zce), false);
- isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmp), false);
- isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmt), false);
-
- if (env->misa_mxl != MXL_RV32) {
- isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcf), false);
- }
-}
-
static Property riscv_cpu_properties[] = {
DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str,
int max_str_len)
{
+ const RISCVIsaExtData *edata;
char *old = *isa_str;
char *new = *isa_str;
- int i;
- for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
- if (isa_ext_is_enabled(cpu, isa_edata_arr[i].ext_enable_offset)) {
- new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
+ for (edata = isa_edata_arr; edata && edata->name; edata++) {
+ if (isa_ext_is_enabled(cpu, edata->ext_enable_offset)) {
+ new = g_strconcat(old, "_", edata->name, NULL);
g_free(old);
old = new;
}