diff mbox series

[v1,06/27] s390x/tcg: injection of emergency signals and extarnal calls

Message ID 20170918160012.4317-7-david@redhat.com
State New
Headers show
Series s390x: SMP for TCG (+ cleanups) | expand

Commit Message

David Hildenbrand Sept. 18, 2017, 3:59 p.m. UTC
Preparation for new TCG SIGP code. Especially also prepare for
indicating that another external call is already pending.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/cpu.h         |  8 +++++++-
 target/s390x/excp_helper.c | 14 ++++++++++++++
 target/s390x/internal.h    |  2 ++
 target/s390x/interrupt.c   | 26 ++++++++++++++++++++++++++
 4 files changed, 49 insertions(+), 1 deletion(-)

Comments

David Hildenbrand Sept. 25, 2017, 1:16 p.m. UTC | #1
> @@ -248,6 +249,19 @@ static void do_ext_interrupt(CPUS390XState *env)
>          lowcore->ext_int_code = cpu_to_be16(EXT_CPU_TIMER);
>          lowcore->cpu_addr = 0;
>          env->pending_int &= ~INTERRUPT_EXT_CPU_TIMER;
> +    } else if (env->pending_int & INTERRUPT_EMERGENCY_SIGNAL) {
> +        lowcore->ext_int_code = cpu_to_be16(EXT_EMERGENCY);
> +        cpu_addr = find_first_bit(env->emergency_signals, S390_MAX_CPUS);
> +        g_assert(cpu_addr < S390_MAX_CPUS);
> +        lowcore->cpu_addr = cpu_to_be16(cpu_addr);
> +        clear_bit(cpu_addr, env->emergency_signals);
> +        if (bitmap_empty(env->emergency_signals, max_cpus)) {
> +            env->pending_int &= ~INTERRUPT_EMERGENCY_SIGNAL;
> +        }
> +    } else if (env->pending_int & INTERRUPT_EXTERNAL_CALL) {
> +        lowcore->ext_int_code = cpu_to_be16(EXT_EXTERNAL_CALL);
> +        lowcore->cpu_addr = cpu_to_be16(env->external_call_addr);
> +        env->pending_int &= ~INTERRUPT_EXTERNAL_CALL;

The priority of the interrupts is still wrong and we don't check for the
subclass-mask bits. Will fix this.
diff mbox series

Patch

diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
index d4e2aa2f24..857af21d06 100644
--- a/target/s390x/cpu.h
+++ b/target/s390x/cpu.h
@@ -132,6 +132,8 @@  struct CPUS390XState {
     MchkQueue mchk_queue[MAX_MCHK_QUEUE];
 
     int pending_int;
+    uint16_t external_call_addr;
+    DECLARE_BITMAP(emergency_signals, S390_MAX_CPUS);
     int ext_index;
     int io_index[8];
     int mchk_index;
@@ -405,9 +407,13 @@  static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
 #define INTERRUPT_EXT_FLOATING           (1 << 2)
 #define INTERRUPT_EXT_CPU_TIMER          (1 << 3)
 #define INTERRUPT_EXT_CLOCK_COMPARATOR   (1 << 4)
+#define INTERRUPT_EXTERNAL_CALL          (1 << 5)
+#define INTERRUPT_EMERGENCY_SIGNAL       (1 << 6)
 #define INTERRUPT_EXT                    (INTERRUPT_EXT_FLOATING | \
                                           INTERRUPT_EXT_CPU_TIMER | \
-                                          INTERRUPT_EXT_CLOCK_COMPARATOR)
+                                          INTERRUPT_EXT_CLOCK_COMPARATOR | \
+                                          INTERRUPT_EXTERNAL_CALL | \
+                                          INTERRUPT_EMERGENCY_SIGNAL)
 
 /* Program Status Word.  */
 #define S390_PSWM_REGNUM 0
