Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45c9b47c authored by Tony Krowiak's avatar Tony Krowiak Committed by Christian Borntraeger
Browse files

KVM: s390/CPACF: Choose crypto control block format



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: default avatarTony Krowiak <akrowiak@linux.vnet.ibm.com>
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent f3d0bd6c
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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{
+47 −2
Original line number Diff line number Diff line
@@ -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;