mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-08 02:03:56 -06:00
target/riscv: Apply pointer masking for virtualized memory accesses
Signed-off-by: Alexey Baturo <baturo.alexey@gmail.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20250106102346.1100149-7-baturo.alexey@gmail.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
This commit is contained in:
parent
4d501a7a7f
commit
4d1600934a
5 changed files with 82 additions and 29 deletions
|
@ -777,6 +777,7 @@ bool riscv_cpu_is_32bit(RISCVCPU *cpu);
|
||||||
|
|
||||||
bool riscv_cpu_virt_mem_enabled(CPURISCVState *env);
|
bool riscv_cpu_virt_mem_enabled(CPURISCVState *env);
|
||||||
RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env);
|
RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env);
|
||||||
|
RISCVPmPmm riscv_pm_get_virt_pmm(CPURISCVState *env);
|
||||||
uint32_t riscv_pm_get_pmlen(RISCVPmPmm pmm);
|
uint32_t riscv_pm_get_pmlen(RISCVPmPmm pmm);
|
||||||
|
|
||||||
RISCVException riscv_csrr(CPURISCVState *env, int csrno,
|
RISCVException riscv_csrr(CPURISCVState *env, int csrno,
|
||||||
|
|
|
@ -263,6 +263,25 @@ RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RISCVPmPmm riscv_pm_get_virt_pmm(CPURISCVState *env)
|
||||||
|
{
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
int priv_mode = cpu_address_mode(env);
|
||||||
|
|
||||||
|
if (priv_mode == PRV_U) {
|
||||||
|
return get_field(env->hstatus, HSTATUS_HUPMM);
|
||||||
|
} else {
|
||||||
|
if (get_field(env->hstatus, HSTATUS_SPVP)) {
|
||||||
|
return get_field(env->henvcfg, HENVCFG_PMM);
|
||||||
|
} else {
|
||||||
|
return get_field(env->senvcfg, SENVCFG_PMM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return PMM_FIELD_DISABLED;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool riscv_cpu_virt_mem_enabled(CPURISCVState *env)
|
bool riscv_cpu_virt_mem_enabled(CPURISCVState *env)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
|
|
@ -145,4 +145,58 @@ static inline float16 check_nanbox_h(CPURISCVState *env, uint64_t f)
|
||||||
/* Our implementation of CPUClass::has_work */
|
/* Our implementation of CPUClass::has_work */
|
||||||
bool riscv_cpu_has_work(CPUState *cs);
|
bool riscv_cpu_has_work(CPUState *cs);
|
||||||
|
|
||||||
|
/* Zjpm addr masking routine */
|
||||||
|
static inline target_ulong adjust_addr_body(CPURISCVState *env,
|
||||||
|
target_ulong addr,
|
||||||
|
bool is_virt_addr)
|
||||||
|
{
|
||||||
|
RISCVPmPmm pmm = PMM_FIELD_DISABLED;
|
||||||
|
uint32_t pmlen = 0;
|
||||||
|
bool signext = false;
|
||||||
|
|
||||||
|
/* do nothing for rv32 mode */
|
||||||
|
if (riscv_cpu_mxl(env) == MXL_RV32) {
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get pmm field depending on whether addr is */
|
||||||
|
if (is_virt_addr) {
|
||||||
|
pmm = riscv_pm_get_virt_pmm(env);
|
||||||
|
} else {
|
||||||
|
pmm = riscv_pm_get_pmm(env);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if pointer masking is disabled, return original addr */
|
||||||
|
if (pmm == PMM_FIELD_DISABLED) {
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_virt_addr) {
|
||||||
|
signext = riscv_cpu_virt_mem_enabled(env);
|
||||||
|
}
|
||||||
|
addr = addr << pmlen;
|
||||||
|
pmlen = riscv_pm_get_pmlen(pmm);
|
||||||
|
|
||||||
|
/* sign/zero extend masked address by N-1 bit */
|
||||||
|
if (signext) {
|
||||||
|
addr = (target_long)addr >> pmlen;
|
||||||
|
} else {
|
||||||
|
addr = addr >> pmlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline target_ulong adjust_addr(CPURISCVState *env,
|
||||||
|
target_ulong addr)
|
||||||
|
{
|
||||||
|
return adjust_addr_body(env, addr, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline target_ulong adjust_addr_virt(CPURISCVState *env,
|
||||||
|
target_ulong addr)
|
||||||
|
{
|
||||||
|
return adjust_addr_body(env, addr, true);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -479,7 +479,7 @@ target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr)
|
||||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||||
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
|
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
|
||||||
|
|
||||||
return cpu_ldb_mmu(env, addr, oi, ra);
|
return cpu_ldb_mmu(env, adjust_addr_virt(env, addr), oi, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
target_ulong helper_hyp_hlv_hu(CPURISCVState *env, target_ulong addr)
|
target_ulong helper_hyp_hlv_hu(CPURISCVState *env, target_ulong addr)
|
||||||
|
@ -488,7 +488,7 @@ target_ulong helper_hyp_hlv_hu(CPURISCVState *env, target_ulong addr)
|
||||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||||
MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
|
MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
|
||||||
|
|
||||||
return cpu_ldw_mmu(env, addr, oi, ra);
|
return cpu_ldw_mmu(env, adjust_addr_virt(env, addr), oi, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
target_ulong helper_hyp_hlv_wu(CPURISCVState *env, target_ulong addr)
|
target_ulong helper_hyp_hlv_wu(CPURISCVState *env, target_ulong addr)
|
||||||
|
@ -497,7 +497,7 @@ target_ulong helper_hyp_hlv_wu(CPURISCVState *env, target_ulong addr)
|
||||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||||
MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
|
MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
|
||||||
|
|
||||||
return cpu_ldl_mmu(env, addr, oi, ra);
|
return cpu_ldl_mmu(env, adjust_addr_virt(env, addr), oi, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
target_ulong helper_hyp_hlv_d(CPURISCVState *env, target_ulong addr)
|
target_ulong helper_hyp_hlv_d(CPURISCVState *env, target_ulong addr)
|
||||||
|
@ -506,7 +506,7 @@ target_ulong helper_hyp_hlv_d(CPURISCVState *env, target_ulong addr)
|
||||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||||
MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
|
MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
|
||||||
|
|
||||||
return cpu_ldq_mmu(env, addr, oi, ra);
|
return cpu_ldq_mmu(env, adjust_addr_virt(env, addr), oi, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_hyp_hsv_b(CPURISCVState *env, target_ulong addr, target_ulong val)
|
void helper_hyp_hsv_b(CPURISCVState *env, target_ulong addr, target_ulong val)
|
||||||
|
@ -515,7 +515,7 @@ void helper_hyp_hsv_b(CPURISCVState *env, target_ulong addr, target_ulong val)
|
||||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||||
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
|
MemOpIdx oi = make_memop_idx(MO_UB, mmu_idx);
|
||||||
|
|
||||||
cpu_stb_mmu(env, addr, val, oi, ra);
|
cpu_stb_mmu(env, adjust_addr_virt(env, addr), val, oi, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_hyp_hsv_h(CPURISCVState *env, target_ulong addr, target_ulong val)
|
void helper_hyp_hsv_h(CPURISCVState *env, target_ulong addr, target_ulong val)
|
||||||
|
@ -524,7 +524,7 @@ void helper_hyp_hsv_h(CPURISCVState *env, target_ulong addr, target_ulong val)
|
||||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||||
MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
|
MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx);
|
||||||
|
|
||||||
cpu_stw_mmu(env, addr, val, oi, ra);
|
cpu_stw_mmu(env, adjust_addr_virt(env, addr), val, oi, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_hyp_hsv_w(CPURISCVState *env, target_ulong addr, target_ulong val)
|
void helper_hyp_hsv_w(CPURISCVState *env, target_ulong addr, target_ulong val)
|
||||||
|
@ -533,7 +533,7 @@ void helper_hyp_hsv_w(CPURISCVState *env, target_ulong addr, target_ulong val)
|
||||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||||
MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
|
MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx);
|
||||||
|
|
||||||
cpu_stl_mmu(env, addr, val, oi, ra);
|
cpu_stl_mmu(env, adjust_addr_virt(env, addr), val, oi, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
void helper_hyp_hsv_d(CPURISCVState *env, target_ulong addr, target_ulong val)
|
void helper_hyp_hsv_d(CPURISCVState *env, target_ulong addr, target_ulong val)
|
||||||
|
@ -542,7 +542,7 @@ void helper_hyp_hsv_d(CPURISCVState *env, target_ulong addr, target_ulong val)
|
||||||
int mmu_idx = check_access_hlsv(env, false, ra);
|
int mmu_idx = check_access_hlsv(env, false, ra);
|
||||||
MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
|
MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx);
|
||||||
|
|
||||||
cpu_stq_mmu(env, addr, val, oi, ra);
|
cpu_stq_mmu(env, adjust_addr_virt(env, addr), val, oi, ra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -105,27 +105,6 @@ static inline uint32_t vext_max_elems(uint32_t desc, uint32_t log2_esz)
|
||||||
return scale < 0 ? vlenb >> -scale : vlenb << scale;
|
return scale < 0 ? vlenb >> -scale : vlenb << scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline target_ulong adjust_addr(CPURISCVState *env, target_ulong addr)
|
|
||||||
{
|
|
||||||
if (riscv_cpu_mxl(env) == MXL_RV32) {
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
RISCVPmPmm pmm = riscv_pm_get_pmm(env);
|
|
||||||
if (pmm == PMM_FIELD_DISABLED) {
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
int pmlen = riscv_pm_get_pmlen(pmm);
|
|
||||||
bool signext = riscv_cpu_virt_mem_enabled(env);
|
|
||||||
addr = addr << pmlen;
|
|
||||||
/* sign/zero extend masked address by N-1 bit */
|
|
||||||
if (signext) {
|
|
||||||
addr = (target_long)addr >> pmlen;
|
|
||||||
} else {
|
|
||||||
addr = addr >> pmlen;
|
|
||||||
}
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function checks watchpoint before real load operation.
|
* This function checks watchpoint before real load operation.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue