All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space
@ 2015-02-24 13:15 Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 01/10] s390x: introduce defines for SIGP condition codes Jens Freimann
                   ` (10 more replies)
  0 siblings, 11 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: Jens Freimann, qemu-devel

Cornelia, Alex, Christian,

these patches move large parts of SIGP handling from kernel
to user space.

Please note: This series needs a linux-headers sync with v4.0-rc1 
to work and should be applied only after Michael Tsirkin's series 
"virtio: pull headers from linux" was applied and a header sync
was done with the new scripts and header files. 

regards
Jens

David Hildenbrand (10):
  s390x: introduce defines for SIGP condition codes
  s390x/kvm: more details for SIGP handler with one destination vcpu
  s390x/kvm: pass the SIGP instruction parameter to the SIGP handler
  s390x/kvm: helper to set the SIGP status in SigpInfo
  s390x/kvm: trace all SIGP orders
  s390x/kvm: implement handling of new SIGP orders
  s390x/kvm: SIGP START is only applicable when STOPPED
  s390x: add function to deliver restart irqs
  s390x/kvm: deliver SIGP RESTART directly if stopped
  s390x/kvm: enable the new SIGP handling in user space

 target-s390x/cpu.c         |   2 +
 target-s390x/cpu.h         |  25 ++-
 target-s390x/helper.c      |  35 ++++-
 target-s390x/kvm.c         | 371 ++++++++++++++++++++++++++++++++++++++-------
 target-s390x/machine.c     |   5 +-
 target-s390x/misc_helper.c |   4 +-
 trace-events               |   1 +
 7 files changed, 372 insertions(+), 71 deletions(-)

-- 
2.1.4

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 01/10] s390x: introduce defines for SIGP condition codes
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
@ 2015-02-24 13:15 ` Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 02/10] s390x/kvm: more details for SIGP handler with one destination vcpu Jens Freimann
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: David Hildenbrand, Jens Freimann, qemu-devel

From: David Hildenbrand <dahi@linux.vnet.ibm.com>

