@@ -25,6 +25,7 @@
#include "exec/cpu-defs.h"
#include "fpu/softfloat-types.h"
#include "qom/object.h"
+#include "cpu_bits.h"
#define TCG_GUEST_DEFAULT_MO 0
@@ -51,9 +52,6 @@
# define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE64
#endif
-#define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2))
-#define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2))
-
#define RV(x) ((target_ulong)1 << (x - 'A'))
#define RVI RV('I')
@@ -133,8 +131,12 @@ struct CPURISCVState {
target_ulong priv_ver;
target_ulong bext_ver;
target_ulong vext_ver;
- target_ulong misa;
- target_ulong misa_mask;
+
+ /* RISCVMXL, but uint32_t for vmstate migration */
+ uint32_t misa_mxl; /* current mxl */
+ uint32_t misa_mxl_max; /* max mxl for this cpu */
+ uint32_t misa_ext; /* current extensions */
+ uint32_t misa_ext_mask; /* max ext for this cpu */
uint32_t features;
@@ -313,7 +315,7 @@ struct RISCVCPU {
static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
{
- return (env->misa & ext) != 0;
+ return (env->misa_ext & ext) != 0;
}
static inline bool riscv_feature(CPURISCVState *env, int feature)
@@ -322,7 +324,6 @@ static inline bool riscv_feature(CPURISCVState *env, int feature)
}
#include "cpu_user.h"
-#include "cpu_bits.h"
extern const char * const riscv_int_regnames[];
extern const char * const riscv_fpr_regnames[];
@@ -1448,7 +1448,7 @@ static uint32_t get_elf_hwcap(void)
uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A')
| MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C');
- return cpu->env.misa & mask;
+ return cpu->env.misa_ext & mask;
#undef MISA_BIT
}
@@ -133,7 +133,7 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
env->gpr[xSP] = regs->sp;
env->elf_flags = info->elf_flags;
- if ((env->misa & RVE) && !(env->elf_flags & EF_RISCV_RVE)) {
+ if ((env->misa_ext & RVE) && !(env->elf_flags & EF_RISCV_RVE)) {
error_report("Incompatible ELF: RVE cpu requires RVE ABI binary");
exit(EXIT_FAILURE);
}
@@ -110,16 +110,13 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
bool riscv_cpu_is_32bit(CPURISCVState *env)
{
- if (env->misa & RV64) {
- return false;
- }
-
- return true;
+ return env->misa_mxl == MXL_RV32;
}
-static void set_misa(CPURISCVState *env, target_ulong misa)
+static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
{
- env->misa_mask = env->misa = misa;
+ env->misa_mxl_max = env->misa_mxl = mxl;
+ env->misa_ext_mask = env->misa_ext = ext;
}
static void set_priv_version(CPURISCVState *env, int priv_ver)
@@ -148,9 +145,9 @@ static void riscv_any_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
#if defined(TARGET_RISCV32)
- set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+ set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
#elif defined(TARGET_RISCV64)
- set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
+ set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
#endif
set_priv_version(env, PRIV_VERSION_1_11_0);
}
@@ -160,20 +157,20 @@ static void rv64_base_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
- set_misa(env, RV64);
+ set_misa(env, MXL_RV64, 0);
}
static void rv64_sifive_u_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
- set_misa(env, 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);
}
static void rv64_sifive_e_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
- set_misa(env, 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);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
@@ -182,20 +179,20 @@ static void rv32_base_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
- set_misa(env, RV32);
+ set_misa(env, MXL_RV32, 0);
}
static void rv32_sifive_u_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
- set_misa(env, 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);
}
static void rv32_sifive_e_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
- set_misa(env, 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);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
@@ -203,7 +200,7 @@ static void rv32_sifive_e_cpu_init(Object *obj)
static void rv32_ibex_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
- set_misa(env, RV32 | RVI | RVM | RVC | RVU);
+ set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
qdev_prop_set_bit(DEVICE(obj), "x-epmp", true);
@@ -212,7 +209,7 @@ static void rv32_ibex_cpu_init(Object *obj)
static void rv32_imafcu_nommu_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
- set_misa(env, 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);
set_resetvec(env, DEFAULT_RSTVEC);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
@@ -360,6 +357,7 @@ static void riscv_cpu_reset(DeviceState *dev)
mcc->parent_reset(dev);
#ifndef CONFIG_USER_ONLY
+ env->misa_mxl = env->misa_mxl_max;
env->priv = PRV_M;
env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
env->mcause = 0;
@@ -388,7 +386,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
CPURISCVState *env = &cpu->env;
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
int priv_version = 0;
- target_ulong target_misa = env->misa;
Error *local_err = NULL;
cpu_exec_realizefn(cs, &local_err);
@@ -434,8 +431,23 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
set_resetvec(env, cpu->cfg.resetvec);
- /* If only XLEN is set for misa, then set misa from properties */
- if (env->misa == RV32 || env->misa == RV64) {
+ /* Validate that MISA_MXL is set properly. */
+ switch (env->misa_mxl_max) {
+#ifdef TARGET_RISCV64
+ case MXL_RV64:
+ break;
+#endif
+ case MXL_RV32:
+ 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) {
+ uint32_t ext = 0;
+
/* Do some ISA extension error checking */
if (cpu->cfg.ext_i && cpu->cfg.ext_e) {
error_setg(errp,
@@ -462,38 +474,38 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
/* Set the ISA extensions, checks should have happened above */
if (cpu->cfg.ext_i) {
- target_misa |= RVI;
+ ext |= RVI;
}
if (cpu->cfg.ext_e) {
- target_misa |= RVE;
+ ext |= RVE;
}
if (cpu->cfg.ext_m) {
- target_misa |= RVM;
+ ext |= RVM;
}
if (cpu->cfg.ext_a) {
- target_misa |= RVA;
+ ext |= RVA;
}
if (cpu->cfg.ext_f) {
- target_misa |= RVF;
+ ext |= RVF;
}
if (cpu->cfg.ext_d) {
- target_misa |= RVD;
+ ext |= RVD;
}
if (cpu->cfg.ext_c) {
- target_misa |= RVC;
+ ext |= RVC;
}
if (cpu->cfg.ext_s) {
- target_misa |= RVS;
+ ext |= RVS;
}
if (cpu->cfg.ext_u) {
- target_misa |= RVU;
+ ext |= RVU;
}
if (cpu->cfg.ext_h) {
- target_misa |= RVH;
+ ext |= RVH;
}
if (cpu->cfg.ext_v) {
int vext_version = VEXT_VERSION_0_07_1;
- target_misa |= RVV;
+ ext |= RVV;
if (!is_power_of_2(cpu->cfg.vlen)) {
error_setg(errp,
"Vector extension VLEN must be power of 2");
@@ -532,7 +544,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
set_vext_version(env, vext_version);
}
- set_misa(env, target_misa);
+ set_misa(env, env->misa_mxl, ext);
}
riscv_cpu_register_gdb_regs_for_features(cs);
@@ -705,7 +717,7 @@ char *riscv_isa_string(RISCVCPU *cpu)
char *isa_str = g_new(char, maxlen);
char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS);
for (i = 0; i < sizeof(riscv_exts); i++) {
- if (cpu->env.misa & RV(riscv_exts[i])) {
+ if (cpu->env.misa_ext & RV(riscv_exts[i])) {
*p++ = qemu_tolower(riscv_exts[i]);
}
}
@@ -39,7 +39,7 @@ static RISCVException fs(CPURISCVState *env, int csrno)
{
#if !defined(CONFIG_USER_ONLY)
/* loose check condition for fcsr in vector extension */
- if ((csrno == CSR_FCSR) && (env->misa & RVV)) {
+ if ((csrno == CSR_FCSR) && (env->misa_ext & RVV)) {
return RISCV_EXCP_NONE;
}
if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
@@ -51,7 +51,7 @@ static RISCVException fs(CPURISCVState *env, int csrno)
static RISCVException vs(CPURISCVState *env, int csrno)
{
- if (env->misa & RVV) {
+ if (env->misa_ext & RVV) {
return RISCV_EXCP_NONE;
}
return RISCV_EXCP_ILLEGAL_INST;
@@ -557,7 +557,22 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno,
static RISCVException read_misa(CPURISCVState *env, int csrno,
target_ulong *val)
{
- *val = env->misa;
+ target_ulong misa;
+
+ switch (env->misa_mxl) {
+ case MXL_RV32:
+ misa = (target_ulong)MXL_RV32 << 30;
+ break;
+#ifdef TARGET_RISCV64
+ case MXL_RV64:
+ misa = (target_ulong)MXL_RV64 << 62;
+ break;
+#endif
+ default:
+ g_assert_not_reached();
+ }
+
+ *val = misa | env->misa_ext;
return RISCV_EXCP_NONE;
}
@@ -583,8 +598,13 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
+ /*
+ * misa.MXL writes are not supported by QEMU.
+ * Drop writes to those bits.
+ */
+
/* Mask extensions that are not supported by this hart */
- val &= env->misa_mask;
+ val &= env->misa_ext_mask;
/* Mask extensions that are not supported by QEMU */
val &= (RVI | RVE | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
@@ -601,20 +621,14 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
val &= ~RVC;
}
- /* misa.MXL writes are not supported by QEMU */
- if (riscv_cpu_is_32bit(env)) {
- val = (env->misa & MISA32_MXL) | (val & ~MISA32_MXL);
- } else {
- val = (env->misa & MISA64_MXL) | (val & ~MISA64_MXL);
+ /* If nothing changed, do nothing. */
+ if (val == env->misa_ext) {
+ return RISCV_EXCP_NONE;
}
/* flush translation cache */
- if (val != env->misa) {
- tb_flush(env_cpu(env));
- }
-
- env->misa = val;
-
+ tb_flush(env_cpu(env));
+ env->misa_ext = val;
return RISCV_EXCP_NONE;
}
@@ -54,10 +54,10 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n)
{
if (n < 32) {
- if (env->misa & RVD) {
+ if (env->misa_ext & RVD) {
return gdb_get_reg64(buf, env->fpr[n]);
}
- if (env->misa & RVF) {
+ if (env->misa_ext & RVF) {
return gdb_get_reg32(buf, env->fpr[n]);
}
/* there is hole between ft11 and fflags in fpu.xml */
@@ -191,10 +191,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
{
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
- if (env->misa & RVD) {
+ if (env->misa_ext & RVD) {
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
36, "riscv-64bit-fpu.xml", 0);
- } else if (env->misa & RVF) {
+ } else if (env->misa_ext & RVF) {
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
36, "riscv-32bit-fpu.xml", 0);
}
@@ -140,8 +140,8 @@ static const VMStateDescription vmstate_hyper = {
const VMStateDescription vmstate_riscv_cpu = {
.name = "cpu",
- .version_id = 2,
- .minimum_version_id = 2,
+ .version_id = 3,
+ .minimum_version_id = 3,
.fields = (VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32),
@@ -153,8 +153,10 @@ const VMStateDescription vmstate_riscv_cpu = {
VMSTATE_UINTTL(env.guest_phys_fault_addr, RISCVCPU),
VMSTATE_UINTTL(env.priv_ver, RISCVCPU),
VMSTATE_UINTTL(env.vext_ver, RISCVCPU),
- VMSTATE_UINTTL(env.misa, RISCVCPU),
- VMSTATE_UINTTL(env.misa_mask, RISCVCPU),
+ VMSTATE_UINT32(env.misa_mxl, RISCVCPU),
+ VMSTATE_UINT32(env.misa_ext, RISCVCPU),
+ VMSTATE_UINT32(env.misa_mxl_max, RISCVCPU),
+ VMSTATE_UINT32(env.misa_ext_mask, RISCVCPU),
VMSTATE_UINT32(env.features, RISCVCPU),
VMSTATE_UINTTL(env.priv, RISCVCPU),
VMSTATE_UINTTL(env.virt, RISCVCPU),
@@ -55,7 +55,8 @@ typedef struct DisasContext {
/* pc_succ_insn points to the instruction following base.pc_next */
target_ulong pc_succ_insn;
target_ulong priv_ver;
- target_ulong misa;
+ RISCVMXL xl;
+ uint32_t misa_ext;
uint32_t opcode;
uint32_t mstatus_fs;
uint32_t mstatus_hs_fs;
@@ -86,7 +87,7 @@ typedef struct DisasContext {
static inline bool has_ext(DisasContext *ctx, uint32_t ext)
{
- return ctx->misa & ext;
+ return ctx->misa_ext & ext;
}
#ifdef TARGET_RISCV32
@@ -96,7 +97,7 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext)
#else
static inline bool is_32bit(DisasContext *ctx)
{
- return (ctx->misa & RV32) == RV32;
+ return ctx->xl == MXL_RV32;
}
#endif
@@ -538,7 +539,8 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
#else
ctx->virt_enabled = false;
#endif
- ctx->misa = env->misa;
+ ctx->xl = env->misa_mxl;
+ ctx->misa_ext = env->misa_ext;
ctx->frm = -1; /* unknown rounding mode */
ctx->ext_ifencei = cpu->cfg.ext_ifencei;
ctx->vlen = cpu->cfg.vlen;