c687bc
From 7ad1c4aaea6cd202449c05fc0034af6b108def4f Mon Sep 17 00:00:00 2001
c687bc
From: Thomas Huth <thuth@redhat.com>
c687bc
Date: Wed, 11 Nov 2020 12:03:14 -0500
c687bc
Subject: [PATCH 14/18] s390: guest support for diagnose 0x318
c687bc
c687bc
RH-Author: Thomas Huth <thuth@redhat.com>
c687bc
Message-id: <20201111120316.707489-11-thuth@redhat.com>
c687bc
Patchwork-id: 99507
c687bc
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH v2 10/12] s390: guest support for diagnose 0x318
c687bc
Bugzilla: 1798506
c687bc
RH-Acked-by: Jens Freimann <jfreimann@redhat.com>
c687bc
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
c687bc
RH-Acked-by: David Hildenbrand <david@redhat.com>
c687bc
c687bc
From: Collin Walling <walling@linux.ibm.com>
c687bc
c687bc
DIAGNOSE 0x318 (diag318) is an s390 instruction that allows the storage
c687bc
of diagnostic information that is collected by the firmware in the case
c687bc
of hardware/firmware service events.
c687bc
c687bc
QEMU handles the instruction by storing the info in the CPU state. A
c687bc
subsequent register sync will communicate the data to the hypervisor.
c687bc
c687bc
QEMU handles the migration via a VM State Description.
c687bc
c687bc
This feature depends on the Extended-Length SCCB (els) feature. If
c687bc
els is not present, then a warning will be printed and the SCLP bit
c687bc
that allows the Linux kernel to execute the instruction will not be
c687bc
set.
c687bc
c687bc
Availability of this instruction is determined by byte 134 (aka fac134)
c687bc
bit 0 of the SCLP Read Info block. This coincidentally expands into the
c687bc
space used for CPU entries, which means VMs running with the diag318
c687bc
capability may not be able to read information regarding all CPUs
c687bc
unless the guest kernel supports an extended-length SCCB.
c687bc
c687bc
This feature is not supported in protected virtualization mode.
c687bc
c687bc
Signed-off-by: Collin Walling <walling@linux.ibm.com>
c687bc
Acked-by: Janosch Frank <frankja@linux.ibm.com>
c687bc
Acked-by: Thomas Huth <thuth@redhat.com>
c687bc
Acked-by: David Hildenbrand <david@redhat.com>
c687bc
Acked-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
c687bc
Message-Id: <20200915194416.107460-9-walling@linux.ibm.com>
c687bc
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
c687bc
(cherry picked from commit fabdada9357b9cfd980c7744ddce47e34600bbef)
c687bc
Signed-off-by: Thomas Huth <thuth@redhat.com>
c687bc
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
c687bc
---
c687bc
 hw/s390x/sclp.c                     |  5 ++++
c687bc
 include/hw/s390x/sclp.h             |  8 ++++++
c687bc
 target/s390x/cpu.h                  |  2 ++
c687bc
 target/s390x/cpu_features.h         |  1 +
c687bc
 target/s390x/cpu_features_def.inc.h |  3 +++
c687bc
 target/s390x/cpu_models.c           |  1 +
c687bc
 target/s390x/gen-features.c         |  1 +
c687bc
 target/s390x/kvm.c                  | 39 +++++++++++++++++++++++++++++
c687bc
 target/s390x/machine.c              | 17 +++++++++++++
c687bc
 9 files changed, 77 insertions(+)
c687bc
c687bc
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
c687bc
index 8d111628e04..2931046f456 100644
c687bc
--- a/hw/s390x/sclp.c
c687bc
+++ b/hw/s390x/sclp.c
c687bc
@@ -139,6 +139,11 @@ static void read_SCP_info(SCLPDevice *sclp, SCCB *sccb)
c687bc
     s390_get_feat_block(S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
c687bc
                          read_info->conf_char_ext);
c687bc
 
