@samitouri / QOSamiQemu / commits / b2e874bfec

target/riscv: fix stale ptshift and base on page walk restart

When the atomic compare-and-swap for updating A/D bits in the page table entry fails due to a concurrent PTE modification by another vCPU, get_physical_address() jumps to the 'restart' label to re-walk the page table from the root. However, neither 'ptshift' nor 'base' are re-initialized before the restart. After the walk completes, ptshift has been decremented to its final value and base has been overwritten with an inner PTE PPN. On goto restart, the for loop resets i=0 but ptshift and base remain stale, causing the restarted walk to compute incorrect PTE addresses. In an SMP guest with MTTCG and Svadu active, this can result in incorrect physical address mappings or guest crashes. Fix by saving the root base address and re-initializing both ptshift and base on each restart. Fixes: 0c3e702aca ("RISC-V CPU Helpers") Signed-off-by: Sebastián Alba Vives <sebasjosue84@gmail.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260401053853.10473-1-sebasjosue84@gmail.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Sebastián Alba Vives committed Mar 31, 2026 at 23:38 UTC b2e874bfec59f6150b49a70df0529458efa0726b
1 file changed +4 -1
target/riscv/cpu_helper.c
+4 -1
@@ -1316,12 +1316,15 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
1316 adue = adue && (env->henvcfg & HENVCFG_ADUE);
1317 }
1318
1319 - int ptshift = (levels - 1) * ptidxbits;
1319 + int ptshift;
1320 target_ulong pte;
1321 hwaddr pte_addr;
1322 + const hwaddr base_root = base;
1323 int i;
1324
1325 restart:
1326 + ptshift = (levels - 1) * ptidxbits;
1327 + base = base_root;
1328 for (i = 0; i < levels; i++, ptshift -= ptidxbits) {
1329 target_ulong idx;
1330 if (i == 0) {