From: Nina Schoetterl-Glausch Implement shadowing of format-2 facility list when running in VSIE. ASTFLEIE2 is available since IBM z16. To function G1 has to run this KVM code and G1 and G2 have to run QEMU with ASTFLEIE2 support. Signed-off-by: Nina Schoetterl-Glausch Co-developed-by: Christoph Schlameuss Signed-off-by: Christoph Schlameuss --- arch/s390/kvm/kvm-s390.c | 2 ++ arch/s390/kvm/vsie.c | 33 +++++++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 797d77174fe692c1e63cacc38f251dd3bc98a23b..3f922b96356aa3c5ed653758fbd05509ba5b337f 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -464,6 +464,8 @@ static void __init kvm_s390_cpu_feat_init(void) allow_cpu_feat(KVM_S390_VM_CPU_FEAT_IBS); if (sclp.has_kss) allow_cpu_feat(KVM_S390_VM_CPU_FEAT_KSS); + if (sclp.has_astfleie2) + allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ASTFLEIE2); /* * KVM_S390_VM_CPU_FEAT_SKEY: Wrong shadow of PTE.I bits will make * all skey handling functions read/set the skey from the PGSTE diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index 3a90d4011bf06c35416ca2ea81eab1f0f71e8be4..4396abeb58ed577c49fa9b98de1c630d6759e9a2 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -65,9 +65,9 @@ struct vsie_page { * looked up by other CPUs. */ unsigned long flags; /* 0x0260 */ - __u8 reserved[0x0700 - 0x0268]; /* 0x0268 */ - struct kvm_s390_crypto_cb crycb; /* 0x0700 */ - __u8 fac[S390_ARCH_FAC_LIST_SIZE_BYTE]; /* 0x0800 */ + __u8 reserved[0x06f8 - 0x0268]; /* 0x0268 */ + struct kvm_s390_crypto_cb crycb; /* 0x06f8 */ + __u8 fac[8 + S390_ARCH_FAC_LIST_SIZE_BYTE];/* 0x0800 */ }; /** @@ -1028,6 +1028,29 @@ static int handle_stfle_0(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, return 0; } +static int handle_stfle_2(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, + u32 fac_list_origin) +{ + struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; + u8 *shadow_fac = &vsie_page->fac[0]; + u64 len; + + if (read_guest_real(vcpu, fac_list_origin, &len, sizeof(len))) + return set_validity_icpt(scb_s, 0x1090U); + fac_list_origin += sizeof(len); + len = (len & 0xff); + memcpy(shadow_fac, &len, sizeof(len)); /* discard reserved bits */ + shadow_fac += sizeof(len); + len += 1; + /* assert no overflow with maximum len */ + BUILD_BUG_ON(sizeof(vsie_page->fac) < 257 * sizeof(u64)); + if (read_guest_real(vcpu, fac_list_origin, shadow_fac, len * sizeof(u64))) + return set_validity_icpt(scb_s, 0x1090U); + BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct vsie_page, fac), 8)); + scb_s->fac = (u32)virt_to_phys(&vsie_page->fac) | 2; + return 0; +} + /* * Try to shadow + enable the guest 2 provided facility list. * Retry instruction execution if enabled for and provided by guest 2. @@ -1057,9 +1080,11 @@ static int handle_stfle(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) case 0: return handle_stfle_0(vcpu, vsie_page, fac_list_origin); case 1: + return set_validity_icpt(&vsie_page->scb_s, 0x1330U); case 2: + return handle_stfle_2(vcpu, vsie_page, fac_list_origin); case 3: - unreachable(); + return set_validity_icpt(&vsie_page->scb_s, 0x1330U); } } return 0; -- 2.53.0