This patch introduces defines for the SIGP condition codes and replaces all
occurrences of numeral condition codes with the new defines.

Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/cpu.h         |  9 ++++++++-
 target-s390x/kvm.c         | 14 +++++++-------
 target-s390x/misc_helper.c |  4 ++--
 3 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 2e2554c..e6edb72 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -856,6 +856,7 @@ struct sysib_322 {
 #define SK_F                    (0x1 << 3)
 #define SK_ACC_MASK             (0xf << 4)
 
+/* SIGP order codes */
 #define SIGP_SENSE             0x01
 #define SIGP_EXTERNAL_CALL     0x02
 #define SIGP_EMERGENCY         0x03
@@ -869,7 +870,13 @@ struct sysib_322 {
 #define SIGP_STORE_STATUS_ADDR 0x0e
 #define SIGP_SET_ARCH          0x12
 
-/* cpu status bits */
+/* SIGP condition codes */
+#define SIGP_CC_ORDER_CODE_ACCEPTED 0
+#define SIGP_CC_STATUS_STORED       1
+#define SIGP_CC_BUSY                2
+#define SIGP_CC_NOT_OPERATIONAL     3
+
+/* SIGP status bits */
 #define SIGP_STAT_EQUIPMENT_CHECK   0x80000000UL
 #define SIGP_STAT_INCORRECT_STATE   0x00000200UL
 #define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 6f2d5b4..91b0257 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -1165,37 +1165,37 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
     cpu_addr = env->regs[ipa1 & 0x0f];
     target_cpu = s390_cpu_addr2state(cpu_addr);
     if (target_cpu == NULL) {
-        cc = 3;    /* not operational */
+        cc = SIGP_CC_NOT_OPERATIONAL;
         goto out;
     }
 
     switch (order_code) {
     case SIGP_START:
         run_on_cpu(CPU(target_cpu), sigp_cpu_start, CPU(target_cpu));
-        cc = 0;
+        cc = SIGP_CC_ORDER_CODE_ACCEPTED;
         break;
     case SIGP_RESTART:
         run_on_cpu(CPU(target_cpu), sigp_cpu_restart, CPU(target_cpu));
-        cc = 0;
+        cc = SIGP_CC_ORDER_CODE_ACCEPTED;
         break;
     case SIGP_SET_ARCH:
         *statusreg &= 0xffffffff00000000UL;
         *statusreg |= SIGP_STAT_INVALID_PARAMETER;
-        cc = 1;   /* status stored */
+        cc = SIGP_CC_STATUS_STORED;
         break;
     case SIGP_INITIAL_CPU_RESET:
         run_on_cpu(CPU(target_cpu), sigp_initial_cpu_reset, CPU(target_cpu));
-        cc = 0;
+        cc = SIGP_CC_ORDER_CODE_ACCEPTED;
         break;
     case SIGP_CPU_RESET:
         run_on_cpu(CPU(target_cpu), sigp_cpu_reset, CPU(target_cpu));
-        cc = 0;
+        cc = SIGP_CC_ORDER_CODE_ACCEPTED;
         break;
     default:
         DPRINTF("KVM: unknown SIGP: 0x%x\n", order_code);
         *statusreg &= 0xffffffff00000000UL;
         *statusreg |= SIGP_STAT_INVALID_ORDER;
-        cc = 1;   /* status stored */
+        cc = SIGP_CC_STATUS_STORED;
         break;
     }
 
diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c
index ef9758a..bfd9809 100644
--- a/target-s390x/misc_helper.c
+++ b/target-s390x/misc_helper.c
@@ -427,7 +427,7 @@ uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
 uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
                       uint64_t cpu_addr)
 {
-    int cc = 0;
+    int cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 
     HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
                __func__, order_code, r1, cpu_addr);
@@ -461,7 +461,7 @@ uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
     default:
         /* unknown sigp */
         fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
-        cc = 3;
+        cc = SIGP_CC_NOT_OPERATIONAL;
     }
 
     return cc;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 02/10] s390x/kvm: more details for SIGP handler with one destination vcpu
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 01/10] s390x: introduce defines for SIGP condition codes Jens Freimann
@ 2015-02-24 13:15 ` Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 03/10] s390x/kvm: pass the SIGP instruction parameter to the SIGP handler Jens Freimann
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: David Hildenbrand, Jens Freimann, qemu-devel

From: David Hildenbrand <dahi@linux.vnet.ibm.com>

Whenever a sigp order is to be executed by a target vcpu, we use run_on_cpu().
As we have only one pointer to pass all data to these sigp handlers, let's
introduce the struct sigp_info and use it as a transport container.

All orders targeting a single vcpu are now  dispatched from a separate
handler. The destination vcpu is only valid for these orders and must not be
checked for SIGP SET ARCHITECTURE.

The sigp_info is filled with life in this new handler and used to pass the
information about the sigp order to the existing handlers. The cc is set
within these handlers.

Rename sigp_cpu_start() and sigp_cpu_restart() on the way to match the SIGP
order names (in order to avoid touching affected lines several times).

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/kvm.c | 153 +++++++++++++++++++++++++++++++----------------------
 1 file changed, 91 insertions(+), 62 deletions(-)

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 91b0257..ec17ac8 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -1098,110 +1098,139 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
     return r;
 }
 
-static void sigp_cpu_start(void *arg)
+typedef struct SigpInfo {
+    S390CPU *cpu;
+    int cc;
+    uint64_t *status_reg;
+} SigpInfo;
+
+static void sigp_start(void *arg)
 {
-    CPUState *cs = arg;
-    S390CPU *cpu = S390_CPU(cs);
+    SigpInfo *si = arg;
 
-    s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
-    DPRINTF("DONE: KVM cpu start: %p\n", &cpu->env);
+    s390_cpu_set_state(CPU_STATE_OPERATING, si->cpu);
+    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
+    DPRINTF("DONE: KVM cpu start: %p\n", &si->cpu->env);
 }
 
-static void sigp_cpu_restart(void *arg)
+static void sigp_restart(void *arg)
 {
-    CPUState *cs = arg;
-    S390CPU *cpu = S390_CPU(cs);
+    SigpInfo *si = arg;
     struct kvm_s390_irq irq = {
         .type = KVM_S390_RESTART,
     };
 
-    kvm_s390_vcpu_interrupt(cpu, &irq);
-    s390_cpu_set_state(CPU_STATE_OPERATING, cpu);
+    kvm_s390_vcpu_interrupt(si->cpu, &irq);
+    s390_cpu_set_state(CPU_STATE_OPERATING, si->cpu);
+    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 }
 
 int kvm_s390_cpu_restart(S390CPU *cpu)
 {
-    run_on_cpu(CPU(cpu), sigp_cpu_restart, CPU(cpu));
+    SigpInfo si = {
+        .cpu = cpu,
+    };
+
+    run_on_cpu(CPU(cpu), sigp_restart, &si);
     DPRINTF("DONE: KVM cpu restart: %p\n", &cpu->env);
     return 0;
 }
 
 static void sigp_initial_cpu_reset(void *arg)
 {
-    CPUState *cpu = arg;
-    S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
+    SigpInfo *si = arg;
+    CPUState *cs = CPU(si->cpu);
+    S390CPUClass *scc = S390_CPU_GET_CLASS(si->cpu);
 
-    cpu_synchronize_state(cpu);
-    scc->initial_cpu_reset(cpu);
-    cpu_synchronize_post_reset(cpu);
+    cpu_synchronize_state(cs);
+    scc->initial_cpu_reset(cs);
+    cpu_synchronize_post_reset(cs);
+    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 }
 
 static void sigp_cpu_reset(void *arg)
 {
-    CPUState *cpu = arg;
-    S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
+    SigpInfo *si = arg;
+    CPUState *cs = CPU(si->cpu);
+    S390CPUClass *scc = S390_CPU_GET_CLASS(si->cpu);
 
-    cpu_synchronize_state(cpu);
-    scc->cpu_reset(cpu);
-    cpu_synchronize_post_reset(cpu);
+    cpu_synchronize_state(cs);
+    scc->cpu_reset(cs);
+    cpu_synchronize_post_reset(cs);
+    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 }
 
-#define SIGP_ORDER_MASK 0x000000ff
-
-static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
+static int handle_sigp_single_dst(S390CPU *dst_cpu, uint8_t order,
+                                  uint64_t *status_reg)
 {
-    CPUS390XState *env = &cpu->env;
-    uint8_t order_code;
-    uint16_t cpu_addr;
-    S390CPU *target_cpu;
-    uint64_t *statusreg = &env->regs[ipa1 >> 4];
-    int cc;
-
-    cpu_synchronize_state(CPU(cpu));
-
-    /* get order code */
-    order_code = decode_basedisp_rs(env, run->s390_sieic.ipb) & SIGP_ORDER_MASK;
+    SigpInfo si = {
+        .cpu = dst_cpu,
+        .status_reg = status_reg,
+    };
 
-    cpu_addr = env->regs[ipa1 & 0x0f];
-    target_cpu = s390_cpu_addr2state(cpu_addr);
-    if (target_cpu == NULL) {
-        cc = SIGP_CC_NOT_OPERATIONAL;
-        goto out;
+    /* cpu available? */
+    if (dst_cpu == NULL) {
+        return SIGP_CC_NOT_OPERATIONAL;
     }
 
-    switch (order_code) {
+    switch (order) {
     case SIGP_START:
-        run_on_cpu(CPU(target_cpu), sigp_cpu_start, CPU(target_cpu));
-        cc = SIGP_CC_ORDER_CODE_ACCEPTED;
+        run_on_cpu(CPU(dst_cpu), sigp_start, &si);
         break;
     case SIGP_RESTART:
-        run_on_cpu(CPU(target_cpu), sigp_cpu_restart, CPU(target_cpu));
-        cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-        break;
-    case SIGP_SET_ARCH:
-        *statusreg &= 0xffffffff00000000UL;
-        *statusreg |= SIGP_STAT_INVALID_PARAMETER;
-        cc = SIGP_CC_STATUS_STORED;
-        break;
+        run_on_cpu(CPU(dst_cpu), sigp_restart, &si);
     case SIGP_INITIAL_CPU_RESET:
-        run_on_cpu(CPU(target_cpu), sigp_initial_cpu_reset, CPU(target_cpu));
-        cc = SIGP_CC_ORDER_CODE_ACCEPTED;
+        run_on_cpu(CPU(dst_cpu), sigp_initial_cpu_reset, &si);
         break;
     case SIGP_CPU_RESET:
-        run_on_cpu(CPU(target_cpu), sigp_cpu_reset, CPU(target_cpu));
-        cc = SIGP_CC_ORDER_CODE_ACCEPTED;
+        run_on_cpu(CPU(dst_cpu), sigp_cpu_reset, &si);
         break;
     default:
-        DPRINTF("KVM: unknown SIGP: 0x%x\n", order_code);
-        *statusreg &= 0xffffffff00000000UL;
-        *statusreg |= SIGP_STAT_INVALID_ORDER;
-        cc = SIGP_CC_STATUS_STORED;
+        DPRINTF("KVM: unknown SIGP: 0x%x\n", order);
+        *status_reg &= 0xffffffff00000000ULL;
+        *status_reg |= SIGP_STAT_INVALID_ORDER;
+        si.cc = SIGP_CC_STATUS_STORED;
+    }
+
+    return si.cc;
+}
+
+#define SIGP_ORDER_MASK 0x000000ff
+
+static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
+{
+    CPUS390XState *env = &cpu->env;
+    const uint8_t r1 = ipa1 >> 4;
+    const uint8_t r3 = ipa1 & 0x0f;
+    int ret;
+    uint8_t order;
+    uint64_t *status_reg;
+    S390CPU *dst_cpu = NULL;
+
+    cpu_synchronize_state(CPU(cpu));
+
+    /* get order code */
+    order = decode_basedisp_rs(env, run->s390_sieic.ipb) & SIGP_ORDER_MASK;
+    status_reg = &env->regs[r1];
+
+    switch (order) {
+    case SIGP_SET_ARCH:
+        *status_reg &= 0xffffffff00000000ULL;
+        *status_reg |= SIGP_STAT_INVALID_PARAMETER;
+        ret = SIGP_CC_STATUS_STORED;
         break;
+    default:
+        /* all other sigp orders target a single vcpu */
+        dst_cpu = s390_cpu_addr2state(env->regs[r3]);
+        ret = handle_sigp_single_dst(dst_cpu, order, status_reg);
     }
 
-out:
-    setcc(cpu, cc);
-    return 0;
+    if (ret >= 0) {
+        setcc(cpu, ret);
+        return 0;
+    }
+
+    return ret;
 }
 
 static int handle_instruction(S390CPU *cpu, struct kvm_run *run)
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 03/10] s390x/kvm: pass the SIGP instruction parameter to the SIGP handler
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 01/10] s390x: introduce defines for SIGP condition codes Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 02/10] s390x/kvm: more details for SIGP handler with one destination vcpu Jens Freimann
@ 2015-02-24 13:15 ` Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 04/10] s390x/kvm: helper to set the SIGP status in SigpInfo Jens Freimann
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: David Hildenbrand, Jens Freimann, qemu-devel

