target/riscv: Create xl field in env

Current xlen has been used in helper functions and many other places.
The computation of current xlen is not so trivial, so that we should
recompute it as little as possible.

Fortunately, xlen only changes in very seldom cases, such as exception,
misa write, mstatus write, cpu reset, migration load. So that we can only
recompute xlen in this places and cache it into CPURISCVState.

Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-id: 20220120122050.41546-6-zhiwei_liu@c-sky.com
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
LIU Zhiwei 2022-01-20 20:20:32 +08:00 committed by Alistair Francis
parent 40f0c2046c
commit 440544e1cf
5 changed files with 46 additions and 32 deletions

View File

@ -413,6 +413,7 @@ static void riscv_cpu_reset(DeviceState *dev)
/* mmte is supposed to have pm.current hardwired to 1 */
env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT);
#endif
env->xl = riscv_cpu_mxl(env);
cs->exception_index = RISCV_EXCP_NONE;
env->load_res = -1;
set_default_nan_mode(1, &env->fp_status);

View File

@ -146,6 +146,7 @@ struct CPURISCVState {
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 xl; /* current xlen */
/* 128-bit helpers upper part return value */
target_ulong retxh;
@ -456,6 +457,36 @@ static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env)
}
#endif
#if defined(TARGET_RISCV32)
#define cpu_recompute_xl(env) ((void)(env), MXL_RV32)
#else
static inline RISCVMXL cpu_recompute_xl(CPURISCVState *env)
{
RISCVMXL xl = env->misa_mxl;
#if !defined(CONFIG_USER_ONLY)
/*
* When emulating a 32-bit-only cpu, use RV32.
* When emulating a 64-bit cpu, and MXL has been reduced to RV32,
* MSTATUSH doesn't have UXL/SXL, therefore XLEN cannot be widened
* back to RV64 for lower privs.
*/
if (xl != MXL_RV32) {
switch (env->priv) {
case PRV_M:
break;
case PRV_U:
xl = get_field(env->mstatus, MSTATUS64_UXL);
break;
default: /* PRV_S | PRV_H */
xl = get_field(env->mstatus, MSTATUS64_SXL);
break;
}
}
#endif
return xl;
}
#endif
/*
* Encode LMUL to lmul as follows:
* LMUL vlmul lmul

View File

@ -35,37 +35,6 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
#endif
}
static RISCVMXL cpu_get_xl(CPURISCVState *env)
{
#if defined(TARGET_RISCV32)
return MXL_RV32;
#elif defined(CONFIG_USER_ONLY)
return MXL_RV64;
#else
RISCVMXL xl = riscv_cpu_mxl(env);
/*
* When emulating a 32-bit-only cpu, use RV32.
* When emulating a 64-bit cpu, and MXL has been reduced to RV32,
* MSTATUSH doesn't have UXL/SXL, therefore XLEN cannot be widened
* back to RV64 for lower privs.
*/
if (xl != MXL_RV32) {
switch (env->priv) {
case PRV_M:
break;
case PRV_U:
xl = get_field(env->mstatus, MSTATUS64_UXL);
break;
default: /* PRV_S | PRV_H */
xl = get_field(env->mstatus, MSTATUS64_SXL);
break;
}
}
return xl;
#endif
}
void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *pflags)
{
@ -148,7 +117,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
}
#endif
flags = FIELD_DP32(flags, TB_FLAGS, XL, cpu_get_xl(env));
flags = FIELD_DP32(flags, TB_FLAGS, XL, env->xl);
*pflags = flags;
}
@ -364,6 +333,7 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
}
/* tlb_flush is unnecessary as mode is contained in mmu_idx */
env->priv = newpriv;
env->xl = cpu_recompute_xl(env);
/*
* Clear the load reservation - otherwise a reservation placed in one

View File

@ -589,6 +589,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
mstatus = set_field(mstatus, MSTATUS64_UXL, xl);
}
env->mstatus = mstatus;
env->xl = cpu_recompute_xl(env);
return RISCV_EXCP_NONE;
}
@ -704,6 +705,7 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
/* flush translation cache */
tb_flush(env_cpu(env));
env->misa_ext = val;
env->xl = riscv_cpu_mxl(env);
return RISCV_EXCP_NONE;
}

View File

@ -214,10 +214,20 @@ static const VMStateDescription vmstate_kvmtimer = {
}
};
static int riscv_cpu_post_load(void *opaque, int version_id)
{
RISCVCPU *cpu = opaque;
CPURISCVState *env = &cpu->env;
env->xl = cpu_recompute_xl(env);
return 0;
}
const VMStateDescription vmstate_riscv_cpu = {
.name = "cpu",
.version_id = 3,
.minimum_version_id = 3,
.post_load = riscv_cpu_post_load,
.fields = (VMStateField[]) {
VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32),