KVM: s390/CPACF: Choose crypto control block format
authorTony Krowiak <akrowiak@linux.vnet.ibm.com>
Tue, 13 Jan 2015 16:33:26 +0000 (11:33 -0500)
committerChristian Borntraeger <borntraeger@de.ibm.com>
Mon, 9 Feb 2015 11:44:12 +0000 (12:44 +0100)
We need to specify a different format for the crypto control block
depending on whether the APXA facility is installed or not. Let's
test for it by executing the PQAP(QCI) function and use either a
format-1 or a format-2 crypto control block accordingly. This is a
host only change for z13 and does not affect the guest view.

Signed-off-by: Tony Krowiak <akrowiak@linux.vnet.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
arch/s390/include/asm/kvm_host.h
arch/s390/kvm/kvm-s390.c

index f79058e3fd98f1d5c9c5e6a5b0f45ec35ff0e146..77ae01444e982fa69ad872422744eae09fe91152 100644 (file)
@@ -163,6 +163,7 @@ struct kvm_s390_sie_block {
        __u64   tecmc;                  /* 0x00e8 */
        __u8    reservedf0[12];         /* 0x00f0 */
 #define CRYCB_FORMAT1 0x00000001
+#define CRYCB_FORMAT2 0x00000003
        __u32   crycbd;                 /* 0x00fc */
        __u64   gcr[16];                /* 0x0100 */
        __u64   gbea;                   /* 0x0180 */
@@ -516,6 +517,7 @@ struct kvm_s390_crypto_cb {
        __u8    reserved00[72];                 /* 0x0000 */
        __u8    dea_wrapping_key_mask[24];      /* 0x0048 */
        __u8    aes_wrapping_key_mask[32];      /* 0x0060 */
+       __u8    reserved80[128];                /* 0x0080 */
 };
 
 struct kvm_arch{
index 3acf08ba88e4ffecce9b0dbaa32f438d999543ae..deac47378f777b2864ae951b8c172662707c251f 100644 (file)
@@ -654,6 +654,52 @@ long kvm_arch_vm_ioctl(struct file *filp,
        return r;
 }
 
+static int kvm_s390_query_ap_config(u8 *config)
+{
+       u32 fcn_code = 0x04000000UL;
+       u32 cc;
+
+       asm volatile(
+               "lgr 0,%1\n"
+               "lgr 2,%2\n"
+               ".long 0xb2af0000\n"            /* PQAP(QCI) */
+               "ipm %0\n"
+               "srl %0,28\n"
+               : "=r" (cc)
+               : "r" (fcn_code), "r" (config)
+               : "cc", "0", "2", "memory"
+       );
+
+       return cc;
+}
+
+static int kvm_s390_apxa_installed(void)
+{
+       u8 config[128];
+       int cc;
+
+       if (test_facility(2) && test_facility(12)) {
+               cc = kvm_s390_query_ap_config(config);
+
+               if (cc)
+                       pr_err("PQAP(QCI) failed with cc=%d", cc);
+               else
+                       return config[0] & 0x40;
+       }
+
+       return 0;
+}
+
+static void kvm_s390_set_crycb_format(struct kvm *kvm)
+{
+       kvm->arch.crypto.crycbd = (__u32)(unsigned long) kvm->arch.crypto.crycb;
+
+       if (kvm_s390_apxa_installed())
+               kvm->arch.crypto.crycbd |= CRYCB_FORMAT2;
+       else
+               kvm->arch.crypto.crycbd |= CRYCB_FORMAT1;
+}
+
 static int kvm_s390_crypto_init(struct kvm *kvm)
 {
        if (!test_vfacility(76))
@@ -664,8 +710,7 @@ static int kvm_s390_crypto_init(struct kvm *kvm)
        if (!kvm->arch.crypto.crycb)
                return -ENOMEM;
 
-       kvm->arch.crypto.crycbd = (__u32) (unsigned long) kvm->arch.crypto.crycb |
-                                 CRYCB_FORMAT1;
+       kvm_s390_set_crycb_format(kvm);
 
        /* Disable AES/DEA protected key functions by default */
        kvm->arch.crypto.aes_kw = 0;