From: David Hildenbrand <dahi@linux.vnet.ibm.com>

The parameter of the SIGP instruction will be neded in the future. Let's read it
out and store it in the struct sigp_info, so it can be passed to the sigp
handlers.

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/kvm.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index ec17ac8..1f4a4b1 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -1100,6 +1100,7 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
 
 typedef struct SigpInfo {
     S390CPU *cpu;
+    uint64_t param;
     int cc;
     uint64_t *status_reg;
 } SigpInfo;
@@ -1161,10 +1162,11 @@ static void sigp_cpu_reset(void *arg)
 }
 
 static int handle_sigp_single_dst(S390CPU *dst_cpu, uint8_t order,
-                                  uint64_t *status_reg)
+                                  uint64_t param, uint64_t *status_reg)
 {
     SigpInfo si = {
         .cpu = dst_cpu,
+        .param = param,
         .status_reg = status_reg,
     };
 
@@ -1205,6 +1207,7 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
     int ret;
     uint8_t order;
     uint64_t *status_reg;
+    uint64_t param;
     S390CPU *dst_cpu = NULL;
 
     cpu_synchronize_state(CPU(cpu));
@@ -1212,6 +1215,7 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
     /* get order code */
     order = decode_basedisp_rs(env, run->s390_sieic.ipb) & SIGP_ORDER_MASK;
     status_reg = &env->regs[r1];
+    param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1];
 
     switch (order) {
     case SIGP_SET_ARCH:
@@ -1222,7 +1226,7 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
     default:
         /* all other sigp orders target a single vcpu */
         dst_cpu = s390_cpu_addr2state(env->regs[r3]);
-        ret = handle_sigp_single_dst(dst_cpu, order, status_reg);
+        ret = handle_sigp_single_dst(dst_cpu, order, param, status_reg);
     }
 
     if (ret >= 0) {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 04/10] s390x/kvm: helper to set the SIGP status in SigpInfo
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
                   ` (2 preceding siblings ...)
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 03/10] s390x/kvm: pass the SIGP instruction parameter to the SIGP handler Jens Freimann
@ 2015-02-24 13:15 ` Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 05/10] s390x/kvm: trace all SIGP orders Jens Freimann
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: David Hildenbrand, Jens Freimann, qemu-devel

From: David Hildenbrand <dahi@linux.vnet.ibm.com>

Whenever we set the SIGP status in the status register, we have to wipe out
the lower 4 bytes and keep the higher 4 bytes. Also the condition code will
always be set to STATUS_STORED.

Let's introduce the wrapper for SigpInfo, as this will avoid most duplicate
code in the future.

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/kvm.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 1f4a4b1..fb0ce6d 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -1105,6 +1105,13 @@ typedef struct SigpInfo {
     uint64_t *status_reg;
 } SigpInfo;
 
