@samitouri / QOSamiQemu / commits / fabf2446e7

target/riscv: Fix pointer masking translation mode check bug

When running with virtualization in VS/VU mode, or when executing the virtual-machine load/store instructions (HLV.* and HSV.*), the type of address that determines which pointer masking rules apply should be checked against vsatp rather than satp. As a result, sign extension also applies to the virtual-machine load/store instructions. Signed-off-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Radim Krčmář <rkrcmar@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260421093715.2995067-7-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Frank Chang committed Apr 21, 2026 at 17:37 UTC fabf2446e7fff1bc4f0bef6fef197f9ad894decb
4 files changed +19 -10
target/riscv/cpu.h
+1 -1
@@ -888,7 +888,7 @@ static inline uint32_t vext_get_vlmax(uint32_t vlenb, uint32_t vsew,
888
889 bool riscv_cpu_is_32bit(RISCVCPU *cpu);
890
891 -bool riscv_cpu_virt_mem_enabled(CPURISCVState *env);
891 +bool riscv_cpu_virt_mem_enabled(CPURISCVState *env, bool is_vm_ldst);
892 RISCVPmPmm riscv_pm_get_pmm(CPURISCVState *env);
893 RISCVPmPmm riscv_pm_get_vm_ldst_pmm(CPURISCVState *env);
894 uint32_t riscv_pm_get_pmlen(RISCVPmPmm pmm);
target/riscv/cpu_helper.c
+15 -4
@@ -240,16 +240,27 @@ RISCVPmPmm riscv_pm_get_vm_ldst_pmm(CPURISCVState *env)
240 #endif
241 }
242
243 -bool riscv_cpu_virt_mem_enabled(CPURISCVState *env)
243 +bool riscv_cpu_virt_mem_enabled(CPURISCVState *env, bool is_vm_ldst)
244 {
245 #ifndef CONFIG_USER_ONLY
246 int satp_mode = 0;
247 - int priv_mode = cpu_address_mode(env);
247 + uint64_t satp;
248 + int priv_mode;
249 + bool virt = false;
250 +
251 + if (!is_vm_ldst) {
252 + riscv_cpu_eff_priv(env, &priv_mode, &virt);
253 + } else {
254 + priv_mode = get_field(env->hstatus, HSTATUS_SPVP);
255 + virt = true;
256 + }
257 +
258 + satp = virt ? env->vsatp : env->satp;
259
260 if (riscv_cpu_mxl(env) == MXL_RV32) {
250 - satp_mode = get_field(env->satp, SATP32_MODE);
261 + satp_mode = get_field(satp, SATP32_MODE);
262 } else {
252 - satp_mode = get_field(env->satp, SATP64_MODE);
263 + satp_mode = get_field(satp, SATP64_MODE);
264 }
265
266 return ((satp_mode != VM_1_10_MBARE) && (priv_mode != PRV_M));
target/riscv/internals.h
+1 -3
@@ -219,9 +219,7 @@ static inline target_ulong adjust_addr_body(CPURISCVState *env,
219 return addr;
220 }
221
222 - if (!is_virt_addr) {
223 - signext = riscv_cpu_virt_mem_enabled(env);
224 - }
222 + signext = riscv_cpu_virt_mem_enabled(env, is_virt_addr);
223 pmlen = riscv_pm_get_pmlen(pmm);
224 addr = addr << pmlen;
225
target/riscv/tcg/tcg-cpu.c
+2 -2
@@ -105,7 +105,7 @@ static TCGTBCPUState riscv_get_tb_cpu_state(CPUState *cs)
105 RISCVExtStatus fs, vs;
106 uint32_t flags = 0;
107 uint64_t ext_flags = 0;
108 - bool pm_signext = riscv_cpu_virt_mem_enabled(env);
108 + bool pm_signext = riscv_cpu_virt_mem_enabled(env, false);
109
110 if (cpu->cfg.ext_zve32x) {
111 /*
@@ -260,7 +260,7 @@ static vaddr riscv_pointer_wrap(CPUState *cs, int mmu_idx,
260 return result;
261 }
262
263 - pm_signext = riscv_cpu_virt_mem_enabled(env);
263 + pm_signext = riscv_cpu_virt_mem_enabled(env, false);
264 if (pm_signext) {
265 return sextract64(result, 0, 64 - pm_len);
266 }