s390/kvm: fix diag318 propagation and reset functionality
authorCollin Walling <walling@linux.ibm.com>
Fri, 13 Nov 2020 22:10:22 +0000 (17:10 -0500)
committerCornelia Huck <cohuck@redhat.com>
Wed, 18 Nov 2020 15:57:48 +0000 (16:57 +0100)
The Control Program Name Code (CPNC) portion of the diag318
info must be set within the SIE block of each VCPU in the
configuration. The handler will iterate through each VCPU
and dirty the diag318_info reg to be synced with KVM on a
subsequent sync_regs call.

Additionally, the diag318 info resets must be handled via
userspace. As such, QEMU will reset this value for each
VCPU during a modified clear, load normal, and load clear
reset event.

Fixes: fabdada9357b ("s390: guest support for diagnose 0x318")
Signed-off-by: Collin Walling <walling@linux.ibm.com>
Message-Id: <20201113221022.257054-1-walling@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Janosch Frank <frankja@de.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
hw/s390x/s390-virtio-ccw.c
target/s390x/cpu.c
target/s390x/cpu.h
target/s390x/kvm-stub.c
target/s390x/kvm.c
target/s390x/kvm_s390x.h

index 22222c4fd5adb9275de29d1cb99cf28d53d56b82..4e140bbead936bfd3fe383c81276eb114abef555 100644 (file)
@@ -486,6 +486,10 @@ static void s390_machine_reset(MachineState *machine)
     default:
         g_assert_not_reached();
     }
+
+    CPU_FOREACH(t) {
+        run_on_cpu(t, s390_do_cpu_set_diag318, RUN_ON_CPU_HOST_ULONG(0));
+    }
     s390_ipl_clear_reset_request();
 }
 
index 66f5942b53012663ee209c3e4c684c7e00dd8ff8..7b66718c44232f5306e9fa8eb4d56520e3cf0513 100644 (file)
@@ -447,6 +447,13 @@ void s390_enable_css_support(S390CPU *cpu)
         kvm_s390_enable_css_support(cpu);
     }
 }
+
+void s390_do_cpu_set_diag318(CPUState *cs, run_on_cpu_data arg)
+{
+    if (kvm_enabled()) {
+        kvm_s390_set_diag318(cs, arg.host_ulong);
+    }
+}
 #endif
 
 static gchar *s390_gdb_arch_name(CPUState *cs)
index f875ebf0f491d734b19f6132b469af14c038bf42..60d434d5edd55c59cfe7e345967c7a616263b55f 100644 (file)
@@ -769,6 +769,7 @@ int s390_set_memory_limit(uint64_t new_limit, uint64_t *hw_limit);
 void s390_set_max_pagesize(uint64_t pagesize, Error **errp);
 void s390_cmma_reset(void);
 void s390_enable_css_support(S390CPU *cpu);
+void s390_do_cpu_set_diag318(CPUState *cs, run_on_cpu_data arg);
 int s390_assign_subch_ioeventfd(EventNotifier *notifier, uint32_t sch_id,
                                 int vq, bool assign);
 #ifndef CONFIG_USER_ONLY
index aa185017a2a886ca300fa75747edc242cab32ce2..9970b5a8c7056f1a9c433e593c47f8c5a8fa66cb 100644 (file)
@@ -120,3 +120,7 @@ void kvm_s390_stop_interrupt(S390CPU *cpu)
 void kvm_s390_restart_interrupt(S390CPU *cpu)
 {
 }
+
+void kvm_s390_set_diag318(CPUState *cs, uint64_t diag318_info)
+{
+}
index baa070fdf7f9351718412a24927126aad113c653..b8385e6b95d365e089c4c756ef8933fa2c4f09e2 100644 (file)
@@ -1611,10 +1611,23 @@ static int handle_sw_breakpoint(S390CPU *cpu, struct kvm_run *run)
     return -ENOENT;
 }
 
+void kvm_s390_set_diag318(CPUState *cs, uint64_t diag318_info)
+{
+    CPUS390XState *env = &S390_CPU(cs)->env;
+
+    /* Feat bit is set only if KVM supports sync for diag318 */
+    if (s390_has_feat(S390_FEAT_DIAG_318)) {
+        env->diag318_info = diag318_info;
+        cs->kvm_run->s.regs.diag318 = diag318_info;
+        cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_DIAG318;
+    }
+}
+
 static void handle_diag_318(S390CPU *cpu, struct kvm_run *run)
 {
     uint64_t reg = (run->s390_sieic.ipa & 0x00f0) >> 4;
     uint64_t diag318_info = run->s.regs.gprs[reg];
+    CPUState *t;
 
     /*
      * DIAG 318 can only be enabled with KVM support. As such, let's
@@ -1622,13 +1635,12 @@ static void handle_diag_318(S390CPU *cpu, struct kvm_run *run)
      */
     if (!s390_has_feat(S390_FEAT_DIAG_318)) {
         kvm_s390_program_interrupt(cpu, PGM_SPECIFICATION);
+        return;
     }
 
-    cpu->env.diag318_info = diag318_info;
-
-    if (can_sync_regs(CPU(cpu), KVM_SYNC_DIAG318)) {
-        run->s.regs.diag318 = diag318_info;
-        run->kvm_dirty_regs |= KVM_SYNC_DIAG318;
+    CPU_FOREACH(t) {
+        run_on_cpu(t, s390_do_cpu_set_diag318,
+                   RUN_ON_CPU_HOST_ULONG(diag318_info));
     }
 }
 
index 6ab17c81b73a0011e32213552698a15cbc08a8d9..25bbe98b25141a81f3b1e1edd6831deb68bec347 100644 (file)
@@ -45,5 +45,6 @@ void kvm_s390_set_max_pagesize(uint64_t pagesize, Error **errp);
 void kvm_s390_crypto_reset(void);
 void kvm_s390_restart_interrupt(S390CPU *cpu);
 void kvm_s390_stop_interrupt(S390CPU *cpu);
+void kvm_s390_set_diag318(CPUState *cs, uint64_t diag318_info);
 
 #endif /* KVM_S390X_H */