diff options
Diffstat (limited to 'target/riscv/cpu_helper.c')
-rw-r--r-- | target/riscv/cpu_helper.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index d73925a823..b239d721f4 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -122,6 +122,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 (env->xl == 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) { @@ -334,6 +376,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); + riscv_cpu_update_mask(env); /* * Clear the load reservation - otherwise a reservation placed in one |