Blame SOURCES/kvm-s390-kvm-fix-diag318-propagation-and-reset-functiona.patch

a19a21
From a0ad4344984c50939be8c99371af0988551fb776 Mon Sep 17 00:00:00 2001
a19a21
From: Thomas Huth <thuth@redhat.com>
a19a21
Date: Fri, 20 Nov 2020 11:46:09 -0500
a19a21
Subject: [PATCH 17/18] s390/kvm: fix diag318 propagation and reset
a19a21
 functionality
a19a21
a19a21
RH-Author: Thomas Huth <thuth@redhat.com>
a19a21
Message-id: <20201120114609.408610-2-thuth@redhat.com>
a19a21
Patchwork-id: 99787
a19a21
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH 1/1] s390/kvm: fix diag318 propagation and reset functionality
a19a21
Bugzilla: 1659412
a19a21
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
a19a21
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
a19a21
RH-Acked-by: David Hildenbrand <david@redhat.com>
a19a21
a19a21
From: Collin Walling <walling@linux.ibm.com>
a19a21
a19a21
The Control Program Name Code (CPNC) portion of the diag318
a19a21
info must be set within the SIE block of each VCPU in the
a19a21
configuration. The handler will iterate through each VCPU
a19a21
and dirty the diag318_info reg to be synced with KVM on a
a19a21
subsequent sync_regs call.
a19a21
a19a21
Additionally, the diag318 info resets must be handled via
a19a21
userspace. As such, QEMU will reset this value for each
a19a21
VCPU during a modified clear, load normal, and load clear
a19a21
reset event.
a19a21
a19a21
Fixes: fabdada9357b ("s390: guest support for diagnose 0x318")
a19a21
Signed-off-by: Collin Walling <walling@linux.ibm.com>
a19a21
Message-Id: <20201113221022.257054-1-walling@linux.ibm.com>
a19a21
Reviewed-by: Thomas Huth <thuth@redhat.com>
a19a21
Reviewed-by: Janosch Frank <frankja@de.ibm.com>
a19a21
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
a19a21
(cherry picked from commit e2c6cd567422bfa563be026b9741a1854aecdc06)
a19a21
Signed-off-by: Thomas Huth <thuth@redhat.com>
a19a21
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
a19a21
---
a19a21
 hw/s390x/s390-virtio-ccw.c |  4 ++++
a19a21
 target/s390x/cpu.c         |  7 +++++++
a19a21
 target/s390x/cpu.h         |  1 +
a19a21
 target/s390x/kvm-stub.c    |  4 ++++
a19a21
 target/s390x/kvm.c         | 22 +++++++++++++++++-----
a19a21
 target/s390x/kvm_s390x.h   |  1 +
a19a21
 6 files changed, 34 insertions(+), 5 deletions(-)
a19a21
a19a21
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
a19a21
index e6ed13b649a..5905d2b7adc 100644
a19a21
--- a/hw/s390x/s390-virtio-ccw.c
a19a21
+++ b/hw/s390x/s390-virtio-ccw.c
a19a21
@@ -489,6 +489,10 @@ static void s390_machine_reset(MachineState *machine)
a19a21
     default:
a19a21
         g_assert_not_reached();
a19a21
     }
a19a21
+
a19a21
+    CPU_FOREACH(t) {
a19a21
+        run_on_cpu(t, s390_do_cpu_set_diag318, RUN_ON_CPU_HOST_ULONG(0));
a19a21
+    }
a19a21
     s390_ipl_clear_reset_request();
a19a21
 }
a19a21
 
a19a21
diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c
a19a21
index 371b91b2d72..820cab96e12 100644
a19a21
--- a/target/s390x/cpu.c
a19a21
+++ b/target/s390x/cpu.c
a19a21
@@ -445,6 +445,13 @@ void s390_enable_css_support(S390CPU *cpu)
a19a21
         kvm_s390_enable_css_support(cpu);
a19a21
     }
a19a21
 }
a19a21
+
a19a21
+void s390_do_cpu_set_diag318(CPUState *cs, run_on_cpu_data arg)
a19a21
+{
a19a21
+    if (kvm_enabled()) {
a19a21
+        kvm_s390_set_diag318(cs, arg.host_ulong);
a19a21
+    }
a19a21
+}
a19a21
 #endif
a19a21
 
a19a21
 static gchar *s390_gdb_arch_name(CPUState *cs)
