Received: by 2002:a05:6602:18e:0:0:0:0 with SMTP id m14csp8635134ioo; Sat, 4 Jun 2022 13:59:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxXgqLhA0x7zOVMG6L57WdiZ6LAcZahVEY7OsRWKONTYPUXVp9CeJ/uefcl0BuVpfy2c95R X-Received: by 2002:a17:902:b581:b0:161:5f37:6688 with SMTP id a1-20020a170902b58100b001615f376688mr16126396pls.145.1654376365959; Sat, 04 Jun 2022 13:59:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1654376365; cv=none; d=google.com; s=arc-20160816; b=ihUBUU5ohl1unL4aNxRqqn/GninOgp/NJSJh6XsaRSVfVvLAmrCb5Pi1/IldIi2EOP FDVoT4+QIRBmKjBASEZdFLUF8rXKHk3d7ct/utxTnIObYtlJCOxgV1NX1zCWqiYEiVCd UMuCOO+R16rg7ujHc9FKSMoGOFj/jJ8ylLEL+5BhwzN6Nxys0w6y8Lb8umV7bgKTvTU8 VZzL5URwo//Lgd/1VrQ702++Y7+NOM1mI/4Rwq/vDWpX/PANur4Mt/Ea2jugSp9dOHxb zTRaCwTDrN0azgZ2ku0nr2GU+2+I/0VAP641YcZ6wZVBGQaI4uh1YDQ5tAiS+lAYxMuN yZjg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=UC89LK2z8dExdm+YP9vuzkYdGm9XeRVi4z6pyn82VN4=; b=i/3/l5yYDLbISyhSz1XxraP6fmXZTLzaBEKvd6LkOMUhJQNukVq///15AVHs67LABT 7je2BQ8piYfxxtL8F3uAJtXQhYRD6Ssv04RFNy0XpEMcuWBHBA1mxdYJo23rPPpzuHUH 7/SJRx0YVMaB4mlIfbf1bATw36dvg2DlkAvg9RtRMDsJNdm9LgAfBSjtne4k7KLUqX/7 HtJ/xpz2r04tOWizCNqtYDSiNt9301IRX5XuTf+NAjclduv8LBFbaA7ouUF7sNSm45s9 N20gQUr02IZRd/1gjmH+Kskj8y857BikIiUZMjLmxL7Or2VeRfdipgPOUEZiP+iJg7I+ 79kQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@ibm.com header.s=pp1 header.b=tla1HPt+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=ibm.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id p15-20020a17090a930f00b001e2f31e3b38si13541207pjo.34.2022.06.04.13.59.13; Sat, 04 Jun 2022 13:59:25 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@ibm.com header.s=pp1 header.b=tla1HPt+; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242079AbiFCG6S (ORCPT + 99 others); Fri, 3 Jun 2022 02:58:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33638 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241812AbiFCG5F (ORCPT ); Fri, 3 Jun 2022 02:57:05 -0400 Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D89C11115; Thu, 2 Jun 2022 23:56:58 -0700 (PDT) Received: from pps.filterd (m0098414.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.17.1.5/8.17.1.5) with ESMTP id 2533FRjM025233; Fri, 3 Jun 2022 06:56:57 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=UC89LK2z8dExdm+YP9vuzkYdGm9XeRVi4z6pyn82VN4=; b=tla1HPt+a1kOyi1Xwo01IphoxPzvlS/TShEpJJ3bx11DFOBsemcgr5XOVx++EbNXqnlL GG7e6SCS2MfJL0MK692ruK6asvWyJTp8RT+dyfbS34oiYyzhuD0FhhR3+FVs/Ni3yNmT E98nfnNyCK0xeFSIn8fRVaNvXmKWWLDw/Mi16UQSKwMtKEuWLuMv158nKenLdyxHWheK UaE9eavVVHjqppK++TEmvVcO2e0iUPeNM61ntBegzmB8oFBYIX+vpdlhlJUrSQfXUtas PpOWXCUZFNyc0UyThbkC6dJA0EU7n58dI0ULL/JsOdzR/NisXmFtNEuORQGeT70jA7ju 9Q== Received: from pps.reinject (localhost [127.0.0.1]) by mx0b-001b2d01.pphosted.com (PPS) with ESMTPS id 3gf5g172rd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 03 Jun 2022 06:56:57 +0000 Received: from m0098414.ppops.net (m0098414.ppops.net [127.0.0.1]) by pps.reinject (8.17.1.5/8.17.1.5) with ESMTP id 2536cC5m001680; Fri, 3 Jun 2022 06:56:57 GMT Received: from ppma04fra.de.ibm.com (6a.4a.5195.ip4.static.sl-reverse.com [149.81.74.106]) by mx0b-001b2d01.pphosted.com (PPS) with ESMTPS id 3gf5g172qv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 03 Jun 2022 06:56:56 +0000 Received: from pps.filterd (ppma04fra.de.ibm.com [127.0.0.1]) by ppma04fra.de.ibm.com (8.16.1.2/8.16.1.2) with SMTP id 2536pDwC022961; Fri, 3 Jun 2022 06:56:55 GMT Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by ppma04fra.de.ibm.com with ESMTP id 3gbc8yp3pb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 03 Jun 2022 06:56:55 +0000 Received: from d06av24.portsmouth.uk.ibm.com (mk.ibm.com [9.149.105.60]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 2536uq9936176186 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 3 Jun 2022 06:56:52 GMT Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 11F0E42047; Fri, 3 Jun 2022 06:56:52 +0000 (GMT) Received: from d06av24.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B6D9A4204C; Fri, 3 Jun 2022 06:56:51 +0000 (GMT) Received: from p-imbrenda.boeblingen.de.ibm.com (unknown [9.152.224.40]) by d06av24.portsmouth.uk.ibm.com (Postfix) with ESMTP; Fri, 3 Jun 2022 06:56:51 +0000 (GMT) From: Claudio Imbrenda To: kvm@vger.kernel.org Cc: borntraeger@de.ibm.com, frankja@linux.ibm.com, thuth@redhat.com, pasic@linux.ibm.com, david@redhat.com, linux-s390@vger.kernel.org, linux-kernel@vger.kernel.org, scgl@linux.ibm.com, mimu@linux.ibm.com, nrb@linux.ibm.com Subject: [PATCH v11 14/19] KVM: s390: pv: cleanup leftover protected VMs if needed Date: Fri, 3 Jun 2022 08:56:40 +0200 Message-Id: <20220603065645.10019-15-imbrenda@linux.ibm.com> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220603065645.10019-1-imbrenda@linux.ibm.com> References: <20220603065645.10019-1-imbrenda@linux.ibm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-TM-AS-GCONF: 00 X-Proofpoint-GUID: 6BZof1betRgVfLENusGBwtWHvCJSNrI0 X-Proofpoint-ORIG-GUID: HZs2Pk0Unm4zSI-xEvCN4CkwDdtXVTqM X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.205,Aquarius:18.0.874,Hydra:6.0.517,FMLib:17.11.64.514 definitions=2022-06-03_01,2022-06-02_01,2022-02-23_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 phishscore=0 malwarescore=0 bulkscore=0 lowpriorityscore=0 mlxlogscore=999 clxscore=1015 impostorscore=0 spamscore=0 adultscore=0 priorityscore=1501 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2204290000 definitions=main-2206030027 X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In upcoming patches it will be possible to start tearing down a protected VM, and finish the teardown concurrently in a different thread. Protected VMs that are pending for tear down ("leftover") need to be cleaned properly when the userspace process (e.g. qemu) terminates. This patch makes sure that all "leftover" protected VMs are always properly torn down. Signed-off-by: Claudio Imbrenda --- arch/s390/include/asm/kvm_host.h | 2 + arch/s390/kvm/kvm-s390.c | 2 + arch/s390/kvm/pv.c | 109 ++++++++++++++++++++++++++++--- 3 files changed, 104 insertions(+), 9 deletions(-) diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index 5824efe5fc9d..cca8e05e0a71 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h @@ -924,6 +924,8 @@ struct kvm_s390_pv { u64 guest_len; unsigned long stor_base; void *stor_var; + void *prepared_for_async_deinit; + struct list_head need_cleanup; struct mmu_notifier mmu_notifier; }; diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index fe1fa896def7..369de8377116 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -2890,6 +2890,8 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) kvm_s390_vsie_init(kvm); if (use_gisa) kvm_s390_gisa_init(kvm); + INIT_LIST_HEAD(&kvm->arch.pv.need_cleanup); + kvm->arch.pv.prepared_for_async_deinit = NULL; KVM_EVENT(3, "vm 0x%pK created by pid %u", kvm, current->pid); return 0; diff --git a/arch/s390/kvm/pv.c b/arch/s390/kvm/pv.c index 6cffea26c47f..8471c17d538c 100644 --- a/arch/s390/kvm/pv.c +++ b/arch/s390/kvm/pv.c @@ -17,6 +17,19 @@ #include #include "kvm-s390.h" +/** + * @struct leftover_pv_vm + * Represents a "leftover" protected VM that is still registered with the + * Ultravisor, but which does not correspond any longer to an active KVM VM. + */ +struct leftover_pv_vm { + struct list_head list; + unsigned long old_gmap_table; + u64 handle; + void *stor_var; + unsigned long stor_base; +}; + static void kvm_s390_clear_pv_state(struct kvm *kvm) { kvm->arch.pv.handle = 0; @@ -158,23 +171,88 @@ static int kvm_s390_pv_alloc_vm(struct kvm *kvm) return -ENOMEM; } +/** + * kvm_s390_pv_dispose_one_leftover - Clean up one leftover protected VM. + * @kvm the KVM that was associated with this leftover protected VM + * @leftover details about the leftover protected VM that needs a clean up + * @rc the RC code of the Destroy Secure Configuration UVC + * @rrc the RRC code of the Destroy Secure Configuration UVC + * Return: 0 in case of success, otherwise 1 + * + * Destroy one leftover protected VM. + * On success, kvm->mm->context.protected_count will be decremented atomically + * and all other resources used by the VM will be freed. + */ +static int kvm_s390_pv_dispose_one_leftover(struct kvm *kvm, struct leftover_pv_vm *leftover, + u16 *rc, u16 *rrc) +{ + int cc; + + cc = uv_cmd_nodata(leftover->handle, UVC_CMD_DESTROY_SEC_CONF, rc, rrc); + KVM_UV_EVENT(kvm, 3, "PROTVIRT DESTROY LEFTOVER VM: rc %x rrc %x", *rc, *rrc); + WARN_ONCE(cc, "protvirt destroy leftover vm failed rc %x rrc %x", *rc, *rrc); + if (cc) + return cc; + /* + * Intentionally leak unusable memory. If the UVC fails, the memory + * used for the VM and its metadata is permanently unusable. + * This can only happen in case of a serious KVM or hardware bug; it + * is not expected to happen in normal operation. + */ + free_pages(leftover->stor_base, get_order(uv_info.guest_base_stor_len)); + free_pages(leftover->old_gmap_table, CRST_ALLOC_ORDER); + vfree(leftover->stor_var); + atomic_dec(&kvm->mm->context.protected_count); + return 0; +} + +/** + * kvm_s390_pv_cleanup_leftovers - Clean up all leftover protected VMs. + * @kvm the KVM whose leftover protected VMs are to be cleaned up + * @rc the RC code of the first failing UVC, unless it was already != 1 + * @rrc the RRC code of the first failing UVC, unless @rc was already != 1 + * Return: 0 if all leftover VMs are successfully cleaned up, otherwise 1 + * + * This function will clean up all "leftover" protected VMs, including the + * one that had been set aside for deferred teardown. + */ +static int kvm_s390_pv_cleanup_leftovers(struct kvm *kvm, u16 *rc, u16 *rrc) +{ + struct leftover_pv_vm *cur; + u16 _rc, _rrc; + int cc = 0; + + if (kvm->arch.pv.prepared_for_async_deinit) + list_add(kvm->arch.pv.prepared_for_async_deinit, &kvm->arch.pv.need_cleanup); + + while (!list_empty(&kvm->arch.pv.need_cleanup)) { + cur = list_first_entry(&kvm->arch.pv.need_cleanup, typeof(*cur), list); + if (kvm_s390_pv_dispose_one_leftover(kvm, cur, &_rc, &_rrc)) { + cc = 1; + /* do not overwrite a previous error code */ + if (*rc == 1) { + *rc = _rc; + *rrc = _rrc; + } + } + list_del(&cur->list); + kfree(cur); + } + kvm->arch.pv.prepared_for_async_deinit = NULL; + return cc; +} + /* this should not fail, but if it does, we must not free the donated memory */ int kvm_s390_pv_deinit_vm(struct kvm *kvm, u16 *rc, u16 *rrc) { int cc; + /* Make sure the counter does not reach 0 before calling s390_uv_destroy_range */ + atomic_inc(&kvm->mm->context.protected_count); + cc = uv_cmd_nodata(kvm_s390_pv_get_handle(kvm), UVC_CMD_DESTROY_SEC_CONF, rc, rrc); WRITE_ONCE(kvm->arch.gmap->guest_handle, 0); - /* - * if the mm still has a mapping, make all its pages accessible - * before destroying the guest - */ - if (mmget_not_zero(kvm->mm)) { - s390_uv_destroy_range(kvm->mm, 0, TASK_SIZE); - mmput(kvm->mm); - } - if (!cc) { atomic_dec(&kvm->mm->context.protected_count); kvm_s390_pv_dealloc_vm(kvm); @@ -185,6 +263,19 @@ int kvm_s390_pv_deinit_vm(struct kvm *kvm, u16 *rc, u16 *rrc) KVM_UV_EVENT(kvm, 3, "PROTVIRT DESTROY VM: rc %x rrc %x", *rc, *rrc); WARN_ONCE(cc, "protvirt destroy vm failed rc %x rrc %x", *rc, *rrc); + cc |= kvm_s390_pv_cleanup_leftovers(kvm, rc, rrc); + + /* + * If the mm still has a mapping, try to mark all its pages as + * accessible. The counter should not reach zero before this + * cleanup has been performed. + */ + if (mmget_not_zero(kvm->mm)) { + s390_uv_destroy_range(kvm->mm, 0, TASK_SIZE); + mmput(kvm->mm); + } + /* Now the counter can safely reach 0 */ + atomic_dec(&kvm->mm->context.protected_count); return cc ? -EIO : 0; } -- 2.36.1