KVM: s390: vsie: Refactor handle_stfle

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>
This commit is contained in:
Nina Schoetterl-Glausch
2026-06-12 14:23:03 +02:00
committed by Claudio Imbrenda
parent a8ceca7d8c
commit bf8f3cec93
2 changed files with 38 additions and 16 deletions

View 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];
};

View 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;
}