+static void set_sigp_status(SigpInfo *si, uint64_t status)
+{
+    *si->status_reg &= 0xffffffff00000000ULL;
+    *si->status_reg |= status;
+    si->cc = SIGP_CC_STATUS_STORED;
+}
+
 static void sigp_start(void *arg)
 {
     SigpInfo *si = arg;
@@ -1189,9 +1196,7 @@ static int handle_sigp_single_dst(S390CPU *dst_cpu, uint8_t order,
         break;
     default:
         DPRINTF("KVM: unknown SIGP: 0x%x\n", order);
-        *status_reg &= 0xffffffff00000000ULL;
-        *status_reg |= SIGP_STAT_INVALID_ORDER;
-        si.cc = SIGP_CC_STATUS_STORED;
+        set_sigp_status(&si, SIGP_STAT_INVALID_ORDER);
     }
 
     return si.cc;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 05/10] s390x/kvm: trace all SIGP orders
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
                   ` (3 preceding siblings ...)
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 04/10] s390x/kvm: helper to set the SIGP status in SigpInfo Jens Freimann
@ 2015-02-24 13:15 ` Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 06/10] s390x/kvm: implement handling of new " Jens Freimann
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: David Hildenbrand, Jens Freimann, qemu-devel

From: David Hildenbrand <dahi@linux.vnet.ibm.com>

This patch adds tracing code for all SIGP orders (including the destination
vcpu and the resulting condition code).

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/kvm.c | 4 +++-
 trace-events       | 1 +
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index fb0ce6d..ec14714 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -1118,7 +1118,6 @@ static void sigp_start(void *arg)
 
     s390_cpu_set_state(CPU_STATE_OPERATING, si->cpu);
     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
-    DPRINTF("DONE: KVM cpu start: %p\n", &si->cpu->env);
 }
 
 static void sigp_restart(void *arg)
@@ -1234,6 +1233,9 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
         ret = handle_sigp_single_dst(dst_cpu, order, param, status_reg);
     }
 
+    trace_kvm_sigp_finished(order, CPU(cpu)->cpu_index,
+                            dst_cpu ? CPU(dst_cpu)->cpu_index : -1, ret);
+
     if (ret >= 0) {
         setcc(cpu, ret);
         return 0;
diff --git a/trace-events b/trace-events
index f87b077..1e0052d 100644
--- a/trace-events
+++ b/trace-events
@@ -1577,6 +1577,7 @@ mhp_pc_dimm_assigned_address(uint64_t addr) "0x%"PRIx64
 kvm_enable_cmma(int rc) "CMMA: enabling with result code %d"
 kvm_clear_cmma(int rc) "CMMA: clearing with result code %d"
 kvm_failed_cpu_state_set(int cpu_index, uint8_t state, const char *msg) "Warning: Unable to set cpu %d state %" PRIu8 " to KVM: %s"
+kvm_sigp_finished(uint8_t order, int cpu_index, int dst_index, int cc) "SIGP: Finished order %u on cpu %d -> cpu %d with cc=%d"
 
 # hw/dma/i8257.c
 i8257_unregistered_dma(int nchan, int dma_pos, int dma_len) "unregistered DMA channel used nchan=%d dma_pos=%d dma_len=%d"
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 06/10] s390x/kvm: implement handling of new SIGP orders
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
                   ` (4 preceding siblings ...)
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 05/10] s390x/kvm: trace all SIGP orders Jens Freimann
@ 2015-02-24 13:15 ` Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 07/10] s390x/kvm: SIGP START is only applicable when STOPPED Jens Freimann
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: David Hildenbrand, Jens Freimann, qemu-devel

From: David Hildenbrand <dahi@linux.vnet.ibm.com>

This patch adds handling code for the following SIGP orders:
- SIGP SET ARCHITECTURE
- SIGP SET PREFIX
- SIGP STOP
- SIGP STOP AND STORE STATUS
- SIGP STORE STATUS AT ADDRESS

SIGP STOP (AND STORE STATUS) are the only orders that can stay pending forever
(and may only be interrupted by resets), so special care has to be taken about
them. Their status also has to be tracked within QEMU. This patch takes
care of migrating this status (e.g. if migration happens during a SIGP STOP).

Due to the BQL, only one VCPU is currently able to execute SIGP handlers at a
time. According to the PoP, BUSY should be returned if another SIGP order is
currently being executed on a VCPU. This can only be implemented when the BQL
does not protect all handlers. For now, all SIGP orders on all VCPUs will be
serialized, which will be okay for the first shot.

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/cpu.c     |   2 +
 target-s390x/cpu.h     |  12 +++
 target-s390x/kvm.c     | 204 ++++++++++++++++++++++++++++++++++++++++++++++++-
 target-s390x/machine.c |   5 +-
 4 files changed, 218 insertions(+), 5 deletions(-)

diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index d2f6312..e0537fa 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -96,6 +96,7 @@ static void s390_cpu_reset(CPUState *s)
 
     env->pfault_token = -1UL;
     scc->parent_reset(s);
+    cpu->env.sigp_order = 0;
     s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
     tlb_flush(s, 1);
 }
@@ -131,6 +132,7 @@ static void s390_cpu_full_reset(CPUState *s)
     CPUS390XState *env = &cpu->env;
 
     scc->parent_reset(s);
+    cpu->env.sigp_order = 0;
     s390_cpu_set_state(CPU_STATE_STOPPED, cpu);
 
     memset(env, 0, offsetof(CPUS390XState, cpu_num));
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e6edb72..988d4a0 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -157,6 +157,9 @@ typedef struct CPUS390XState {
 #define CPU_STATE_LOAD                 0x04
     uint8_t cpu_state;
 
+    /* currently processed sigp order */
+    uint8_t sigp_order;
+
 } CPUS390XState;
 
 #include "cpu-qom.h"
