Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
---
target/riscv/cpu.c | 1 +
target/riscv/cpu.h | 4 ++++
target/riscv/cpu_helper.c | 43 +++++++++++++++++++++++++++++++++++++++
target/riscv/csr.c | 19 +++++++++++++++++
target/riscv/machine.c | 10 +++++++++
5 files changed, 77 insertions(+)
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 0d2d175fa2..4f01abc989 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -393,6 +393,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
+ riscv_cpu_update_mask(env);
cs->exception_index = RISCV_EXCP_NONE;
env->load_res = -1;
set_default_nan_mode(1, &env->fp_status);
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 8befff0166..fa5a6ba1c8 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -250,6 +250,8 @@ struct CPURISCVState {
target_ulong upmmask;
target_ulong upmbase;
#endif
+ target_ulong cur_pmmask;
+ target_ulong cur_pmbase;
float_status fp_status;
@@ -441,6 +443,8 @@ static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, target_ulong vtype)
void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *pflags);
+void riscv_cpu_update_mask(CPURISCVState *env);
+
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask);
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 79aba9c880..8320f56d9f 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -133,6 +133,48 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
*pflags = flags;
}
+void riscv_cpu_update_mask(CPURISCVState *env)
+{
+ target_ulong mask = -1, base = 0;
+ /*
+ * TODO: Current RVJ spec does not specify
+ * how the extension interacts with XLEN.
+ */
+#ifndef CONFIG_USER_ONLY
+ if (riscv_has_ext(env, RVJ)) {
+ switch (env->priv) {
+ case PRV_M:
+ if (env->mmte & M_PM_ENABLE) {
+ mask = env->mpmmask;
+ base = env->mpmbase;
+ }
+ break;
+ case PRV_S:
+ if (env->mmte & S_PM_ENABLE) {
+ mask = env->spmmask;
+ base = env->spmbase;
+ }
+ break;
+ case PRV_U:
+ if (env->mmte & U_PM_ENABLE) {
+ mask = env->upmmask;
+ base = env->upmbase;
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+#endif
+ if (cpu_get_xl(env) == MXL_RV32) {
+ env->cur_pmmask = mask & UINT32_MAX;
+ env->cur_pmbase = base & UINT32_MAX;
+ } else {
+ env->cur_pmmask = mask;
+ env->cur_pmbase = base;
+ }
+}
+
#ifndef CONFIG_USER_ONLY
static int riscv_cpu_local_irq_pending(CPURISCVState *env)
{
@@ -331,6 +373,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;
+ riscv_cpu_update_mask(env);
/*
* Clear the load reservation - otherwise a reservation placed in one
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 74c0b788fd..6bb2d09519 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1496,6 +1496,7 @@ static RISCVException write_mmte(CPURISCVState *env, int csrno,
/* hardwiring pm.instruction bit to 0, since it's not supported yet */
wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN);
env->mmte = wpri_val | PM_EXT_DIRTY;
+ riscv_cpu_update_mask(env);
/* Set XS and SD bits, since PM CSRs are dirty */
mstatus = env->mstatus | MSTATUS_XS;
@@ -1571,6 +1572,9 @@ static RISCVException write_mpmmask(CPURISCVState *env, int csrno,
uint64_t mstatus;
env->mpmmask = val;
+ if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
+ env->cur_pmmask = val;
+ }
env->mmte |= PM_EXT_DIRTY;
/* Set XS and SD bits, since PM CSRs are dirty */
@@ -1596,6 +1600,9 @@ static RISCVException write_spmmask(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
env->spmmask = val;
+ if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
+ env->cur_pmmask = val;
+ }
env->mmte |= PM_EXT_DIRTY;
/* Set XS and SD bits, since PM CSRs are dirty */
@@ -1621,6 +1628,9 @@ static RISCVException write_upmmask(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
env->upmmask = val;
+ if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
+ env->cur_pmmask = val;
+ }
env->mmte |= PM_EXT_DIRTY;
/* Set XS and SD bits, since PM CSRs are dirty */
@@ -1642,6 +1652,9 @@ static RISCVException write_mpmbase(CPURISCVState *env, int csrno,
uint64_t mstatus;
env->mpmbase = val;
+ if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
+ env->cur_pmbase = val;
+ }
env->mmte |= PM_EXT_DIRTY;
/* Set XS and SD bits, since PM CSRs are dirty */
@@ -1667,6 +1680,9 @@ static RISCVException write_spmbase(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
env->spmbase = val;
+ if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
+ env->cur_pmbase = val;
+ }
env->mmte |= PM_EXT_DIRTY;
/* Set XS and SD bits, since PM CSRs are dirty */
@@ -1692,6 +1708,9 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
env->upmbase = val;
+ if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
+ env->cur_pmbase = val;
+ }
env->mmte |= PM_EXT_DIRTY;
/* Set XS and SD bits, since PM CSRs are dirty */
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 7b4c739564..19e982d3f0 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -164,10 +164,20 @@ static const VMStateDescription vmstate_hyper = {
}
};
+static int riscv_cpu_post_load(void *opaque, int version_id)
+{
+ RISCVCPU *cpu = opaque;
+ CPURISCVState *env = &cpu->env;
+
+ riscv_cpu_update_mask(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),
--
2.25.1
On Fri, Nov 12, 2021 at 2:00 AM LIU Zhiwei <zhiwei_liu@c-sky.com> wrote:
>
> Signed-off-by: LIU Zhiwei <zhiwei_liu@c-sky.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> target/riscv/cpu.c | 1 +
> target/riscv/cpu.h | 4 ++++
> target/riscv/cpu_helper.c | 43 +++++++++++++++++++++++++++++++++++++++
> target/riscv/csr.c | 19 +++++++++++++++++
> target/riscv/machine.c | 10 +++++++++
> 5 files changed, 77 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 0d2d175fa2..4f01abc989 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -393,6 +393,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
> + riscv_cpu_update_mask(env);
> cs->exception_index = RISCV_EXCP_NONE;
> env->load_res = -1;
> set_default_nan_mode(1, &env->fp_status);
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 8befff0166..fa5a6ba1c8 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -250,6 +250,8 @@ struct CPURISCVState {
> target_ulong upmmask;
> target_ulong upmbase;
> #endif
> + target_ulong cur_pmmask;
> + target_ulong cur_pmbase;
>
> float_status fp_status;
>
> @@ -441,6 +443,8 @@ static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, target_ulong vtype)
> void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
> target_ulong *cs_base, uint32_t *pflags);
>
> +void riscv_cpu_update_mask(CPURISCVState *env);
> +
> RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
> target_ulong *ret_value,
> target_ulong new_value, target_ulong write_mask);
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 79aba9c880..8320f56d9f 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -133,6 +133,48 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
> *pflags = flags;
> }
>
> +void riscv_cpu_update_mask(CPURISCVState *env)
> +{
> + target_ulong mask = -1, base = 0;
> + /*
> + * TODO: Current RVJ spec does not specify
> + * how the extension interacts with XLEN.
> + */
> +#ifndef CONFIG_USER_ONLY
> + if (riscv_has_ext(env, RVJ)) {
> + switch (env->priv) {
> + case PRV_M:
> + if (env->mmte & M_PM_ENABLE) {
> + mask = env->mpmmask;
> + base = env->mpmbase;
> + }
> + break;
> + case PRV_S:
> + if (env->mmte & S_PM_ENABLE) {
> + mask = env->spmmask;
> + base = env->spmbase;
> + }
> + break;
> + case PRV_U:
> + if (env->mmte & U_PM_ENABLE) {
> + mask = env->upmmask;
> + base = env->upmbase;
> + }
> + break;
> + default:
> + g_assert_not_reached();
> + }
> + }
> +#endif
> + if (cpu_get_xl(env) == MXL_RV32) {
> + env->cur_pmmask = mask & UINT32_MAX;
> + env->cur_pmbase = base & UINT32_MAX;
> + } else {
> + env->cur_pmmask = mask;
> + env->cur_pmbase = base;
> + }
> +}
> +
> #ifndef CONFIG_USER_ONLY
> static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> {
> @@ -331,6 +373,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;
> + riscv_cpu_update_mask(env);
>
> /*
> * Clear the load reservation - otherwise a reservation placed in one
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 74c0b788fd..6bb2d09519 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -1496,6 +1496,7 @@ static RISCVException write_mmte(CPURISCVState *env, int csrno,
> /* hardwiring pm.instruction bit to 0, since it's not supported yet */
> wpri_val &= ~(MMTE_M_PM_INSN | MMTE_S_PM_INSN | MMTE_U_PM_INSN);
> env->mmte = wpri_val | PM_EXT_DIRTY;
> + riscv_cpu_update_mask(env);
>
> /* Set XS and SD bits, since PM CSRs are dirty */
> mstatus = env->mstatus | MSTATUS_XS;
> @@ -1571,6 +1572,9 @@ static RISCVException write_mpmmask(CPURISCVState *env, int csrno,
> uint64_t mstatus;
>
> env->mpmmask = val;
> + if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
> + env->cur_pmmask = val;
> + }
> env->mmte |= PM_EXT_DIRTY;
>
> /* Set XS and SD bits, since PM CSRs are dirty */
> @@ -1596,6 +1600,9 @@ static RISCVException write_spmmask(CPURISCVState *env, int csrno,
> return RISCV_EXCP_NONE;
> }
> env->spmmask = val;
> + if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
> + env->cur_pmmask = val;
> + }
> env->mmte |= PM_EXT_DIRTY;
>
> /* Set XS and SD bits, since PM CSRs are dirty */
> @@ -1621,6 +1628,9 @@ static RISCVException write_upmmask(CPURISCVState *env, int csrno,
> return RISCV_EXCP_NONE;
> }
> env->upmmask = val;
> + if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
> + env->cur_pmmask = val;
> + }
> env->mmte |= PM_EXT_DIRTY;
>
> /* Set XS and SD bits, since PM CSRs are dirty */
> @@ -1642,6 +1652,9 @@ static RISCVException write_mpmbase(CPURISCVState *env, int csrno,
> uint64_t mstatus;
>
> env->mpmbase = val;
> + if ((env->priv == PRV_M) && (env->mmte & M_PM_ENABLE)) {
> + env->cur_pmbase = val;
> + }
> env->mmte |= PM_EXT_DIRTY;
>
> /* Set XS and SD bits, since PM CSRs are dirty */
> @@ -1667,6 +1680,9 @@ static RISCVException write_spmbase(CPURISCVState *env, int csrno,
> return RISCV_EXCP_NONE;
> }
> env->spmbase = val;
> + if ((env->priv == PRV_S) && (env->mmte & S_PM_ENABLE)) {
> + env->cur_pmbase = val;
> + }
> env->mmte |= PM_EXT_DIRTY;
>
> /* Set XS and SD bits, since PM CSRs are dirty */
> @@ -1692,6 +1708,9 @@ static RISCVException write_upmbase(CPURISCVState *env, int csrno,
> return RISCV_EXCP_NONE;
> }
> env->upmbase = val;
> + if ((env->priv == PRV_U) && (env->mmte & U_PM_ENABLE)) {
> + env->cur_pmbase = val;
> + }
> env->mmte |= PM_EXT_DIRTY;
>
> /* Set XS and SD bits, since PM CSRs are dirty */
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 7b4c739564..19e982d3f0 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -164,10 +164,20 @@ static const VMStateDescription vmstate_hyper = {
> }
> };
>
> +static int riscv_cpu_post_load(void *opaque, int version_id)
> +{
> + RISCVCPU *cpu = opaque;
> + CPURISCVState *env = &cpu->env;
> +
> + riscv_cpu_update_mask(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),
> --
> 2.25.1
>
>
© 2016 - 2026 Red Hat, Inc.