target/riscv: Handle HLV, HSV via helpers

Implement these instructions via helpers, in expectation
of determining the mmu_idx to use at runtime.  This allows
the permission check to also be moved out of line, which
allows HLSX to be removed from TB_FLAGS.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
Tested-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Message-Id: <20230325105429.1142530-11-richard.henderson@linaro.org>
Message-Id: <20230412114333.118895-11-richard.henderson@linaro.org>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
Richard Henderson 2023-04-12 13:43:18 +02:00 committed by Alistair Francis
parent a7f112c5fd
commit 0f58cbbeea
6 changed files with 169 additions and 113 deletions

View file

@ -427,6 +427,91 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
helper_hyp_tlb_flush(env);
}
static int check_access_hlsv(CPURISCVState *env, bool x, uintptr_t ra)
{
if (env->priv == PRV_M) {
/* always allowed */
} else if (env->virt_enabled) {
riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, ra);
} else if (env->priv == PRV_U && !get_field(env->hstatus, HSTATUS_HU)) {
riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
}
return cpu_mmu_index(env, x) | MMU_HYP_ACCESS_BIT;
}
target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
{
uintptr_t ra = GETPC();
int mmu_idx = check_access_hlsv(env, false, ra);
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
return cpu_ldb_mmu(env, addr, oi, ra);
}
target_ulong helper_hyp_hlv_hu(CPURISCVState *env, target_ulong addr)
{
uintptr_t ra = GETPC();
int mmu_idx = check_access_hlsv(env, false, ra);
MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
return cpu_ldw_mmu(env, addr, oi, ra);
}
target_ulong helper_hyp_hlv_wu(CPURISCVState *env, target_ulong addr)
{
uintptr_t ra = GETPC();
int mmu_idx = check_access_hlsv(env, false, ra);
MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
return cpu_ldl_mmu(env, addr, oi, ra);
}
target_ulong helper_hyp_hlv_d(CPURISCVState *env, target_ulong addr)
{
uintptr_t ra = GETPC();
int mmu_idx = check_access_hlsv(env, false, ra);
MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
return cpu_ldq_mmu(env, addr, oi, ra);
}
void helper_hyp_hsv_b(CPURISCVState *env, target_ulong addr, target_ulong val)
{
uintptr_t ra = GETPC();
int mmu_idx = check_access_hlsv(env, false, ra);
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
cpu_stb_mmu(env, addr, val, oi, ra);
}
void helper_hyp_hsv_h(CPURISCVState *env, target_ulong addr, target_ulong val)
{
uintptr_t ra = GETPC();
int mmu_idx = check_access_hlsv(env, false, ra);
MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
cpu_stw_mmu(env, addr, val, oi, ra);
}
void helper_hyp_hsv_w(CPURISCVState *env, target_ulong addr, target_ulong val)
{
uintptr_t ra = GETPC();
int mmu_idx = check_access_hlsv(env, false, ra);
MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
cpu_stl_mmu(env, addr, val, oi, ra);
}
void helper_hyp_hsv_d(CPURISCVState *env, target_ulong addr, target_ulong val)
{
uintptr_t ra = GETPC();
int mmu_idx = check_access_hlsv(env, false, ra);
MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
cpu_stq_mmu(env, addr, val, oi, ra);
}
/*
* TODO: These implementations are not quite correct. They perform the
* access using execute permission just fine, but the final PMP check
@ -434,20 +519,22 @@ void helper_hyp_gvma_tlb_flush(CPURISCVState *env)
* a fair fraction of cputlb.c, fixing this requires adding new mmu_idx
* which would imply that exact check in tlb_fill.
*/
target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong address)
target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong addr)
{
int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
uintptr_t ra = GETPC();
int mmu_idx = check_access_hlsv(env, true, ra);
MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
return cpu_ldw_code_mmu(env, address, oi, GETPC());
return cpu_ldw_code_mmu(env, addr, oi, GETPC());
}
target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong address)
target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong addr)
{
int mmu_idx = cpu_mmu_index(env, true) | MMU_HYP_ACCESS_BIT;
uintptr_t ra = GETPC();
int mmu_idx = check_access_hlsv(env, true, ra);
MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
return cpu_ldl_code_mmu(env, address, oi, GETPC());
return cpu_ldl_code_mmu(env, addr, oi, ra);
}
#endif /* !CONFIG_USER_ONLY */