diff --git a/target/s390x/excp_helper.c b/target/s390x/excp_helper.c
index 46d015f260..ff257ba72e 100644
--- a/target/s390x/excp_helper.c
+++ b/target/s390x/excp_helper.c
@@ -231,6 +231,7 @@  static void do_ext_interrupt(CPUS390XState *env)
 {
     S390CPU *cpu = s390_env_get_cpu(env);
     uint64_t mask, addr;
+    uint16_t cpu_addr;
     LowCore *lowcore;
     ExtQueue *q;
 
@@ -248,6 +249,19 @@  static void do_ext_interrupt(CPUS390XState *env)
         lowcore->ext_int_code = cpu_to_be16(EXT_CPU_TIMER);
         lowcore->cpu_addr = 0;
         env->pending_int &= ~INTERRUPT_EXT_CPU_TIMER;
+    } else if (env->pending_int & INTERRUPT_EMERGENCY_SIGNAL) {
+        lowcore->ext_int_code = cpu_to_be16(EXT_EMERGENCY);
+        cpu_addr = find_first_bit(env->emergency_signals, S390_MAX_CPUS);
+        g_assert(cpu_addr < S390_MAX_CPUS);
+        lowcore->cpu_addr = cpu_to_be16(cpu_addr);
+        clear_bit(cpu_addr, env->emergency_signals);
+        if (bitmap_empty(env->emergency_signals, max_cpus)) {
+            env->pending_int &= ~INTERRUPT_EMERGENCY_SIGNAL;
+        }
+    } else if (env->pending_int & INTERRUPT_EXTERNAL_CALL) {
+        lowcore->ext_int_code = cpu_to_be16(EXT_EXTERNAL_CALL);
+        lowcore->cpu_addr = cpu_to_be16(env->external_call_addr);
+        env->pending_int &= ~INTERRUPT_EXTERNAL_CALL;
     } else if (env->pending_int | INTERRUPT_EXT_FLOATING) {
         g_assert(env->ext_index >= 0);
         /*
diff --git a/target/s390x/internal.h b/target/s390x/internal.h
index ae4b27a574..15743ec40f 100644
--- a/target/s390x/internal.h
+++ b/target/s390x/internal.h
@@ -350,6 +350,8 @@  void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
                     uint64_t param64);
 void cpu_inject_clock_comparator(S390CPU *cpu);
 void cpu_inject_cpu_timer(S390CPU *cpu);
+void cpu_inject_emergency_signal(S390CPU *cpu, uint16_t src_cpu_addr);
+int cpu_inject_external_call(S390CPU *cpu, uint16_t src_cpu_addr);
 
 
 /* ioinst.c */
diff --git a/target/s390x/interrupt.c b/target/s390x/interrupt.c
index 4ba33c49cb..462316be8e 100644
--- a/target/s390x/interrupt.c
+++ b/target/s390x/interrupt.c
@@ -91,6 +91,32 @@  void cpu_inject_cpu_timer(S390CPU *cpu)
     cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
 }
 
+void cpu_inject_emergency_signal(S390CPU *cpu, uint16_t src_cpu_addr)
+{
+    CPUS390XState *env = &cpu->env;
+
+    g_assert(src_cpu_addr < S390_MAX_CPUS);
+    set_bit(src_cpu_addr, env->emergency_signals);
+
+    env->pending_int |= INTERRUPT_EMERGENCY_SIGNAL;
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
+}
+
+int cpu_inject_external_call(S390CPU *cpu, uint16_t src_cpu_addr)
+{
+    CPUS390XState *env = &cpu->env;
+
+    g_assert(src_cpu_addr < S390_MAX_CPUS);
+    if (env->pending_int & INTERRUPT_EXTERNAL_CALL) {
+        return -EBUSY;
+    }
+    env->external_call_addr = src_cpu_addr;
+
+    env->pending_int |= INTERRUPT_EXTERNAL_CALL;
+    cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
+    return 0;
+}
+
 static void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id,
                           uint16_t subchannel_number,
                           uint32_t io_int_parm, uint32_t io_int_word)