c687bc
+    if (s390_has_feat(S390_FEAT_EXTENDED_LENGTH_SCCB)) {
c687bc
+        s390_get_feat_block(S390_FEAT_TYPE_SCLP_FAC134,
c687bc
+                            &read_info->fac134);
c687bc
+    }
c687bc
+
c687bc
     read_info->facilities = cpu_to_be64(SCLP_HAS_CPU_INFO |
c687bc
                                         SCLP_HAS_IOA_RECONFIG);
c687bc
 
c687bc
diff --git a/include/hw/s390x/sclp.h b/include/hw/s390x/sclp.h
c687bc
index 62e2aa1d9f1..addd904e5f4 100644
c687bc
--- a/include/hw/s390x/sclp.h
c687bc
+++ b/include/hw/s390x/sclp.h
c687bc
@@ -133,7 +133,15 @@ typedef struct ReadInfo {
c687bc
     uint16_t highest_cpu;
c687bc
     uint8_t  _reserved5[124 - 122];     /* 122-123 */
c687bc
     uint32_t hmfai;
c687bc
+    uint8_t  _reserved7[134 - 128];     /* 128-133 */
c687bc
+    uint8_t  fac134;
c687bc
+    uint8_t  _reserved8[144 - 135];     /* 135-143 */
c687bc
     struct CPUEntry entries[];
c687bc
+    /*
c687bc
+     * When the Extended-Length SCCB (ELS) feature is enabled the
c687bc
+     * start of the entries field begins at an offset denoted by the
c687bc
+     * offset_cpu field, otherwise it's at an offset of 128.
c687bc
+     */
c687bc
 } QEMU_PACKED ReadInfo;
c687bc
 
