Message ID | 20230325105429.1142530-18-richard.henderson@linaro.org |
---|---|
State | Superseded |
Headers | show |
Series | target/riscv: MSTATUS_SUM + cleanups | expand |
On Sat, Mar 25, 2023 at 10:42 PM Richard Henderson <richard.henderson@linaro.org> wrote: > > Table 9.5 "Effect of MPRV..." specifies that MPV=1 uses VS-level > vsstatus.SUM instead of HS-level sstatus.SUM. > > For HLV/HSV instructions, the HS-level register does not apply, but > the VS-level register presumably does, though this is not mentioned > explicitly in the manual. However, it matches the behavior for MPV. > > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Alistair > --- > target/riscv/cpu_helper.c | 12 ++++++++---- > target/riscv/op_helper.c | 6 +++++- > 2 files changed, 13 insertions(+), 5 deletions(-) > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > index 6c42f9c6fd..0017ecbf37 100644 > --- a/target/riscv/cpu_helper.c > +++ b/target/riscv/cpu_helper.c > @@ -42,11 +42,16 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) > > /* All priv -> mmu_idx mapping are here */ > if (!ifetch) { > - if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) { > + uint64_t status = env->mstatus; > + > + if (mode == PRV_M && get_field(status, MSTATUS_MPRV)) { > mode = get_field(env->mstatus, MSTATUS_MPP); > virt = get_field(env->mstatus, MSTATUS_MPV); > + if (virt) { > + status = env->vsstatus; > + } > } > - if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) { > + if (mode == PRV_S && get_field(status, MSTATUS_SUM)) { > mode = MMUIdx_S_SUM; > } > } > @@ -838,8 +843,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, > } > widened = 2; > } > - /* status.SUM will be ignored if execute on background */ > - sum = mmuidx_sum(mmu_idx) || use_background || is_debug; > + sum = mmuidx_sum(mmu_idx) || is_debug; > switch (vm) { > case VM_1_10_SV32: > levels = 2; ptidxbits = 10; ptesize = 4; break; > diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c > index db7252e09d..93d4ae8b3e 100644 > --- a/target/riscv/op_helper.c > +++ b/target/riscv/op_helper.c > @@ -437,7 +437,11 @@ static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra) > riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra); > } > > - return get_field(env->hstatus, HSTATUS_SPVP) | MMU_2STAGE_BIT; > + int mode = get_field(env->hstatus, HSTATUS_SPVP); > + if (!x && mode == PRV_S && get_field(env->vsstatus, MSTATUS_SUM)) { > + mode = MMUIdx_S_SUM; > + } > + return mode | MMU_2STAGE_BIT; > } > > target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr) > -- > 2.34.1 > >
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 6c42f9c6fd..0017ecbf37 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -42,11 +42,16 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) /* All priv -> mmu_idx mapping are here */ if (!ifetch) { - if (mode == PRV_M && get_field(env->mstatus, MSTATUS_MPRV)) { + uint64_t status = env->mstatus; + + if (mode == PRV_M && get_field(status, MSTATUS_MPRV)) { mode = get_field(env->mstatus, MSTATUS_MPP); virt = get_field(env->mstatus, MSTATUS_MPV); + if (virt) { + status = env->vsstatus; + } } - if (mode == PRV_S && get_field(env->mstatus, MSTATUS_SUM)) { + if (mode == PRV_S && get_field(status, MSTATUS_SUM)) { mode = MMUIdx_S_SUM; } } @@ -838,8 +843,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical, } widened = 2; } - /* status.SUM will be ignored if execute on background */ - sum = mmuidx_sum(mmu_idx) || use_background || is_debug; + sum = mmuidx_sum(mmu_idx) || is_debug; switch (vm) { case VM_1_10_SV32: levels = 2; ptidxbits = 10; ptesize = 4; break; diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index db7252e09d..93d4ae8b3e 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -437,7 +437,11 @@ static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra) riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra); } - return get_field(env->hstatus, HSTATUS_SPVP) | MMU_2STAGE_BIT; + int mode = get_field(env->hstatus, HSTATUS_SPVP); + if (!x && mode == PRV_S && get_field(env->vsstatus, MSTATUS_SUM)) { + mode = MMUIdx_S_SUM; + } + return mode | MMU_2STAGE_BIT; } target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
Table 9.5 "Effect of MPRV..." specifies that MPV=1 uses VS-level vsstatus.SUM instead of HS-level sstatus.SUM. For HLV/HSV instructions, the HS-level register does not apply, but the VS-level register presumably does, though this is not mentioned explicitly in the manual. However, it matches the behavior for MPV. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> --- target/riscv/cpu_helper.c | 12 ++++++++---- target/riscv/op_helper.c | 6 +++++- 2 files changed, 13 insertions(+), 5 deletions(-)