On 5/11/2026 4:13 AM, Zishun Yi wrote:
According to the RISC-V Privileged Manual: "The Sv32 page-based
virtual-memory scheme described in sv32 supports 34-bit physical
addresses for RV32, so the PMP scheme must support addresses wider than
XLEN for RV32."

However, the current QEMU implementation uses `target_ulong` (which
resolves to `uint32_t` on RV32) for PMP address variables.  When
shifting these addresses left (e.g., `this_addr << 2`), an integer
overflow occurs, truncating the high bits of the 34-bit physical
address.

Fix this issue by casting the `target_ulong` variables to `hwaddr`
before performing the left shift operation.

This issue was discovered and reported by SpecHunter, an AI-driven
architecture specification analysis tool.

Link:https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2472/qemu.txt
Signed-off-by: Zishun Yi <[email protected]>
---
  target/riscv/pmp.c | 6 +++---
  1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 5391caa59c7d..dfddafcbcb48 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -253,12 +253,12 @@ void pmp_update_rule_addr(CPURISCVState *env, uint32_t 
pmp_index)
              sa = ea = 0u;
              break;
          }
-        sa = prev_addr << 2; /* shift up from [xx:0] to [xx+2:2] */
-        ea = (this_addr << 2) - 1u;
+        sa = (hwaddr)prev_addr << 2; /* shift up from [xx:0] to [xx+2:2] */
+        ea = ((hwaddr)this_addr << 2) - 1u;


Instead of casting 'hwaddr' I'd rather change both to 'hwaddr' type.  The
new type suits both variables, and in fact pmp_decode_napot() expects a
hwaddr:

pmp_decode_napot(this_addr, &sa, &ea);



Thanks,
Daniel


          break;
case PMP_AMATCH_NA4:
-        sa = this_addr << 2; /* shift up from [xx:0] to [xx+2:2] */
+        sa = (hwaddr)this_addr << 2; /* shift up from [xx:0] to [xx+2:2] */
          ea = (sa + 4u) - 1u;
          break;


Reply via email to