From 4d1600934a6c0fb617ffd4852fd54dfdd3eda35b Mon Sep 17 00:00:00 2001 From: Alexey Baturo <baturo.alexey@gmail.com> Date: Mon, 6 Jan 2025 13:23:45 +0300 Subject: [PATCH] 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> --- target/riscv/cpu.h | 1 + target/riscv/cpu_helper.c | 19 +++++++++++++ target/riscv/internals.h | 54 ++++++++++++++++++++++++++++++++++++ target/riscv/op_helper.c | 16 +++++------ target/riscv/vector_helper.c | 21 -------------- 5 files changed, 82 insertions(+), 29 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index f22e43c662..5e7152200f 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -777,6 +777,7 @@ bool riscv_cpu_is_32bit(RISCVCPU *cpu); bool riscv_cpu_virt_mem_enabled(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); RISCVException riscv_csrr(CPURISCVState *env, int csrno, diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 8728541b99..2e307e4ea5 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -263,6 +263,25 @@ RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env) #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) { #ifndef CONFIG_USER_ONLY diff --git a/target/riscv/internals.h b/target/riscv/internals.h index 76934eaa7b..67291933f8 100644 --- a/target/riscv/internals.h +++ b/target/riscv/internals.h @@ -145,4 +145,58 @@ static inline float16 check_nanbox_h(CPURISCVState *env, uint64_t f) /* Our implementation of CPUClass::has_work */ 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 diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 29de8eb43d..952ef8b3ec 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -479,7 +479,7 @@ target_ulong helper_hyp_hlv_bu(CPURISCVState *env, target_ulong addr) 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); + return cpu_ldb_mmu(env, adjust_addr_virt(env, addr), oi, ra); } 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); 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) @@ -497,7 +497,7 @@ target_ulong helper_hyp_hlv_wu(CPURISCVState *env, target_ulong addr) 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); + return cpu_ldl_mmu(env, adjust_addr_virt(env, addr), oi, ra); } 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); 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) @@ -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); 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) @@ -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); 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) @@ -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); 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) @@ -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); 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); } /* diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 0eea124b66..5386e3b97c 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -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; } -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. * -- 2.30.2