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
}