c687bc
 typedef struct ReadCpuInfo {
c687bc
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
c687bc
index a48e655c4d4..1dc21cd311d 100644
c687bc
--- a/target/s390x/cpu.h
c687bc
+++ b/target/s390x/cpu.h
c687bc
@@ -117,6 +117,8 @@ struct CPUS390XState {
c687bc
     uint16_t external_call_addr;
c687bc
     DECLARE_BITMAP(emergency_signals, S390_MAX_CPUS);
c687bc
 
c687bc
+    uint64_t diag318_info;
c687bc
+
c687bc
     /* Fields up to this point are cleared by a CPU reset */
c687bc
     struct {} end_reset_fields;
c687bc
 
c687bc
diff --git a/target/s390x/cpu_features.h b/target/s390x/cpu_features.h
c687bc
index da695a8346e..f74f7fc3a11 100644
c687bc
--- a/target/s390x/cpu_features.h
c687bc
+++ b/target/s390x/cpu_features.h
c687bc
@@ -23,6 +23,7 @@ typedef enum {
c687bc
     S390_FEAT_TYPE_STFL,
c687bc
     S390_FEAT_TYPE_SCLP_CONF_CHAR,
c687bc
     S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT,
c687bc
+    S390_FEAT_TYPE_SCLP_FAC134,
c687bc
     S390_FEAT_TYPE_SCLP_CPU,
c687bc
     S390_FEAT_TYPE_MISC,
c687bc
     S390_FEAT_TYPE_PLO,
c687bc
diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h
c687bc
index 3548d65a69a..cf7e04ee44f 100644
c687bc
--- a/target/s390x/cpu_features_def.inc.h
c687bc
+++ b/target/s390x/cpu_features_def.inc.h
c687bc
@@ -122,6 +122,9 @@ DEF_FEAT(SIE_CMMA, "cmma", SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-man
c687bc
 DEF_FEAT(SIE_PFMFI, "pfmfi", SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility")
c687bc
 DEF_FEAT(SIE_IBS, "ibs", SCLP_CONF_CHAR_EXT, 10, "SIE: Interlock-and-broadcast-suppression facility")
c687bc
 
c687bc
+/* Features exposed via SCLP SCCB Facilities byte 134 (bit numbers relative to byte-134) */
c687bc
+DEF_FEAT(DIAG_318, "diag318", SCLP_FAC134, 0, "Control program name and version codes")
c687bc
+
c687bc
 /* Features exposed via SCLP CPU info. */
c687bc
 DEF_FEAT(SIE_F2, "sief2", SCLP_CPU, 4, "SIE: interception format 2 (Virtual SIE)")
c687bc
 DEF_FEAT(SIE_SKEY, "skey", SCLP_CPU, 5, "SIE: Storage-key facility")
c687bc
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
c687bc
index be718220d79..bf6a3faba9e 100644
c687bc
--- a/target/s390x/cpu_models.c
c687bc
+++ b/target/s390x/cpu_models.c
c687bc
@@ -823,6 +823,7 @@ static void check_consistency(const S390CPUModel *model)
c687bc
         { S390_FEAT_PTFF_STOE, S390_FEAT_MULTIPLE_EPOCH },
c687bc
         { S390_FEAT_PTFF_STOUE, S390_FEAT_MULTIPLE_EPOCH },
c687bc
         { S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, S390_FEAT_AP },
c687bc
+        { S390_FEAT_DIAG_318, S390_FEAT_EXTENDED_LENGTH_SCCB },
c687bc
     };
c687bc
     int i;
c687bc
 
c687bc
diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c
c687bc
index 6857f657fba..a1f0a6f3c6f 100644
c687bc
--- a/target/s390x/gen-features.c
c687bc
+++ b/target/s390x/gen-features.c
c687bc
@@ -523,6 +523,7 @@ static uint16_t full_GEN12_GA1[] = {
c687bc
     S390_FEAT_AP_FACILITIES_TEST,
c687bc
     S390_FEAT_AP,
c687bc
     S390_FEAT_EXTENDED_LENGTH_SCCB,
c687bc
+    S390_FEAT_DIAG_318,
c687bc
 };
c687bc
 
c687bc
 static uint16_t full_GEN12_GA2[] = {
c687bc
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
c687bc
index ef437acb5c1..e5e190d21c9 100644
c687bc
--- a/target/s390x/kvm.c
c687bc
+++ b/target/s390x/kvm.c
c687bc
@@ -105,6 +105,7 @@
c687bc
 
c687bc
 #define DIAG_TIMEREVENT                 0x288
c687bc
 #define DIAG_IPL                        0x308
c687bc
+#define DIAG_SET_CONTROL_PROGRAM_CODES  0x318
c687bc
 #define DIAG_KVM_HYPERCALL              0x500
c687bc
 #define DIAG_KVM_BREAKPOINT             0x501
c687bc
 
c687bc
@@ -602,6 +603,11 @@ int kvm_arch_put_registers(CPUState *cs, int level)
c687bc
         cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_ETOKEN;
c687bc
     }
c687bc
 
c687bc
+    if (can_sync_regs(cs, KVM_SYNC_DIAG318)) {
c687bc
+        cs->kvm_run->s.regs.diag318 = env->diag318_info;
c687bc
+        cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_DIAG318;
c687bc
+    }
c687bc
+
c687bc
     /* Finally the prefix */
c687bc
     if (can_sync_regs(cs, KVM_SYNC_PREFIX)) {
c687bc
         cs->kvm_run->s.regs.prefix = env->psa;
c687bc
@@ -741,6 +747,10 @@ int kvm_arch_get_registers(CPUState *cs)
c687bc
         }
c687bc
     }
c687bc
 
c687bc
+    if (can_sync_regs(cs, KVM_SYNC_DIAG318)) {
c687bc
+        env->diag318_info = cs->kvm_run->s.regs.diag318;
c687bc
+    }
c687bc
+
c687bc
     return 0;
c687bc
 }
c687bc
 
c687bc
@@ -1601,6 +1611,27 @@ static int handle_sw_breakpoint(S390CPU *cpu, struct kvm_run *run)
c687bc
     return -ENOENT;
c687bc
 }
c687bc
 
c687bc
+static void handle_diag_318(S390CPU *cpu, struct kvm_run *run)
c687bc
+{
c687bc
+    uint64_t reg = (run->s390_sieic.ipa & 0x00f0) >> 4;
c687bc
+    uint64_t diag318_info = run->s.regs.gprs[reg];
c687bc
+
c687bc
+    /*
c687bc
+     * DIAG 318 can only be enabled with KVM support. As such, let's
c687bc
+     * ensure a guest cannot execute this instruction erroneously.
c687bc
+     */
c687bc
+    if (!s390_has_feat(S390_FEAT_DIAG_318)) {
c687bc
+        kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION);
c687bc
+    }
c687bc
+
c687bc
+    cpu->env.diag318_info = diag318_info;
c687bc
+
c687bc
+    if (can_sync_regs(CPU(cpu), KVM_SYNC_DIAG318)) {
c687bc
+        run->s.regs.diag318 = diag318_info;
c687bc
+        run->kvm_dirty_regs |= KVM_SYNC_DIAG318;
c687bc
+    }
c687bc
+}
c687bc
+
c687bc
 #define DIAG_KVM_CODE_MASK 0x000000000000ffff