@@ -408,6 +411,10 @@ S390CPU *s390_cpu_addr2state(uint16_t cpu_addr);
 unsigned int s390_cpu_halt(S390CPU *cpu);
 void s390_cpu_unhalt(S390CPU *cpu);
 unsigned int s390_cpu_set_state(uint8_t cpu_state, S390CPU *cpu);
+static inline uint8_t s390_cpu_get_state(S390CPU *cpu)
+{
+    return cpu->env.cpu_state;
+}
 
 /* service interrupts are floating therefore we must not pass an cpustate */
 void s390_sclp_extint(uint32_t parm);
@@ -888,6 +895,11 @@ struct sysib_322 {
 #define SIGP_STAT_INVALID_ORDER     0x00000002UL
 #define SIGP_STAT_RECEIVER_CHECK    0x00000001UL
 
+/* SIGP SET ARCHITECTURE modes */
+#define SIGP_MODE_ESA_S390 0
+#define SIGP_MODE_Z_ARCH_TRANS_ALL_PSW 1
+#define SIGP_MODE_Z_ARCH_TRANS_CUR_PSW 2
+
 void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
 int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
                   target_ulong *raddr, int *flags);
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index ec14714..fcb0cae 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -38,6 +38,7 @@
 #include "qapi/qmp/qjson.h"
 #include "monitor/monitor.h"
 #include "exec/gdbstub.h"
+#include "exec/address-spaces.h"
 #include "trace.h"
 #include "qapi-event.h"
 #include "hw/s390x/s390-pci-inst.h"
@@ -1120,6 +1121,114 @@ static void sigp_start(void *arg)
     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 }
 
+static void sigp_stop(void *arg)
+{
+    SigpInfo *si = arg;
+    struct kvm_s390_irq irq = {
+        .type = KVM_S390_SIGP_STOP,
+    };
+
+    if (s390_cpu_get_state(si->cpu) != CPU_STATE_OPERATING) {
+        si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
+        return;
+    }
+
+    /* disabled wait - sleeping in user space */
+    if (CPU(si->cpu)->halted) {
+        s390_cpu_set_state(CPU_STATE_STOPPED, si->cpu);
+    } else {
+        /* execute the stop function */
+        si->cpu->env.sigp_order = SIGP_STOP;
+        kvm_s390_vcpu_interrupt(si->cpu, &irq);
+    }
+    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
+}
+
+#define KVM_S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area)
+#define SAVE_AREA_SIZE 512
+static int kvm_s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch)
+{
+    static const uint8_t ar_id = 1;
+    uint64_t ckc = cpu->env.ckc >> 8;
+    void *mem;
+    hwaddr len = SAVE_AREA_SIZE;
+
+    mem = cpu_physical_memory_map(addr, &len, 1);
+    if (!mem) {
+        return -EFAULT;
+    }
+    if (len != SAVE_AREA_SIZE) {
+        cpu_physical_memory_unmap(mem, len, 1, 0);
+        return -EFAULT;
+    }
+
+    if (store_arch) {
+        cpu_physical_memory_write(offsetof(LowCore, ar_access_id), &ar_id, 1);
+    }
+    memcpy(mem, &cpu->env.fregs, 128);
+    memcpy(mem + 128, &cpu->env.regs, 128);
+    memcpy(mem + 256, &cpu->env.psw, 16);
+    memcpy(mem + 280, &cpu->env.psa, 4);
+    memcpy(mem + 284, &cpu->env.fpc, 4);
+    memcpy(mem + 292, &cpu->env.todpr, 4);
+    memcpy(mem + 296, &cpu->env.cputm, 8);
+    memcpy(mem + 304, &ckc, 8);
+    memcpy(mem + 320, &cpu->env.aregs, 64);
+    memcpy(mem + 384, &cpu->env.cregs, 128);
+
+    cpu_physical_memory_unmap(mem, len, 1, len);
+
+    return 0;
+}
+
+static void sigp_stop_and_store_status(void *arg)
+{
+    SigpInfo *si = arg;
+    struct kvm_s390_irq irq = {
+        .type = KVM_S390_SIGP_STOP,
+    };
+
+    /* disabled wait - sleeping in user space */
+    if (s390_cpu_get_state(si->cpu) == CPU_STATE_OPERATING &&
+        CPU(si->cpu)->halted) {
+        s390_cpu_set_state(CPU_STATE_STOPPED, si->cpu);
+    }
+
+    switch (s390_cpu_get_state(si->cpu)) {
+    case CPU_STATE_OPERATING:
+        si->cpu->env.sigp_order = SIGP_STOP_STORE_STATUS;
+        kvm_s390_vcpu_interrupt(si->cpu, &irq);
+        /* store will be performed when handling the stop intercept */
+        break;
+    case CPU_STATE_STOPPED:
+        /* already stopped, just store the status */
+        cpu_synchronize_state(CPU(si->cpu));
+        kvm_s390_store_status(si->cpu, KVM_S390_STORE_STATUS_DEF_ADDR, true);
+        break;
+    }
+    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
+}
+
+static void sigp_store_status_at_address(void *arg)
+{
+    SigpInfo *si = arg;
+    uint32_t address = si->param & 0x7ffffe00u;
+
+    /* cpu has to be stopped */
+    if (s390_cpu_get_state(si->cpu) != CPU_STATE_STOPPED) {
+        set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
+        return;
+    }
+
+    cpu_synchronize_state(CPU(si->cpu));
+
+    if (kvm_s390_store_status(si->cpu, address, false)) {
+        set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
+        return;
+    }
+    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
+}
+
 static void sigp_restart(void *arg)
 {
     SigpInfo *si = arg;
@@ -1167,6 +1276,30 @@ static void sigp_cpu_reset(void *arg)
     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 }
 
