Received: by 2002:ac0:a581:0:0:0:0:0 with SMTP id m1-v6csp1250536imm; Fri, 29 Jun 2018 14:22:33 -0700 (PDT) X-Google-Smtp-Source: AAOMgpezJ7ddU01lJyPXB5/86DVC366kqw1bIxO7jK0jFMMXLW60YjMlopIz+nUAh2uWsCkuceFH X-Received: by 2002:a65:40cd:: with SMTP id u13-v6mr2025457pgp.334.1530307352961; Fri, 29 Jun 2018 14:22:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1530307352; cv=none; d=google.com; s=arc-20160816; b=ldpCY1F7RvSrJlsUw/3LUxDdOrI4PuI2rE36iUyyOrzdXMbozNpeUojtExfyIWaM/F UnvS/6ResRrFa7bi7S6zd6nTSCJ4FOVJddLBGTHVK+N7sAjf5puw+4WmbO2mV4/rLqHL 0swXmw3c/Enui5zrynx7C4hT+4JJ4MWGQeAdVwYWGiE3SNzh5+KVCjFr+gcFoQCXIA4L V6MWjeIcU17e6+hHZUjMrDxaSYjgTetjssixOHMagJVpW02Z9OzvJBkUsKuvyXVmALAv arMtmNHMLy3hRCwcybSvrDHqG+sIeuvuYtU/gVb8tTFlhXkg55pYMv3fKMN5C/6Srl5A 2HJA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:references:in-reply-to:date :subject:cc:to:from:arc-authentication-results; bh=ANIz94/qRXBO8YaRwe43/mCHgE2KidOWGq2BxWV0jmo=; b=BOTWQXXqdkIHawzAsRo8MMCu/rOQOiMczGtspuapuAtgXCaSCNksPlRgURaymlIzDm qYwiljksm8fi1cV2cdJQrQ0LfJf83tnL8JK7gZVMAbQy6jD4uwYtOxkKqDympQsJ+BKi pjNxuFR1HpN/DxEFkX6dGtwPd3HeJNaTENTgxYaTpLDg0PysIYSlq9Wrlfqx5r2On+R2 /j1DAHEyrpSXL1E1qqhCXcPvkEnWbVdGoYhRovqrPRl0sAadvuLAVZBMz+narEVjRBfJ Z96SU9XKbhl4h20ehId00Wa9vpSSBJat6R0V4tc2z8sFVBI0LCp28Wce+wQFZeIeM6Zq /kcg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id m13-v6si9595104pfh.92.2018.06.29.14.22.18; Fri, 29 Jun 2018 14:22:32 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S966553AbeF2VM5 (ORCPT + 99 others); Fri, 29 Jun 2018 17:12:57 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:52014 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S966222AbeF2VMQ (ORCPT ); Fri, 29 Jun 2018 17:12:16 -0400 Received: from pps.filterd (m0098416.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w5TL9GkL135543 for ; Fri, 29 Jun 2018 17:12:15 -0400 Received: from e11.ny.us.ibm.com (e11.ny.us.ibm.com [129.33.205.201]) by mx0b-001b2d01.pphosted.com with ESMTP id 2jwrsrr1ry-1 (version=TLSv1.2 cipher=AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 29 Jun 2018 17:12:15 -0400 Received: from localhost by e11.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Fri, 29 Jun 2018 17:12:15 -0400 Received: from b01cxnp22035.gho.pok.ibm.com (9.57.198.25) by e11.ny.us.ibm.com (146.89.104.198) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; (version=TLSv1/SSLv3 cipher=AES256-GCM-SHA384 bits=256/256) Fri, 29 Jun 2018 17:12:12 -0400 Received: from b01ledav002.gho.pok.ibm.com (b01ledav002.gho.pok.ibm.com [9.57.199.107]) by b01cxnp22035.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w5TLCAxm8192612 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Fri, 29 Jun 2018 21:12:10 GMT Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 02E9F124054; Fri, 29 Jun 2018 18:13:40 -0400 (EDT) Received: from b01ledav002.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id ED98112405E; Fri, 29 Jun 2018 18:13:38 -0400 (EDT) Received: from localhost.localdomain (unknown [9.85.157.42]) by b01ledav002.gho.pok.ibm.com (Postfix) with ESMTPS; Fri, 29 Jun 2018 18:13:38 -0400 (EDT) From: Tony Krowiak To: linux-s390@vger.kernel.org, linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: freude@de.ibm.com, schwidefsky@de.ibm.com, heiko.carstens@de.ibm.com, borntraeger@de.ibm.com, cohuck@redhat.com, kwankhede@nvidia.com, bjsdjshi@linux.vnet.ibm.com, pbonzini@redhat.com, alex.williamson@redhat.com, pmorel@linux.vnet.ibm.com, alifm@linux.vnet.ibm.com, mjrosato@linux.vnet.ibm.com, jjherne@linux.vnet.ibm.com, thuth@redhat.com, pasic@linux.vnet.ibm.com, berrange@redhat.com, fiuczy@linux.vnet.ibm.com, buendgen@de.ibm.com, akrowiak@linux.vnet.ibm.com, Pierre Morel , Tony Krowiak Subject: [PATCH v6 20/21] KVM: s390: Handling of Cypto control block in VSIE Date: Fri, 29 Jun 2018 17:11:22 -0400 X-Mailer: git-send-email 1.7.1 In-Reply-To: <1530306683-7270-1-git-send-email-akrowiak@linux.vnet.ibm.com> References: <1530306683-7270-1-git-send-email-akrowiak@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18062921-2213-0000-0000-000002C21EA5 X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00009278; HX=3.00000241; KW=3.00000007; PH=3.00000004; SC=3.00000266; SDB=6.01054190; UDB=6.00540581; IPR=6.00832111; MB=3.00021933; MTD=3.00000008; XFM=3.00000015; UTC=2018-06-29 21:12:15 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18062921-2214-0000-0000-00005AA78698 Message-Id: <1530306683-7270-21-git-send-email-akrowiak@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10434:,, definitions=2018-06-29_10:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=0 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 mlxscore=0 impostorscore=0 mlxlogscore=999 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1806210000 definitions=main-1806290224 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Pierre Morel Shadowing the crypto control block now supports APCB shadowing. AP instruction interpretation for guest 3 through ECA.28 is shadowed when guest 2 ECA.28 is set. CRYCB is shadowed for APCB and wrapping keys. CRYCB format 0 is now supported for both guests 2 and 3. Shadow CRYCB always uses the guest 2 CRYCB format and it follows that: * Guest 3 CRYCB format 0 is supported with guest 2 CRYCB format 0,1 or 2 * Guest 3 CRYCB format 1 is supported with guest 2 CRYCB format 1 or 2 * Guest 3 CRYCB format 2 is supported with guest 2 CRYCB format 2 Signed-off-by: Pierre Morel Signed-off-by: Tony Krowiak --- arch/s390/kvm/vsie.c | 224 ++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 200 insertions(+), 24 deletions(-) diff --git a/arch/s390/kvm/vsie.c b/arch/s390/kvm/vsie.c index 84c89cb..25c8ccc 100644 --- a/arch/s390/kvm/vsie.c +++ b/arch/s390/kvm/vsie.c @@ -136,17 +136,8 @@ static int prepare_cpuflags(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) return 0; } -/* - * Create a shadow copy of the crycb block and setup key wrapping, if - * requested for guest 3 and enabled for guest 2. - * - * We only accept format-1 (no AP in g2), but convert it into format-2 - * There is nothing to do for format-0. - * - * Returns: - 0 if shadowed or nothing to do - * - > 0 if control has to be given to guest 2 - */ -static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) +/* Copy keys into shadow crycb, is only called if MSA3 is available. */ +static int copy_key_masks(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) { struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; struct kvm_s390_sie_block *scb_o = vsie_page->scb_o; @@ -155,30 +146,17 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) unsigned long *b1, *b2; u8 ecb3_flags; - scb_s->crycbd = 0; - if (!(crycbd_o & vcpu->arch.sie_block->crycbd & CRYCB_FORMAT1)) - return 0; - /* format-1 is supported with message-security-assist extension 3 */ - if (!test_kvm_facility(vcpu->kvm, 76)) - return 0; /* we may only allow it if enabled for guest 2 */ ecb3_flags = scb_o->ecb3 & vcpu->arch.sie_block->ecb3 & (ECB3_AES | ECB3_DEA); if (!ecb3_flags) return 0; - if ((crycb_addr & PAGE_MASK) != ((crycb_addr + 128) & PAGE_MASK)) - return set_validity_icpt(scb_s, 0x003CU); - else if (!crycb_addr) - return set_validity_icpt(scb_s, 0x0039U); - /* copy only the wrapping keys */ if (read_guest_real(vcpu, crycb_addr + 72, &vsie_page->crycb, 56)) return set_validity_icpt(scb_s, 0x0035U); scb_s->ecb3 |= ecb3_flags; - scb_s->crycbd = ((__u32)(__u64) &vsie_page->crycb) | CRYCB_FORMAT1 | - CRYCB_FORMAT2; /* xor both blocks in one run */ b1 = (unsigned long *) vsie_page->crycb.dea_wrapping_key_mask; @@ -189,6 +167,204 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) return 0; } +/* Copy masks into apcb when g2 and g3 use format 1 */ +static int copy_apcb1(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) +{ + struct kvm_s390_sie_block *scb_o = vsie_page->scb_o; + struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; + const uint32_t crycbd_o = READ_ONCE(scb_o->crycbd); + const u32 crycb_o = crycbd_o & 0x7ffffff8U; + struct kvm_s390_crypto_cb *crycb_h = &vcpu->kvm->arch.sie_page2->crycb; + struct kvm_s390_crypto_cb *crycb_s = &vsie_page->crycb; + unsigned long *apcb_s = (unsigned long *) &crycb_s->apcb1; + unsigned long *apcb_h = (unsigned long *) &crycb_h->apcb1; + int i; + u32 src; + + src = crycb_o + offsetof(struct kvm_s390_crypto_cb, apcb1); + if (read_guest_real(vcpu, src, apcb_s, sizeof(struct kvm_s390_apcb1))) + return set_validity_icpt(scb_s, 0x0035U); + + for (i = 0; i < sizeof(struct kvm_s390_apcb1); i += sizeof(*apcb_s)) + *apcb_s &= *apcb_h; + + return 0; +} + +/* + * Copy masks into apcb when g2 use format 1 and g3 use format 0 + * In this case the shadow APCB uses format 1 + */ +static int copy_apcb01(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) +{ + struct kvm_s390_sie_block *scb_o = vsie_page->scb_o; + struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; + const uint32_t crycbd_o = READ_ONCE(scb_o->crycbd); + const u32 crycb_o = crycbd_o & 0x7ffffff8U; + struct kvm_s390_apcb1 *apcb_h = &vcpu->kvm->arch.sie_page2->crycb.apcb1; + struct kvm_s390_apcb1 *apcb_s = &vsie_page->crycb.apcb1; + u32 src; + + memset(apcb_s, 0, sizeof(*apcb_s)); + + src = crycb_o + offsetof(struct kvm_s390_crypto_cb, apcb0.apm[0]); + if (read_guest_real(vcpu, src, &apcb_s->apm[0], sizeof(__u64))) + return set_validity_icpt(scb_s, 0x0035U); + + src = crycb_o + offsetof(struct kvm_s390_crypto_cb, apcb0.aqm[0]); + if (read_guest_real(vcpu, src, &apcb_s->aqm[0], sizeof(__u64))) + return set_validity_icpt(scb_s, 0x0035U); + + src = crycb_o + offsetof(struct kvm_s390_crypto_cb, apcb0.adm[0]); + if (read_guest_real(vcpu, src, &apcb_s->adm[0], sizeof(__u64))) + return set_validity_icpt(scb_s, 0x0035U); + + apcb_s->apm[0] &= apcb_h->apm[0]; + apcb_s->aqm[0] &= apcb_h->aqm[0]; + apcb_s->adm[0] &= apcb_h->adm[0]; + + return 0; +} + +/* Copy masks into apcb when g2 and g3 use format 0 */ +static int copy_apcb0(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) +{ + struct kvm_s390_sie_block *scb_o = vsie_page->scb_o; + struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; + const uint32_t crycbd_o = READ_ONCE(scb_o->crycbd); + const u32 crycb_o = crycbd_o & 0x7ffffff8U; + struct kvm_s390_apcb0 *apcb_h = &vcpu->kvm->arch.sie_page2->crycb.apcb0; + struct kvm_s390_apcb0 *apcb_s = &vsie_page->crycb.apcb0; + u32 src; + + src = crycb_o + offsetof(struct kvm_s390_crypto_cb, apcb0.apm[0]); + if (read_guest_real(vcpu, src, &apcb_s->apm[0], sizeof(__u64))) + return set_validity_icpt(scb_s, 0x0035U); + + src = crycb_o + offsetof(struct kvm_s390_crypto_cb, apcb0.aqm[0]); + if (read_guest_real(vcpu, src, &apcb_s->aqm[0], sizeof(__u64))) + return set_validity_icpt(scb_s, 0x0035U); + + src = crycb_o + offsetof(struct kvm_s390_crypto_cb, apcb0.adm[0]); + if (read_guest_real(vcpu, src, &apcb_s->adm[0], sizeof(__u64))) + return set_validity_icpt(scb_s, 0x0035U); + + apcb_s->apm[0] &= apcb_h->apm[0]; + apcb_s->aqm[0] &= apcb_h->aqm[0]; + apcb_s->adm[0] &= apcb_h->adm[0]; + + return 0; +} + +/* Shadowing APCB depends on G2 and G3 CRYCB format */ +static int copy_apcb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page, + int g2_fmt, int g3_fmt) +{ + struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; + int ret = 0; + + switch (g2_fmt) { + case CRYCB_FORMAT0: + switch (g3_fmt) { + case CRYCB_FORMAT0: + ret = copy_apcb0(vcpu, vsie_page); + break; + default: + return set_validity_icpt(scb_s, 0x0020U); + } + break; + case CRYCB_FORMAT1: + switch (g3_fmt) { + case CRYCB_FORMAT1: + case CRYCB_FORMAT0: /* Fall through to copy APCB */ + ret = copy_apcb0(vcpu, vsie_page); + break; + default: + return set_validity_icpt(scb_s, 0x0020U); + } + break; + case CRYCB_FORMAT2: + switch (g3_fmt) { + case CRYCB_FORMAT0: + case CRYCB_FORMAT1: + ret = copy_apcb01(vcpu, vsie_page); + break; + case CRYCB_FORMAT2: + ret = copy_apcb1(vcpu, vsie_page); + break; + } + break; + default: + /* + * Guest 2 format is valid or we can not get to here. + */ + break; + } + + return ret; +} + +/* + * Create a shadow copy of the crycb block. + * - Setup key wrapping, if requested for guest 3 and enabled for guest 2. + * - Shadow APCB if requested by guest 3 and enabled for guest 2 through + * ECA_APIE. + * + * We only accept format-1 (no AP in g2), but convert it into format-2 + * There is nothing to do for format-0. + * + * Returns: - 0 if shadowed or nothing to do + * - > 0 if control has to be given to guest 2 + * - < 0 if something went wrong on copy + */ +#define ECA_APIE 0x00000008 +static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) +{ + struct kvm_s390_sie_block *scb_s = &vsie_page->scb_s; + struct kvm_s390_sie_block *scb_o = vsie_page->scb_o; + const uint32_t crycbd_o = READ_ONCE(scb_o->crycbd); + const u32 crycb_addr = crycbd_o & 0x7ffffff8U; + int g2_fmt = vcpu->arch.sie_block->crycbd & CRYCB_FORMAT_MASK; + int g3_fmt = crycbd_o & CRYCB_FORMAT_MASK; + int g2_apie, g2_msa3, g3_apie, g3_msa3; + int size, ret; + + /* crycb should not cross a page boundary */ + size = (g3_fmt == CRYCB_FORMAT2) ? 0x100 : 0x80; + if ((crycb_addr & PAGE_MASK) != ((crycb_addr + size) & PAGE_MASK)) + return set_validity_icpt(scb_s, 0x003CU); + + g2_apie = vcpu->arch.sie_block->eca & ECA_APIE; + g3_apie = scb_o->eca & g2_apie; + + g2_msa3 = test_kvm_facility(vcpu->kvm, 76); + g3_msa3 = (g3_fmt != CRYCB_FORMAT0) & g2_msa3; + + scb_s->crycbd = 0; + /* If no AP instructions and no keys we just set crycbd to 0 */ + if (!(g3_apie || g3_msa3)) + return 0; + + if (!crycb_addr) + return set_validity_icpt(scb_s, 0x0039U); + + if (g3_apie) { + ret = copy_apcb(vcpu, vsie_page, g2_fmt, g3_fmt); + if (ret) + goto out; + scb_s->eca |= g3_apie; + } + + if (g3_msa3) + ret = copy_key_masks(vcpu, vsie_page); + + if (!ret) + scb_s->crycbd = ((__u32)(__u64) &vsie_page->crycb) | g2_fmt; + +out: + return ret; +} + /* shadow (round up/down) the ibc to avoid validity icpt */ static void prepare_ibc(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page) { -- 1.7.1