From: Tony Krowiak <[email protected]>

Introduces two new VM crypto device attributes (KVM_S390_VM_CRYPTO)
to enable or disable AP instruction interpretation from userspace
via the KVM_SET_DEVICE_ATTR ioctl:

* The KVM_S390_VM_CRYPTO_ENABLE_APIE attribute enables hardware
  interpretation of AP instructions executed on the guest.

* The KVM_S390_VM_CRYPTO_DISABLE_APIE attribute disables hardware
  interpretation of AP instructions executed on the guest. In this
  case the instructions will be intercepted and pass through to
  the guest.

Signed-off-by: Tony Krowiak <[email protected]>
---
 arch/s390/include/asm/kvm_host.h |    1 +
 arch/s390/include/uapi/asm/kvm.h |    2 ++
 arch/s390/kvm/kvm-s390.c         |   27 +++++++++++++++++++++++----
 3 files changed, 26 insertions(+), 4 deletions(-)

diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index b32bd1b..36d3531 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -719,6 +719,7 @@ struct kvm_s390_crypto {
        __u32 crycbd;
        __u8 aes_kw;
        __u8 dea_kw;
+       __u8 apie;
 };
 
 #define APCB0_MASK_SIZE 1
diff --git a/arch/s390/include/uapi/asm/kvm.h b/arch/s390/include/uapi/asm/kvm.h
index 8c23afc..a8dbd90 100644
--- a/arch/s390/include/uapi/asm/kvm.h
+++ b/arch/s390/include/uapi/asm/kvm.h
@@ -161,6 +161,8 @@ struct kvm_s390_vm_cpu_subfunc {
 #define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW       1
 #define KVM_S390_VM_CRYPTO_DISABLE_AES_KW      2
 #define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW      3
+#define KVM_S390_VM_CRYPTO_ENABLE_APIE         4
+#define KVM_S390_VM_CRYPTO_DISABLE_APIE                5
 
 /* kvm attributes for migration mode */
 #define KVM_S390_VM_MIGRATION_STOP     0
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 2cdd980..286c2e0 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -856,12 +856,11 @@ void kvm_s390_vcpu_crypto_reset_all(struct kvm *kvm)
 
 static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr 
*attr)
 {
-       if (!test_kvm_facility(kvm, 76))
-               return -EINVAL;
-
        mutex_lock(&kvm->lock);
        switch (attr->attr) {
        case KVM_S390_VM_CRYPTO_ENABLE_AES_KW:
+               if (!test_kvm_facility(kvm, 76))
+                       return -EINVAL;
                get_random_bytes(
                        kvm->arch.crypto.crycb->aes_wrapping_key_mask,
                        sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
@@ -869,6 +868,8 @@ static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct 
kvm_device_attr *attr)
                VM_EVENT(kvm, 3, "%s", "ENABLE: AES keywrapping support");
                break;
        case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW:
+               if (!test_kvm_facility(kvm, 76))
+                       return -EINVAL;
                get_random_bytes(
                        kvm->arch.crypto.crycb->dea_wrapping_key_mask,
                        sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
@@ -876,17 +877,31 @@ static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct 
kvm_device_attr *attr)
                VM_EVENT(kvm, 3, "%s", "ENABLE: DEA keywrapping support");
                break;
        case KVM_S390_VM_CRYPTO_DISABLE_AES_KW:
+               if (!test_kvm_facility(kvm, 76))
+                       return -EINVAL;
                kvm->arch.crypto.aes_kw = 0;
                memset(kvm->arch.crypto.crycb->aes_wrapping_key_mask, 0,
                        sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
                VM_EVENT(kvm, 3, "%s", "DISABLE: AES keywrapping support");
                break;
        case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW:
+               if (!test_kvm_facility(kvm, 76))
+                       return -EINVAL;
                kvm->arch.crypto.dea_kw = 0;
                memset(kvm->arch.crypto.crycb->dea_wrapping_key_mask, 0,
                        sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
                VM_EVENT(kvm, 3, "%s", "DISABLE: DEA keywrapping support");
                break;
+       case KVM_S390_VM_CRYPTO_ENABLE_APIE:
+               if (!ap_instructions_available()) {
+                       mutex_unlock(&kvm->lock);
+                       return -EOPNOTSUPP;
+               }
+               kvm->arch.crypto.apie = 1;
+               break;
+       case KVM_S390_VM_CRYPTO_DISABLE_APIE:
+               kvm->arch.crypto.apie = 0;
+               break;
        default:
                mutex_unlock(&kvm->lock);
                return -ENXIO;
@@ -1493,6 +1508,8 @@ static int kvm_s390_vm_has_attr(struct kvm *kvm, struct 
kvm_device_attr *attr)
                case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW:
                case KVM_S390_VM_CRYPTO_DISABLE_AES_KW:
                case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW:
+               case KVM_S390_VM_CRYPTO_ENABLE_APIE:
+               case KVM_S390_VM_CRYPTO_DISABLE_APIE:
                        ret = 0;
                        break;
                default:
@@ -2062,6 +2079,7 @@ static u64 kvm_s390_get_initial_cpuid(void)
 static void kvm_s390_crypto_init(struct kvm *kvm)
 {
        kvm->arch.crypto.crycb = &kvm->arch.sie_page2->crycb;
+       kvm->arch.crypto.apie = 0;
        kvm_s390_set_crycb_format(kvm);
 
        if (!test_kvm_facility(kvm, 76))
@@ -2602,8 +2620,9 @@ 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;
 
-       if (test_kvm_cpu_feat(vcpu->kvm, KVM_S390_VM_CPU_FEAT_AP))
+       if (vcpu->kvm->arch.crypto.apie)
                vcpu->arch.sie_block->eca |= ECA_APIE;
 
        /* Set up protected key support */
-- 
1.7.1

Reply via email to