check_zicbom_access() probes the cache block with MMU_DATA_LOAD and
returns early for any result other than TLB_INVALID_MASK.  This treats
TLB_MMIO as a successful load access.

For Zicbom, a TLB_MMIO result does not provide a RAM host pointer for the
cache block operation and should not be treated as a successful access.
Raise a store/AMO access fault instead of silently completing the CBO
instruction.

This fixes sv39_zicbom_exceptions_Smode.S, where cbo.clean/cbo.flush and
cbo.inval access a block mapped to a physical address without PMA
permissions.  Before this change, the CBO instruction completed and the
following addi was executed.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/3501
Signed-off-by: ZhengXiang Qin <[email protected]>
---
 target/riscv/op_helper.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 81873014cb..6c9bd5c102 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -218,6 +218,7 @@ static void check_zicbom_access(CPURISCVState *env,
     void *phost;
     int ret;
 
+    target_ulong fault_addr = address;
     /* Mask off low-bits to align-down to the cache-block. */
     address &= ~(cbomlen - 1);
 
@@ -235,6 +236,10 @@ static void check_zicbom_access(CPURISCVState *env,
      */
     ret = probe_access_flags(env, address, cbomlen, MMU_DATA_LOAD,
                              mmu_idx, true, &phost, ra);
+    if (ret == TLB_MMIO) {
+        env->badaddr = fault_addr;
+        riscv_raise_exception(env, RISCV_EXCP_STORE_AMO_ACCESS_FAULT, ra);
+    }
     if (ret != TLB_INVALID_MASK) {
         /* Success: readable */
         return;
-- 
2.43.0


Reply via email to