qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v1] s390x/tcg: MVCL: Exit to main loop if there are pending inter


From: David Hildenbrand
Subject: [PATCH v1] s390x/tcg: MVCL: Exit to main loop if there are pending interrupts
Date: Tue, 1 Oct 2019 20:16:55 +0200

MVCL is interruptible and we should check for interrupts and process
them after writing back the variables to the registers.

I can see both checks triggering. Most of them pass the first check,
however, sometimes also the second check strikes and an interrupt gets
delivered. (I assume pending interrupts that were not deliverable when
injected but are now deliverable)

When booting Fedora 30, I can see a handful of these exits and it seems
to work reliable. (it never get's triggered via EXECUTE, though)

Suggested-by: Richard Henderson <address@hidden>
Signed-off-by: David Hildenbrand <address@hidden>
---
 target/s390x/mem_helper.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
index 4254548935..96f0728cb7 100644
--- a/target/s390x/mem_helper.c
+++ b/target/s390x/mem_helper.c
@@ -1005,6 +1005,24 @@ static inline uint32_t do_mvcl(CPUS390XState *env,
     return *destlen ? 3 : cc;
 }
 
+static inline bool should_interrupt_instruction(CPUState *cs)
+{
+    /*
+     * Something asked us to stop executing chained TBs, e.g.,
+     * cpu_interrupt() or cpu_exit().
+     */
+    if ((int32_t)atomic_read(&cpu_neg(cs)->icount_decr.u32) < 0) {
+        return true;
+    }
+
+    /* We have a deliverable interrupt pending. */
+    if ((atomic_read(&cs->interrupt_request) & CPU_INTERRUPT_HARD) &&
+        s390_cpu_has_int(S390_CPU(cs))) {
+        return true;
+    }
+    return false;
+}
+
 /* move long */
 uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, uint32_t r2)
 {
@@ -1015,6 +1033,7 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, 
uint32_t r2)
     uint64_t srclen = env->regs[r2 + 1] & 0xffffff;
     uint64_t src = get_address(env, r2);
     uint8_t pad = env->regs[r2 + 1] >> 24;
+    CPUState *cs = env_cpu(env);
     S390Access srca, desta;
     uint32_t cc, cur_len;
 
@@ -1065,7 +1084,14 @@ uint32_t HELPER(mvcl)(CPUS390XState *env, uint32_t r1, 
uint32_t r2)
         env->regs[r1 + 1] = deposit64(env->regs[r1 + 1], 0, 24, destlen);
         set_address_zero(env, r1, dest);
 
-        /* TODO: Deliver interrupts. */
+        /*
+         * MVCL is interruptible. Check if there is any irq, and if so,
+         * return to the main loop where we can process it. In case we
+         * don't deliver an interrupt, we'll end up back in this handler.
+         */
+        if (unlikely(should_interrupt_instruction(cs))) {
+            cpu_loop_exit_restore(cs, ra);
+        }
     }
     return cc;
 }
-- 
2.21.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]