riscv_pmu_incr_ctr() sets OF and LCOFIP on wrap even when Sscofpmf is
disabled. Use the shared overflow helper to require Sscofpmf and suppress
notifications while OF is set without stopping the counter.

Test DTLB overflow with Sscofpmf enabled and disabled, including
notification suppression and continued counting.

Fixes: 14664483457b ("target/riscv: Add sscofpmf extension support")
Signed-off-by: TANG Tiancheng <[email protected]>
---
 target/riscv/tcg/pmu.c                      |   6 +-
 tests/tcg/riscv64/Makefile.softmmu-target   |  10 +++
 tests/tcg/riscv64/sscofpmf-event-overflow.S | 103 ++++++++++++++++++++++++++++
 3 files changed, 114 insertions(+), 5 deletions(-)

diff --git a/target/riscv/tcg/pmu.c b/target/riscv/tcg/pmu.c
index 
16942e53489cd5a2d2dd055fdffef07d04d59465..2f600c5a0fc2d7ba380ef34f89af6366e3e27884
 100644
--- a/target/riscv/tcg/pmu.c
+++ b/target/riscv/tcg/pmu.c
@@ -448,11 +448,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum 
riscv_pmu_event_idx event_idx)
         counter = &env->pmu_ctrs[ctr_idx];
         if (counter->mhpmcounter_val == max_val) {
             counter->mhpmcounter_val = 0;
-            /* Generate interrupt only if OF bit is clear */
-            if (!(env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_OF)) {
-                env->mhpmevent_val[ctr_idx] |= MHPMEVENT_BIT_OF;
-                riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1));
-            }
+            riscv_pmu_set_overflow(env, ctr_idx);
         } else {
             counter->mhpmcounter_val++;
         }
diff --git a/tests/tcg/riscv64/Makefile.softmmu-target 
b/tests/tcg/riscv64/Makefile.softmmu-target
index 
5a94a90c40f838e4e78268f8cedc480d5e2ff3bf..b100f7a9ddf8e31fb104aa834b28aa64fc31f50e
 100644
--- a/tests/tcg/riscv64/Makefile.softmmu-target
+++ b/tests/tcg/riscv64/Makefile.softmmu-target
@@ -69,6 +69,16 @@ TESTS += sscofpmf-overflow
 run-sscofpmf-overflow: sscofpmf-overflow
        $(call run-test, $<, $(QEMU) -cpu max -icount shift=0 $(QEMU_OPTS)$<)
 
+sscofpmf-event-overflow-off: sscofpmf-event-overflow.S $(LINK_SCRIPT)
+       $(CC) $(CFLAGS) -DEXPECT_SSCOFPMF=0 $< -Wa,--noexecstack -c -o [email protected]
+       $(LD) $(LDFLAGS) [email protected] -o $@
+
+TESTS += sscofpmf-event-overflow sscofpmf-event-overflow-off
+run-sscofpmf-event-overflow: sscofpmf-event-overflow
+       $(call run-test, $<, $(QEMU) -cpu max $(QEMU_OPTS)$<)
+run-sscofpmf-event-overflow-off: sscofpmf-event-overflow-off
+       $(call run-test, $<, $(QEMU) -cpu max$(COMMA)sscofpmf=false 
$(QEMU_OPTS)$<)
+
 TESTS += sscofpmf-cycle-overflow
 run-sscofpmf-cycle-overflow: sscofpmf-cycle-overflow
        $(call run-test, $<, $(QEMU) -cpu max -icount shift=3 $(QEMU_OPTS)$<)
diff --git a/tests/tcg/riscv64/sscofpmf-event-overflow.S 
b/tests/tcg/riscv64/sscofpmf-event-overflow.S
new file mode 100644
index 
0000000000000000000000000000000000000000..5bbcb060ae87124349151a14c6db815755c6e58d
--- /dev/null
+++ b/tests/tcg/riscv64/sscofpmf-event-overflow.S
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* Non-fixed event overflow with and without Sscofpmf. */
+
+#ifndef EXPECT_SSCOFPMF
+#define EXPECT_SSCOFPMF 1
+#endif
+
+       .option norvc
+       .option norelax
+
+       .text
+       .global _start
+_start:
+       /* Unexpected exceptions report the current check number. */
+       li      t4, 1
+       lla     t0, exit
+       csrw    mtvec, t0
+       csrw    mie, zero
+       csrw    mip, zero
+       csrw    mcountinhibit, zero
+       csrw    0x323, zero             /* mhpmevent3 */
+       li      t0, -1
+       csrw    0xb03, t0               /* mhpmcounter3 */
+       li      t0, 0x10019             /* DTLB read miss */
+       csrw    0x323, t0
+
+       /* One load after flushing the TLB must wrap the counter to zero. */
+       sfence.vma
+       lla     t0, first_page
+       lw      t1, 0(t0)
+       csrr    t0, 0xb03
+       bnez    t0, exit
+
+       /* Only Sscofpmf turns that wrap into OF and LCOFIP. */
+       li      t4, 2
+       csrr    t0, 0x323
+       srli    t0, t0, 63
+       li      t1, EXPECT_SSCOFPMF
+       bne     t0, t1, exit
+       li      t4, 3
+       csrr    t0, mip
+       srli    t0, t0, 13
+       andi    t0, t0, 1
+       bne     t0, t1, exit
+
+       /* Clearing LCOFIP alone must not re-enable overflow notification. */
+       li      t0, 1 << 13
+       csrc    mip, t0
+       li      t0, -1
+       csrw    0xb03, t0
+       sfence.vma
+       lla     t0, second_page
+       lw      t1, 0(t0)
+       li      t4, 4
+       csrr    t0, 0xb03
+       bnez    t0, exit
+       li      t4, 5
+       csrr    t0, 0x323
+       srli    t0, t0, 63
+       li      t1, EXPECT_SSCOFPMF
+       bne     t0, t1, exit
+       li      t4, 6
+       csrr    t0, mip
+       li      t1, 1 << 13
+       and     t0, t0, t1
+       bnez    t0, exit
+
+       /* Overflow notification must not stop event counting. */
+       sfence.vma
+       lla     t0, third_page
+       lw      t1, 0(t0)
+       li      t4, 7
+       csrr    t0, 0xb03
+       li      t1, 1
+       bne     t0, t1, exit
+       li      t4, 0
+
+exit:
+       lla     a1, semiargs
+       li      t0, 0x20026             /* ADP_Stopped_ApplicationExit */
+       sd      t0, 0(a1)
+       sd      t4, 8(a1)
+       li      a0, 0x20                /* TARGET_SYS_EXIT_EXTENDED */
+       .balign 16
+       slli    zero, zero, 0x1f
+       ebreak
+       srai    zero, zero, 0x7
+       j       .
+
+       .data
+       .balign 4096
+first_page:
+       .word   0
+       .balign 4096
+second_page:
+       .word   0
+       .balign 4096
+third_page:
+       .word   0
+       .balign 16
+semiargs:
+       .space  16

-- 
2.43.0


Reply via email to