riscv_cpu_update_mip() was called with a zero mask only to re-poll
interrupts after updating env->vstime_irq, where the VS timer keeps
VSTIP (see 14cb78bfaf4 "target/riscv: Don't clear mask in
riscv_cpu_update_mip() for VSTIP"). Move that re-poll to
riscv_accel_set_irq(), which now calls riscv_cpu_interrupt() directly
for the zero-mask case, and keep the early return for the no-op VSTIP
update.

No caller passes a zero mask anymore, so document @mask as non-zero
and assert it.

AI-used-for: code (prototype)
Signed-off-by: Philippe Mathieu-Daudé <[email protected]>
---
 target/riscv/cpu.h            |  2 +-
 target/riscv/tcg/cpu_helper.c |  6 +++++-
 target/riscv/time_helper.c    | 11 ++++++++++-
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index ad731bf5d34..6173360e407 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -694,7 +694,7 @@ uint64_t riscv_cpu_get_mip(const CPURISCVState *env);
 /**
  * riscv_cpu_update_mip:
  * @env: CPURISCVState
- * @mask: Mask of the MIP bits to update
+ * @mask: Mask of the MIP bits to update (must be non-zero)
  * @value: New values for the bits set in @mask.
  *         Use BOOL_TO_MASK() for boolean values.
  *
diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c
index db7f2bd6de7..16b2c486934 100644
--- a/target/riscv/tcg/cpu_helper.c
+++ b/target/riscv/tcg/cpu_helper.c
@@ -579,8 +579,12 @@ uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t 
mask, uint64_t value)
 {
     uint64_t old;
 
+    assert(mask);
+
     /* No need to update mip for VSTIP */
-    mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 : mask;
+    if (mask == MIP_VSTIP && env->vstime_irq) {
+        return riscv_cpu_get_mip(env);
+    }
 
     BQL_LOCK_GUARD();
 
diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index 29bbebb96fc..6bd917383e3 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -39,7 +39,16 @@ static void riscv_accel_set_irq(RISCVCPU *cpu,
         uint64_t mask = irq_or_mask;
         uint64_t value = level_or_value;
 
-        riscv_cpu_update_mip(&cpu->env, mask, value);
+        if (!mask) {
+            /*
+             * The VS timer keeps VSTIP in env->vstime_irq rather than
+             * in mip, so callers pass a zero mask only to re-poll
+             * interrupts after updating it.
+             */
+            riscv_cpu_interrupt(&cpu->env);
+        } else {
+            riscv_cpu_update_mip(&cpu->env, mask, value);
+        }
     }
 }
 
-- 
2.55.0


Reply via email to