a19a21
diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h
a19a21
index 1dc21cd311d..83a23a11b96 100644
a19a21
--- a/target/s390x/cpu.h
a19a21
+++ b/target/s390x/cpu.h
a19a21
@@ -774,6 +774,7 @@ int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit);
a19a21
 void s390_set_max_pagesize(uint64_t pagesize, Error **errp);
a19a21
 void s390_cmma_reset(void);
a19a21
 void s390_enable_css_support(S390CPU *cpu);
a19a21
+void s390_do_cpu_set_diag318(CPUState *cs, run_on_cpu_data arg);
a19a21
 int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
a19a21
                                 int vq, bool assign);
a19a21
 #ifndef CONFIG_USER_ONLY
a19a21
diff --git a/target/s390x/kvm-stub.c b/target/s390x/kvm-stub.c
a19a21
index aa185017a2a..9970b5a8c70 100644
a19a21
--- a/target/s390x/kvm-stub.c
a19a21
+++ b/target/s390x/kvm-stub.c
a19a21
@@ -120,3 +120,7 @@ void kvm_s390_stop_interrupt(S390CPU *cpu)
a19a21
 void kvm_s390_restart_interrupt(S390CPU *cpu)
a19a21
 {
a19a21
 }
a19a21
+
a19a21
+void kvm_s390_set_diag318(CPUState *cs, uint64_t diag318_info)
a19a21
+{
a19a21
+}
a19a21
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
a19a21
index 6edb52f6d25..8d4406124b9 100644
a19a21
--- a/target/s390x/kvm.c
a19a21
+++ b/target/s390x/kvm.c
a19a21
@@ -1611,10 +1611,23 @@ static int handle_sw_breakpoint(S390CPU *cpu, struct kvm_run *run)
a19a21
     return -ENOENT;
a19a21
 }
a19a21
 
a19a21
+void kvm_s390_set_diag318(CPUState *cs, uint64_t diag318_info)
a19a21
+{
a19a21
+    CPUS390XState *env = &S390_CPU(cs)->env;
a19a21
+
a19a21
+    /* Feat bit is set only if KVM supports sync for diag318 */
a19a21
+    if (s390_has_feat(S390_FEAT_DIAG_318)) {
a19a21
+        env->diag318_info = diag318_info;
a19a21
+        cs->kvm_run->s.regs.diag318 = diag318_info;
a19a21
+        cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_DIAG318;
a19a21
+    }
a19a21
+}
a19a21
+
a19a21
 static void handle_diag_318(S390CPU *cpu, struct kvm_run *run)
a19a21
 {
a19a21
     uint64_t reg = (run->s390_sieic.ipa & 0x00f0) >> 4;
a19a21
     uint64_t diag318_info = run->s.regs.gprs[reg];
a19a21
+    CPUState *t;
a19a21
 
a19a21
     /*
a19a21
      * DIAG 318 can only be enabled with KVM support. As such, let's
a19a21
@@ -1622,13 +1635,12 @@ static void handle_diag_318(S390CPU *cpu, struct kvm_run *run)
a19a21
      */
a19a21
     if (!s390_has_feat(S390_FEAT_DIAG_318)) {
a19a21
         kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION);
a19a21
+        return;
a19a21
     }
a19a21
 
a19a21
-    cpu->env.diag318_info = diag318_info;
a19a21
-
a19a21
-    if (can_sync_regs(CPU(cpu), KVM_SYNC_DIAG318)) {
a19a21
-        run->s.regs.diag318 = diag318_info;
a19a21
-        run->kvm_dirty_regs |= KVM_SYNC_DIAG318;
a19a21
+    CPU_FOREACH(t) {
a19a21
+        run_on_cpu(t, s390_do_cpu_set_diag318,
a19a21
+                   RUN_ON_CPU_HOST_ULONG(diag318_info));
a19a21
     }
a19a21
 }
a19a21
 
a19a21
diff --git a/target/s390x/kvm_s390x.h b/target/s390x/kvm_s390x.h
a19a21
index 6ab17c81b73..25bbe98b251 100644
a19a21
--- a/target/s390x/kvm_s390x.h
a19a21
+++ b/target/s390x/kvm_s390x.h
a19a21
@@ -45,5 +45,6 @@ void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp);
a19a21
 void kvm_s390_crypto_reset(void);
a19a21
 void kvm_s390_restart_interrupt(S390CPU *cpu);
a19a21
 void kvm_s390_stop_interrupt(S390CPU *cpu);
a19a21
+void kvm_s390_set_diag318(CPUState *cs, uint64_t diag318_info);
a19a21
 
a19a21
 #endif /* KVM_S390X_H */
a19a21
-- 
a19a21
2.27.0
a19a21