+static void sigp_set_prefix(void *arg)
+{
+    SigpInfo *si = arg;
+    uint32_t addr = si->param & 0x7fffe000u;
+
+    cpu_synchronize_state(CPU(si->cpu));
+
+    if (!address_space_access_valid(&address_space_memory, addr,
+                                    sizeof(struct LowCore), false)) {
+        set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
+        return;
+    }
+
+    /* cpu has to be stopped */
+    if (s390_cpu_get_state(si->cpu) != CPU_STATE_STOPPED) {
+        set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
+        return;
+    }
+
+    si->cpu->env.psa = addr;
+    cpu_synchronize_post_init(CPU(si->cpu));
+    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
+}
+
 static int handle_sigp_single_dst(S390CPU *dst_cpu, uint8_t order,
                                   uint64_t param, uint64_t *status_reg)
 {
@@ -1181,12 +1314,32 @@ static int handle_sigp_single_dst(S390CPU *dst_cpu, uint8_t order,
         return SIGP_CC_NOT_OPERATIONAL;
     }
 
+    /* only resets can break pending orders */
+    if (dst_cpu->env.sigp_order != 0 &&
+        order != SIGP_CPU_RESET &&
+        order != SIGP_INITIAL_CPU_RESET) {
+        return SIGP_CC_BUSY;
+    }
+
     switch (order) {
     case SIGP_START:
         run_on_cpu(CPU(dst_cpu), sigp_start, &si);
         break;
+    case SIGP_STOP:
+        run_on_cpu(CPU(dst_cpu), sigp_stop, &si);
+        break;
     case SIGP_RESTART:
         run_on_cpu(CPU(dst_cpu), sigp_restart, &si);
+        break;
+    case SIGP_STOP_STORE_STATUS:
+        run_on_cpu(CPU(dst_cpu), sigp_stop_and_store_status, &si);
+        break;
+    case SIGP_STORE_STATUS_ADDR:
+        run_on_cpu(CPU(dst_cpu), sigp_store_status_at_address, &si);
+        break;
+    case SIGP_SET_PREFIX:
+        run_on_cpu(CPU(dst_cpu), sigp_set_prefix, &si);
+        break;
     case SIGP_INITIAL_CPU_RESET:
         run_on_cpu(CPU(dst_cpu), sigp_initial_cpu_reset, &si);
         break;
@@ -1201,6 +1354,48 @@ static int handle_sigp_single_dst(S390CPU *dst_cpu, uint8_t order,
     return si.cc;
 }
 
+static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
+                                 uint64_t *status_reg)
+{
+    CPUState *cur_cs;
+    S390CPU *cur_cpu;
+
+    /* due to the BQL, we are the only active cpu */
+    CPU_FOREACH(cur_cs) {
+        cur_cpu = S390_CPU(cur_cs);
+        if (cur_cpu->env.sigp_order != 0) {
+            return SIGP_CC_BUSY;
+        }
+        cpu_synchronize_state(cur_cs);
+        /* all but the current one have to be stopped */
+        if (cur_cpu != cpu &&
+            s390_cpu_get_state(cur_cpu) != CPU_STATE_STOPPED) {
+            *status_reg &= 0xffffffff00000000ULL;
+            *status_reg |= SIGP_STAT_INCORRECT_STATE;
+            return SIGP_CC_STATUS_STORED;
+        }
+    }
+
+    switch (param & 0xff) {
+    case SIGP_MODE_ESA_S390:
+        /* not supported */
+        return SIGP_CC_NOT_OPERATIONAL;
+    case SIGP_MODE_Z_ARCH_TRANS_ALL_PSW:
+    case SIGP_MODE_Z_ARCH_TRANS_CUR_PSW:
+        CPU_FOREACH(cur_cs) {
+            cur_cpu = S390_CPU(cur_cs);
+            cur_cpu->env.pfault_token = -1UL;
+        }
+        break;
+    default:
+        *status_reg &= 0xffffffff00000000ULL;
+        *status_reg |= SIGP_STAT_INVALID_PARAMETER;
+        return SIGP_CC_STATUS_STORED;
+    }
+
+    return SIGP_CC_ORDER_CODE_ACCEPTED;
+}
+
 #define SIGP_ORDER_MASK 0x000000ff
 
 static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
@@ -1223,9 +1418,7 @@ static int handle_sigp(S390CPU *cpu, struct kvm_run *run, uint8_t ipa1)
 
     switch (order) {
     case SIGP_SET_ARCH:
-        *status_reg &= 0xffffffff00000000ULL;
-        *status_reg |= SIGP_STAT_INVALID_PARAMETER;
-        ret = SIGP_CC_STATUS_STORED;
+        ret = sigp_set_architecture(cpu, param, status_reg);
         break;
     default:
         /* all other sigp orders target a single vcpu */
@@ -1344,6 +1537,11 @@ static int handle_intercept(S390CPU *cpu)
             if (s390_cpu_set_state(CPU_STATE_STOPPED, cpu) == 0) {
                 qemu_system_shutdown_request();
             }
+            if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) {
+                kvm_s390_store_status(cpu, KVM_S390_STORE_STATUS_DEF_ADDR,
+                                      true);
+            }
+            cpu->env.sigp_order = 0;
             r = EXCP_HALTED;
             break;
         case ICPT_SOFT_INTERCEPT:
diff --git a/target-s390x/machine.c b/target-s390x/machine.c
index fbcb0d0..bd4cea7 100644
--- a/target-s390x/machine.c
+++ b/target-s390x/machine.c
@@ -36,8 +36,8 @@ static int cpu_post_load(void *opaque, int version_id)
 const VMStateDescription vmstate_s390_cpu = {
     .name = "cpu",
     .post_load = cpu_post_load,
-    .version_id = 1,
-    .minimum_version_id = 1,
+    .version_id = 2,
+    .minimum_version_id = 2,
     .fields      = (VMStateField[]) {
         VMSTATE_UINT64(env.fregs[0].ll, S390CPU),
         VMSTATE_UINT64(env.fregs[1].ll, S390CPU),
@@ -71,6 +71,7 @@ const VMStateDescription vmstate_s390_cpu = {
         VMSTATE_UINT32_ARRAY(env.aregs, S390CPU, 16),
         VMSTATE_UINT64_ARRAY(env.cregs, S390CPU, 16),
         VMSTATE_UINT8(env.cpu_state, S390CPU),
+        VMSTATE_UINT8(env.sigp_order, S390CPU),
         VMSTATE_END_OF_LIST()
      },
 };
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 07/10] s390x/kvm: SIGP START is only applicable when STOPPED
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
                   ` (5 preceding siblings ...)
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 06/10] s390x/kvm: implement handling of new " Jens Freimann
@ 2015-02-24 13:15 ` Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 08/10] s390x: add function to deliver restart irqs Jens Freimann
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: David Hildenbrand, Jens Freimann, qemu-devel

