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]>
---
v2: add a missing space after the Link tag clon

 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;
         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;
 
-- 
2.51.2


Reply via email to