c687bc
 
c687bc
 static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
c687bc
@@ -1620,6 +1651,9 @@ static int handle_diag(S390CPU *cpu, struct kvm_run *run, uint32_t ipb)
c687bc
     case DIAG_IPL:
c687bc
         kvm_handle_diag_308(cpu, run);
c687bc
         break;
c687bc
+    case DIAG_SET_CONTROL_PROGRAM_CODES:
c687bc
+        handle_diag_318(cpu, run);
c687bc
+        break;
c687bc
     case DIAG_KVM_HYPERCALL:
c687bc
         r = handle_hypercall(cpu, run);
c687bc
         break;
c687bc
@@ -2449,6 +2483,11 @@ void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp)
c687bc
      */
c687bc
     set_bit(S390_FEAT_EXTENDED_LENGTH_SCCB, model->features);
c687bc
 
c687bc
+    /* DIAGNOSE 0x318 is not supported under protected virtualization */
c687bc
+    if (!s390_is_pv() && kvm_check_extension(kvm_state, KVM_CAP_S390_DIAG318)) {
c687bc
+        set_bit(S390_FEAT_DIAG_318, model->features);
c687bc
+    }
c687bc
+
c687bc
     /* strip of features that are not part of the maximum model */
c687bc
     bitmap_and(model->features, model->features, model->def->full_feat,
c687bc
                S390_FEAT_MAX);
c687bc
diff --git a/target/s390x/machine.c b/target/s390x/machine.c
c687bc
index 549bb6c2808..5b4e82f1ab9 100644
c687bc
--- a/target/s390x/machine.c
c687bc
+++ b/target/s390x/machine.c
c687bc
@@ -234,6 +234,22 @@ const VMStateDescription vmstate_etoken = {
c687bc
     }
c687bc
 };
c687bc
 
c687bc
+static bool diag318_needed(void *opaque)
c687bc
+{
c687bc
+    return s390_has_feat(S390_FEAT_DIAG_318);
c687bc
+}
c687bc
+
c687bc
+const VMStateDescription vmstate_diag318 = {
c687bc
+    .name = "cpu/diag318",
c687bc
+    .version_id = 1,
c687bc
+    .minimum_version_id = 1,
c687bc
+    .needed = diag318_needed,
c687bc
+    .fields = (VMStateField[]) {
c687bc
+        VMSTATE_UINT64(env.diag318_info, S390CPU),
c687bc
+        VMSTATE_END_OF_LIST()
c687bc
+    }
c687bc
+};
c687bc
+
c687bc
 const VMStateDescription vmstate_s390_cpu = {
c687bc
     .name = "cpu",
c687bc
     .post_load = cpu_post_load,
c687bc
@@ -270,6 +286,7 @@ const VMStateDescription vmstate_s390_cpu = {
c687bc
         &vmstate_gscb,
c687bc
         &vmstate_bpbc,
c687bc
         &vmstate_etoken,
c687bc
+        &vmstate_diag318,
c687bc
         NULL
c687bc
     },
c687bc
 };
c687bc
-- 
c687bc
2.27.0
c687bc