__u8    reserved60;             /* 0x0060 */
        __u8    ecb;                    /* 0x0061 */
        __u8    ecb2;                   /* 0x0062 */
-       __u8    reserved63[1];          /* 0x0063 */
+#define ECB3_AES 0x04
+#define ECB3_DEA 0x08
+       __u8    ecb3;                   /* 0x0063 */
        __u32   scaol;                  /* 0x0064 */
        __u8    reserved68[4];          /* 0x0068 */
        __u32   todpr;                  /* 0x006c */
 struct kvm_s390_crypto {
        struct kvm_s390_crypto_cb *crycb;
        __u32 crycbd;
+       __u8 aes_kw;
+       __u8 dea_kw;
 };
 
 struct kvm_s390_crypto_cb {
-       __u8    reserved00[128];                /* 0x0000 */
+       __u8    reserved00[72];                 /* 0x0000 */
+       __u8    dea_wrapping_key_mask[24];      /* 0x0048 */
+       __u8    aes_wrapping_key_mask[32];      /* 0x0060 */
 };
 
 struct kvm_arch{
 
 /* kvm attr_group  on vm fd */
 #define KVM_S390_VM_MEM_CTRL           0
 #define KVM_S390_VM_TOD                        1
+#define KVM_S390_VM_CRYPTO             2
 
 /* kvm attributes for mem_ctrl */
 #define KVM_S390_VM_MEM_ENABLE_CMMA    0
 #define KVM_S390_VM_TOD_LOW            0
 #define KVM_S390_VM_TOD_HIGH           1
 
+/* kvm attributes for crypto */
+#define KVM_S390_VM_CRYPTO_ENABLE_AES_KW       0
+#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
+
 /* for KVM_GET_REGS and KVM_SET_REGS */
 struct kvm_regs {
        /* general purpose regs for s390 */
 
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/module.h>
+#include <linux/random.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
 #include <asm/asm-offsets.h>
        return ret;
 }
 
+static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu);
+
+static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr)
+{
+       struct kvm_vcpu *vcpu;
+       int i;
+
+       if (!test_vfacility(76))
+               return -EINVAL;
+
+       mutex_lock(&kvm->lock);
+       switch (attr->attr) {
+       case KVM_S390_VM_CRYPTO_ENABLE_AES_KW:
+               get_random_bytes(
+                       kvm->arch.crypto.crycb->aes_wrapping_key_mask,
+                       sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
+               kvm->arch.crypto.aes_kw = 1;
+               break;
+       case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW:
+               get_random_bytes(
+                       kvm->arch.crypto.crycb->dea_wrapping_key_mask,
+                       sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
+               kvm->arch.crypto.dea_kw = 1;
+               break;
+       case KVM_S390_VM_CRYPTO_DISABLE_AES_KW:
+               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));
+               break;
+       case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW:
+               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));
+               break;
+       default:
+               mutex_unlock(&kvm->lock);
+               return -ENXIO;
+       }
+
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               kvm_s390_vcpu_crypto_setup(vcpu);
+               exit_sie(vcpu);
+       }
+       mutex_unlock(&kvm->lock);
+       return 0;
+}
+
 static int kvm_s390_set_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
 {
        u8 gtod_high;
        case KVM_S390_VM_TOD:
                ret = kvm_s390_set_tod(kvm, attr);
                break;
+       case KVM_S390_VM_CRYPTO:
+               ret = kvm_s390_vm_set_crypto(kvm, attr);
+               break;
        default:
                ret = -ENXIO;
                break;
                        break;
                }
                break;
+       case KVM_S390_VM_CRYPTO:
+               switch (attr->attr) {
+               case KVM_S390_VM_CRYPTO_ENABLE_AES_KW:
+               case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW:
+               case KVM_S390_VM_CRYPTO_DISABLE_AES_KW:
+               case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW:
+                       ret = 0;
+                       break;
+               default:
+                       ret = -ENXIO;
+                       break;
+               }
+               break;
        default:
                ret = -ENXIO;
                break;
        kvm->arch.crypto.crycbd = (__u32) (unsigned long) kvm->arch.crypto.crycb |
                                  CRYCB_FORMAT1;
 
+       /* Disable AES/DEA protected key functions by default */
+       kvm->arch.crypto.aes_kw = 0;
+       kvm->arch.crypto.dea_kw = 0;
+
        return 0;
 }
 
        if (!test_vfacility(76))
                return;
 
+       vcpu->arch.sie_block->ecb3 &= ~(ECB3_AES | ECB3_DEA);
+
+       if (vcpu->kvm->arch.crypto.aes_kw)
+               vcpu->arch.sie_block->ecb3 |= ECB3_AES;
+       if (vcpu->kvm->arch.crypto.dea_kw)
+               vcpu->arch.sie_block->ecb3 |= ECB3_DEA;
+
        vcpu->arch.sie_block->crycbd = vcpu->kvm->arch.crypto.crycbd;
 }