From: David Hildenbrand <dahi@linux.vnet.ibm.com>

In preparation for other CPU states, SIGP START will only start a VCPU if it is
in the STOPPED state.

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/kvm.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index fcb0cae..ed56b3c 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -1117,6 +1117,11 @@ static void sigp_start(void *arg)
 {
     SigpInfo *si = arg;
 
+    if (s390_cpu_get_state(si->cpu) != CPU_STATE_STOPPED) {
+        si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
+        return;
+    }
+
     s390_cpu_set_state(CPU_STATE_OPERATING, si->cpu);
     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 }
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 08/10] s390x: add function to deliver restart irqs
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
                   ` (6 preceding siblings ...)
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 07/10] s390x/kvm: SIGP START is only applicable when STOPPED Jens Freimann
@ 2015-02-24 13:15 ` Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 09/10] s390x/kvm: deliver SIGP RESTART directly if stopped Jens Freimann
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: David Hildenbrand, Jens Freimann, qemu-devel

From: David Hildenbrand <dahi@linux.vnet.ibm.com>

This patch adds a helper function to deliver restart irqs. To be able to be used
by kvm, the psw load/store methods have to perform special cc-code handling only
when running with tcg.

Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/cpu.h    |  4 +++-
 target-s390x/helper.c | 35 ++++++++++++++++++++++++++++-------
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index 988d4a0..162cbb6 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -355,6 +355,8 @@ void *s390_cpu_physical_memory_map(CPUS390XState *env, hwaddr addr, hwaddr *len,
                                    int is_write);
 void s390_cpu_physical_memory_unmap(CPUS390XState *env, void *addr, hwaddr len,
                                     int is_write);
+void do_restart_interrupt(CPUS390XState *env);
+
 static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb)
 {
     hwaddr addr = 0;
@@ -666,7 +668,7 @@ typedef struct LowCore
     PSW             mcck_old_psw;             /* 0x160 */
     PSW             io_old_psw;               /* 0x170 */
     uint8_t         pad7[0x1a0-0x180];        /* 0x180 */
-    PSW             restart_psw;              /* 0x1a0 */
+    PSW             restart_new_psw;          /* 0x1a0 */
     PSW             external_new_psw;         /* 0x1b0 */
     PSW             svc_new_psw;              /* 0x1c0 */
     PSW             program_new_psw;          /* 0x1d0 */
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 5958343..cb84779 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -506,7 +506,9 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
 {
     env->psw.addr = addr;
     env->psw.mask = mask;
-    env->cc_op = (mask >> 44) & 3;
+    if (tcg_enabled()) {
+        env->cc_op = (mask >> 44) & 3;
+    }
 
     if (mask & PSW_MASK_WAIT) {
         S390CPU *cpu = s390_env_get_cpu(env);
@@ -520,14 +522,16 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
 
 static uint64_t get_psw_mask(CPUS390XState *env)
 {
-    uint64_t r;
+    uint64_t r = env->psw.mask;
 
-    env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst, env->cc_vr);
+    if (tcg_enabled()) {
+        env->cc_op = calc_cc(env, env->cc_op, env->cc_src, env->cc_dst,
+                             env->cc_vr);
 
-    r = env->psw.mask;
-    r &= ~PSW_MASK_CC;
-    assert(!(env->cc_op & ~3));
-    r |= (uint64_t)env->cc_op << 44;
+        r &= ~PSW_MASK_CC;
+        assert(!(env->cc_op & ~3));
+        r |= (uint64_t)env->cc_op << 44;
+    }
 
     return r;
 }
@@ -577,6 +581,23 @@ void s390_cpu_physical_memory_unmap(CPUS390XState *env, void *addr, hwaddr len,
     cpu_physical_memory_unmap(addr, len, is_write, len);
 }
 
+void do_restart_interrupt(CPUS390XState *env)
+{
+    uint64_t mask, addr;
+    LowCore *lowcore;
+
+    lowcore = cpu_map_lowcore(env);
+
+    lowcore->restart_old_psw.mask = cpu_to_be64(get_psw_mask(env));
+    lowcore->restart_old_psw.addr = cpu_to_be64(env->psw.addr);
+    mask = be64_to_cpu(lowcore->restart_new_psw.mask);
+    addr = be64_to_cpu(lowcore->restart_new_psw.addr);
+
+    cpu_unmap_lowcore(lowcore);
+
+    load_psw(env, mask, addr);
+}
+
 static void do_svc_interrupt(CPUS390XState *env)
 {
     uint64_t mask, addr;
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 09/10] s390x/kvm: deliver SIGP RESTART directly if stopped
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
                   ` (7 preceding siblings ...)
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 08/10] s390x: add function to deliver restart irqs Jens Freimann
@ 2015-02-24 13:15 ` Jens Freimann
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 10/10] s390x/kvm: enable the new SIGP handling in user space Jens Freimann
  2015-03-03 14:02 ` [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to " Christian Borntraeger
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: David Hildenbrand, Jens Freimann, qemu-devel

From: David Hildenbrand <dahi@linux.vnet.ibm.com>

According to the PoP, a restart irq has to be delivered "without first honoring
any other pending interruptions", if a cpu is in the STOPPED state.

While it is hard to implement this case in kvm, it can easily be handled in qemu.

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/kvm.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index ed56b3c..7f9fd02 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -1241,8 +1241,17 @@ static void sigp_restart(void *arg)
         .type = KVM_S390_RESTART,
     };
 
-    kvm_s390_vcpu_interrupt(si->cpu, &irq);
-    s390_cpu_set_state(CPU_STATE_OPERATING, si->cpu);
+    switch (s390_cpu_get_state(si->cpu)) {
+    case CPU_STATE_STOPPED:
+        /* the restart irq has to be delivered prior to any other pending irq */
+        cpu_synchronize_state(CPU(si->cpu));
+        do_restart_interrupt(&si->cpu->env);
+        s390_cpu_set_state(CPU_STATE_OPERATING, si->cpu);
+        break;
+    case CPU_STATE_OPERATING:
+        kvm_s390_vcpu_interrupt(si->cpu, &irq);
+        break;
+    }
     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [Qemu-devel] [PATCH 10/10] s390x/kvm: enable the new SIGP handling in user space
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
                   ` (8 preceding siblings ...)
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 09/10] s390x/kvm: deliver SIGP RESTART directly if stopped Jens Freimann
@ 2015-02-24 13:15 ` Jens Freimann
  2015-03-03 14:02 ` [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to " Christian Borntraeger
  10 siblings, 0 replies; 12+ messages in thread
From: Jens Freimann @ 2015-02-24 13:15 UTC (permalink / raw)
  To: Christian Borntraeger, Alexander Graf, Cornelia Huck
  Cc: David Hildenbrand, Jens Freimann, qemu-devel

From: David Hildenbrand <dahi@linux.vnet.ibm.com>

All required SIGP handlers have been implemented in QEMU.

Let's enable the new sigp handling in user space if the kernel supports it.

Reviewed-by: Thomas Huth <thuth@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Jens Freimann <jfrei@linux.vnet.ibm.com>
Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
---
 target-s390x/kvm.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 7f9fd02..8066cb7 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -186,6 +186,9 @@ int kvm_arch_init(KVMState *s)
         || !kvm_check_extension(s, KVM_CAP_S390_COW)) {
         phys_mem_set_alloc(legacy_s390_alloc);
     }
