]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: s390: vsie: Refactor handle_stfle
authorNina Schoetterl-Glausch <nsg@linux.ibm.com>
Fri, 12 Jun 2026 12:23:03 +0000 (14:23 +0200)
committerClaudio Imbrenda <imbrenda@linux.ibm.com>
Fri, 12 Jun 2026 13:13:27 +0000 (15:13 +0200)
Use switch case in anticipation of handling format-1 and format-2
facility list designations in the future.
As the alternate STFLE facilities are not enabled, only case 0 is
possible.
No functional change intended.

Signed-off-by: Nina Schoetterl-Glausch <nsg@linux.ibm.com>
Co-developed-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
Signed-off-by: Christoph Schlameuss <schlameuss@linux.ibm.com>
Reviewed-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Signed-off-by: Claudio Imbrenda <imbrenda@linux.ibm.com>
Message-ID: <20260612-vsie-alter-stfle-fac-v4-3-74f0e1559929@linux.ibm.com>

arch/s390/include/uapi/asm/kvm.h
arch/s390/kvm/vsie.c

index 60345dd2cba2d611b76f8b5c70eab8f0abab4b9b..4192769b5ce069ba28d00d7cf1c4f1b34037d633 100644 (file)
@@ -444,6 +444,7 @@ struct kvm_s390_vm_cpu_machine {
 #define KVM_S390_VM_CPU_FEAT_PFMFI     11
 #define KVM_S390_VM_CPU_FEAT_SIGPIF    12
 #define KVM_S390_VM_CPU_FEAT_KSS       13
+#define KVM_S390_VM_CPU_FEAT_ASTFLEIE2 14
 struct kvm_s390_vm_cpu_feat {
        __u64 feat[16];
 };
index e5a23f1c97495a6ed087cd1b0828e9c777b7316d..c7dcdd460dd1d2639902e1b67232ea8ec57b6416 100644 (file)
@@ -6,12 +6,15 @@
  *
  *    Author(s): David Hildenbrand <dahi@linux.vnet.ibm.com>
  */
+#include <linux/align.h>
 #include <linux/vmalloc.h>
 #include <linux/kvm_host.h>
 #include <linux/bug.h>
+#include <linux/compiler.h>
 #include <linux/list.h>
 #include <linux/bitmap.h>
 #include <linux/sched/signal.h>
+#include <linux/stddef.h>
 #include <linux/io.h>
 #include <linux/mman.h>
 
@@ -1000,6 +1003,23 @@ static void retry_vsie_icpt(struct vsie_page *vsie_page)
        clear_vsie_icpt(vsie_page);
 }
 
+static int handle_stfle_0(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page,
+                         u32 fac_list_origin)
+{
+       struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s;
+
+       /*
+        * format-0 -> size of nested guest's facility list == guest's size
+        * guest's size == host's size, since STFLE is interpretatively executed
+        * using a format-0 for the guest, too.
+        */
+       if (read_guest_real(vcpu, fac_list_origin, &vsie_page->fac,
+                           stfle_size() * sizeof(u64)))
+               return set_validity_icpt(scb_s, 0x1090U);
+       scb_s->fac = (u32)virt_to_phys(&vsie_page->fac);
+       return 0;
+}
+
 /*
  * Try to shadow + enable the guest 2 provided facility list.
  * Retry instruction execution if enabled for and provided by guest 2.
@@ -1009,29 +1029,30 @@ static void retry_vsie_icpt(struct vsie_page *vsie_page)
  */
 static int handle_stfle(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
 {
-       struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s;
-       __u32 fac = READ_ONCE(vsie_page->scb_o->fac);
+       bool has_astfleie2 = test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_ASTFLEIE2);
+       u32 fac = READ_ONCE(vsie_page->scb_o->fac);
+       int format_mask, format;
+       u32 origin;
+
+       BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct vsie_page, fac), 8));
 
-       /*
-        * Alternate-STFLE-Interpretive-Execution facilities are not supported
-        * -> format-0 flcb
-        */
        if (fac && test_kvm_facility(vcpu->kvm, 7)) {
                retry_vsie_icpt(vsie_page);
                /*
                 * The facility list origin (FLO) is in bits 1 - 28 of the FLD
                 * so we need to mask here before reading.
                 */
-               fac = fac & 0x7ffffff8U;
-               /*
-                * format-0 -> size of nested guest's facility list == guest's size
-                * guest's size == host's size, since STFLE is interpretatively executed
-                * using a format-0 for the guest, too.
-                */
-               if (read_guest_real(vcpu, fac, &vsie_page->fac,
-                                   stfle_size() * sizeof(u64)))
-                       return set_validity_icpt(scb_s, 0x1090U);
-               scb_s->fac = (u32)virt_to_phys(&vsie_page->fac);
+               origin = fac & 0x7ffffff8U;
+               format_mask = has_astfleie2 ? 3 : 0;
+               format = fac & format_mask;
+               switch (format) {
+               case 0:
+                       return handle_stfle_0(vcpu, vsie_page, origin);
+               case 1:
+               case 2:
+               case 3:
+                       unreachable();
+               }
        }
        return 0;
 }