|
@@ -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;
|