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

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