+
+    kvm_vm_enable_cap(s, KVM_CAP_S390_USER_SIGP, 0);
+
     return 0;
 }
 
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space
  2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
                   ` (9 preceding siblings ...)
  2015-02-24 13:15 ` [Qemu-devel] [PATCH 10/10] s390x/kvm: enable the new SIGP handling in user space Jens Freimann
@ 2015-03-03 14:02 ` Christian Borntraeger
  10 siblings, 0 replies; 12+ messages in thread
From: Christian Borntraeger @ 2015-03-03 14:02 UTC (permalink / raw)
  To: Jens Freimann, Alexander Graf, Cornelia Huck; +Cc: qemu-devel

Am 24.02.2015 um 14:15 schrieb Jens Freimann:
> Cornelia, Alex, Christian,
> 
> these patches move large parts of SIGP handling from kernel
> to user space.
> 
> Please note: This series needs a linux-headers sync with v4.0-rc1 
> to work and should be applied only after Michael Tsirkin's series 
> "virtio: pull headers from linux" was applied and a header sync
> was done with the new scripts and header files. 
> 
> regards
> Jens
> 
> David Hildenbrand (10):
>   s390x: introduce defines for SIGP condition codes
>   s390x/kvm: more details for SIGP handler with one destination vcpu
>   s390x/kvm: pass the SIGP instruction parameter to the SIGP handler
>   s390x/kvm: helper to set the SIGP status in SigpInfo
>   s390x/kvm: trace all SIGP orders
>   s390x/kvm: implement handling of new SIGP orders
>   s390x/kvm: SIGP START is only applicable when STOPPED
>   s390x: add function to deliver restart irqs
>   s390x/kvm: deliver SIGP RESTART directly if stopped
>   s390x/kvm: enable the new SIGP handling in user space
> 
>  target-s390x/cpu.c         |   2 +
>  target-s390x/cpu.h         |  25 ++-
>  target-s390x/helper.c      |  35 ++++-
>  target-s390x/kvm.c         | 371 ++++++++++++++++++++++++++++++++++++++-------
>  target-s390x/machine.c     |   5 +-
>  target-s390x/misc_helper.c |   4 +-
>  trace-events               |   1 +
>  7 files changed, 372 insertions(+), 71 deletions(-)
> 

Thanks applied.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2015-03-03 14:02 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-24 13:15 [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to user space Jens Freimann
2015-02-24 13:15 ` [Qemu-devel] [PATCH 01/10] s390x: introduce defines for SIGP condition codes Jens Freimann
2015-02-24 13:15 ` [Qemu-devel] [PATCH 02/10] s390x/kvm: more details for SIGP handler with one destination vcpu Jens Freimann
2015-02-24 13:15 ` [Qemu-devel] [PATCH 03/10] s390x/kvm: pass the SIGP instruction parameter to the SIGP handler Jens Freimann
2015-02-24 13:15 ` [Qemu-devel] [PATCH 04/10] s390x/kvm: helper to set the SIGP status in SigpInfo Jens Freimann
2015-02-24 13:15 ` [Qemu-devel] [PATCH 05/10] s390x/kvm: trace all SIGP orders Jens Freimann
2015-02-24 13:15 ` [Qemu-devel] [PATCH 06/10] s390x/kvm: implement handling of new " Jens Freimann
2015-02-24 13:15 ` [Qemu-devel] [PATCH 07/10] s390x/kvm: SIGP START is only applicable when STOPPED Jens Freimann
2015-02-24 13:15 ` [Qemu-devel] [PATCH 08/10] s390x: add function to deliver restart irqs Jens Freimann
2015-02-24 13:15 ` [Qemu-devel] [PATCH 09/10] s390x/kvm: deliver SIGP RESTART directly if stopped Jens Freimann
2015-02-24 13:15 ` [Qemu-devel] [PATCH 10/10] s390x/kvm: enable the new SIGP handling in user space Jens Freimann
2015-03-03 14:02 ` [Qemu-devel] [PATCH 00/10] s390x: move sigp handling to " Christian Borntraeger

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.