]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
KVM: s390: enable MSA9 keywrapping functions depending on cpu model
authorChristian Borntraeger <borntraeger@de.ibm.com>
Tue, 16 Jul 2019 06:54:00 +0000 (08:54 +0200)
committerSultan Alsawaf <sultan.alsawaf@canonical.com>
Wed, 24 Jul 2019 15:45:13 +0000 (09:45 -0600)
BugLink: https://bugs.launchpad.net/bugs/1836153
Instead of adding a new machine option to disable/enable the keywrapping
options of pckmo (like for AES and DEA) we can now use the CPU model to
decide. As ECC is also wrapped with the AES key we need that to be
enabled.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
(cherry picked from commit 8ec2fa52eac53bff7ef1cedbc4ad8af650ec937c)
Signed-off-by: Frank Heimes <frank.heimes@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
arch/s390/include/asm/kvm_host.h
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/vsie.c

index b5b73621e1a3be8fe3a74cec922a64d7b7573fcb..280097b11ad1cfde50e0e1213f30c3d1b0df49a9 100644 (file)
@@ -271,6 +271,7 @@ struct kvm_s390_sie_block {
 #define ECD_HOSTREGMGMT        0x20000000
 #define ECD_MEF                0x08000000
 #define ECD_ETOKENF    0x02000000
+#define ECD_ECC                0x00200000
        __u32   ecd;                    /* 0x01c8 */
        __u8    reserved1cc[18];        /* 0x01cc */
        __u64   pp;                     /* 0x01de */
index d1b574eb2a721129aabc5f4544a51a0d0a14aa91..fbf2c1342e753f29f6784542c14609e7db36ad46 100644 (file)
@@ -2735,6 +2735,25 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
        vcpu->arch.enabled_gmap = vcpu->arch.gmap;
 }
 
+static bool kvm_has_pckmo_subfunc(struct kvm *kvm, unsigned long nr)
+{
+       if (test_bit_inv(nr, (unsigned long *)&kvm->arch.model.subfuncs.pckmo) &&
+           test_bit_inv(nr, (unsigned long *)&kvm_s390_available_subfunc.pckmo))
+               return true;
+       return false;
+}
+
+static bool kvm_has_pckmo_ecc(struct kvm *kvm)
+{
+       /* At least one ECC subfunction must be present */
+       return kvm_has_pckmo_subfunc(kvm, 32) ||
+              kvm_has_pckmo_subfunc(kvm, 33) ||
+              kvm_has_pckmo_subfunc(kvm, 34) ||
+              kvm_has_pckmo_subfunc(kvm, 40) ||
+              kvm_has_pckmo_subfunc(kvm, 41);
+
+}
+
 static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
 {
        /*
@@ -2747,13 +2766,19 @@ static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
        vcpu->arch.sie_block->crycbd = vcpu->kvm->arch.crypto.crycbd;
        vcpu->arch.sie_block->ecb3 &= ~(ECB3_AES | ECB3_DEA);
        vcpu->arch.sie_block->eca &= ~ECA_APIE;
+       vcpu->arch.sie_block->ecd &= ~ECD_ECC;
 
        if (vcpu->kvm->arch.crypto.apie)
                vcpu->arch.sie_block->eca |= ECA_APIE;
 
        /* Set up protected key support */
-       if (vcpu->kvm->arch.crypto.aes_kw)
+       if (vcpu->kvm->arch.crypto.aes_kw) {
                vcpu->arch.sie_block->ecb3 |= ECB3_AES;
+               /* ecc is also wrapped with AES key */
+               if (kvm_has_pckmo_ecc(vcpu->kvm))
+                       vcpu->arch.sie_block->ecd |= ECD_ECC;
+       }
+
        if (vcpu->kvm->arch.crypto.dea_kw)
                vcpu->arch.sie_block->ecb3 |= ECB3_DEA;
 }
index b92de2b2b837cc304bcc02288c5d17433e0cd27e..35d464c99483a7c93563141da9f00f73914d1e1c 100644 (file)
@@ -282,6 +282,7 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
        const u32 crycb_addr = crycbd_o & 0x7ffffff8U;
        unsigned long *b1, *b2;
        u8 ecb3_flags;
+       u32 ecd_flags;
        int apie_h;
        int key_msk = test_kvm_facility(vcpu->kvm, 76);
        int fmt_o = crycbd_o & CRYCB_FORMAT_MASK;
@@ -314,7 +315,8 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
        /* we may only allow it if enabled for guest 2 */
        ecb3_flags = scb_o->ecb3 & vcpu->arch.sie_block->ecb3 &
                     (ECB3_AES | ECB3_DEA);
-       if (!ecb3_flags)
+       ecd_flags = scb_o->ecd & vcpu->arch.sie_block->ecd & ECD_ECC;
+       if (!ecb3_flags && !ecd_flags)
                goto end;
 
        /* copy only the wrapping keys */
@@ -323,6 +325,7 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
                return set_validity_icpt(scb_s, 0x0035U);
 
        scb_s->ecb3 |= ecb3_flags;
+       scb_s->ecd |= ecd_flags;
 
        /* xor both blocks in one run */
        b1 = (unsigned long *) vsie_page->crycb.dea_wrapping_key_mask;