[v2,03/11] KVM: nSVM: explicitly raise KVM_REQ_EVENT on nested VM exit if L1 doesn't intercept interrupts
Message ID | 20221129193717.513824-4-mlevitsk@redhat.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp536678wrr; Tue, 29 Nov 2022 11:51:50 -0800 (PST) X-Google-Smtp-Source: AA0mqf6q3c6OiSzlUc/X1eYvMX01KKo/iNBGnQBd5SxV1OezFvFS4vjQXFEVGk63ePGdx5LWnTZ1 X-Received: by 2002:a17:906:1b46:b0:7be:e794:a406 with SMTP id p6-20020a1709061b4600b007bee794a406mr12194837ejg.503.1669751509888; Tue, 29 Nov 2022 11:51:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669751509; cv=none; d=google.com; s=arc-20160816; b=nTx3Rcb0zMi9ZrTvIVMav0MAT5xxlh+RaYZXY2EbYB4QHZBmv4Z9WSCbQRw3YZTyrW qVJ5G8AyB7bV1bNgjI0whfmgGxmk/EhbA/U0muShnXR5hpRMCaxCNIGoL6CzG5XpaeZc YIuZDOtyn5Xl5M+lxH1ovfijsADB58fWw4ge+vvJfm41qmmWsHd+wvoj21N9UsdXtcwA /H5VX9e+5PaWuunp7h/9t47snXpQRi0chaLN4d6heD+HGv5FCptTEJbv11ec3x3Kul1C EQlXx5qDmeQLWP1pgCyAJatCK12fmhFjcgiYoRJZZRk8ucmc8D+sRwVPiUeXh61AGiIX m2ZQ== 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=Ax33lO2rYC4qdqXK9hN6118xGd7ZlQSFY6CuNF4UBj0=; b=tooDWexm9z7ohWI/aMSjTgUNhek0yLKlip31umydpUiXMR/YueaQEdYVjfS2SZpguN yoYM/AVnSXQGwsdUeCHZKGG+K5Hz2hPmOavjgHzlGBY7xgOMUBDAly9stzwtdvUtt9y7 ybpbRUJHdPoK8VoRUC8Kmz0wepFONK0GxfpRDS0eJWkKJKWZT6VbDodnQxkYUmcoJ6oT kqNPx8dgjuC/YMt6IQh2cCoQUznHPtqGilLnZTaXitmvSRSZ38I+0EY6oTxE7B/oLE1Y hh6BILi3wmZwwZEOqRy5Mo0C2FG3Pvt1FBla6eVXTk3NI0csk5teHHpiI6CenpXY1A4t o5vg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b="D/XCJxQk"; 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=redhat.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id be4-20020a1709070a4400b0078e27f2fbe4si14436217ejc.293.2022.11.29.11.51.24; Tue, 29 Nov 2022 11:51:49 -0800 (PST) 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=@redhat.com header.s=mimecast20190719 header.b="D/XCJxQk"; 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=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236207AbiK2Tks (ORCPT <rfc822;rbbytesnap@gmail.com> + 99 others); Tue, 29 Nov 2022 14:40:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51560 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235990AbiK2TkY (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Tue, 29 Nov 2022 14:40:24 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id ACB2E262B for <linux-kernel@vger.kernel.org>; Tue, 29 Nov 2022 11:37:40 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1669750659; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Ax33lO2rYC4qdqXK9hN6118xGd7ZlQSFY6CuNF4UBj0=; b=D/XCJxQkCiCal9eFqeLX2zrMXejXyn1/QuVuU4Kw5waYNDYiZ+3lacAD4szuNGEgMnXuKN 3yhkbkLdJPqK3TT+yOXGoPo4sDryssu42As4WK9RHsFRvNO724eYQds/S6tayqMzUMT6ro 7rCbsiEO7aRKbvd5zO6qHMZxtlqXsuA= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-153-KxT3T5GlMzGGlJO3dCad6A-1; Tue, 29 Nov 2022 14:37:36 -0500 X-MC-Unique: KxT3T5GlMzGGlJO3dCad6A-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 00FB81C06EDF; Tue, 29 Nov 2022 19:37:35 +0000 (UTC) Received: from localhost.localdomain (unknown [10.35.206.46]) by smtp.corp.redhat.com (Postfix) with ESMTP id 4D0B82024CB7; Tue, 29 Nov 2022 19:37:31 +0000 (UTC) From: Maxim Levitsky <mlevitsk@redhat.com> To: kvm@vger.kernel.org Cc: Sandipan Das <sandipan.das@amd.com>, Paolo Bonzini <pbonzini@redhat.com>, Jim Mattson <jmattson@google.com>, Peter Zijlstra <peterz@infradead.org>, Dave Hansen <dave.hansen@linux.intel.com>, Borislav Petkov <bp@alien8.de>, Pawan Gupta <pawan.kumar.gupta@linux.intel.com>, Thomas Gleixner <tglx@linutronix.de>, Ingo Molnar <mingo@redhat.com>, Josh Poimboeuf <jpoimboe@kernel.org>, Daniel Sneddon <daniel.sneddon@linux.intel.com>, Jiaxi Chen <jiaxi.chen@linux.intel.com>, Babu Moger <babu.moger@amd.com>, linux-kernel@vger.kernel.org, Jing Liu <jing2.liu@intel.com>, Wyes Karny <wyes.karny@amd.com>, x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>, Sean Christopherson <seanjc@google.com>, Maxim Levitsky <mlevitsk@redhat.com> Subject: [PATCH v2 03/11] KVM: nSVM: explicitly raise KVM_REQ_EVENT on nested VM exit if L1 doesn't intercept interrupts Date: Tue, 29 Nov 2022 21:37:09 +0200 Message-Id: <20221129193717.513824-4-mlevitsk@redhat.com> In-Reply-To: <20221129193717.513824-1-mlevitsk@redhat.com> References: <20221129193717.513824-1-mlevitsk@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_NONE autolearn=unavailable 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750861358840887804?= X-GMAIL-MSGID: =?utf-8?q?1750861358840887804?= |
Series |
SVM: vNMI (with my fixes)
|
|
Commit Message
Maxim Levitsky
Nov. 29, 2022, 7:37 p.m. UTC
If the L2 doesn't intercept interrupts, then the KVM will use vmcb02's
V_IRQ for L1 (to detect the interrupt window)
In this case on the nested VM exit KVM might need to copy the V_IRQ bit
from the vmcb02 to the vmcb01, to continue waiting for the
interrupt window.
To make it simple, just raise the KVM_REQ_EVENT request, which
execution will lead to the reenabling of the interrupt
window if needed.
Note that this is a theoretical bug because the KVM already does raise
the KVM_REQ_EVENT request one each nested VM exit because the nested
VM exit resets RFLAGS and the kvm_set_rflags() raises the
KVM_REQ_EVENT request in the response.
However raising this request explicitly, together with
documenting why this is needed, is still preferred.
Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
---
arch/x86/kvm/svm/nested.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
Comments
Shortlog is too long, maybe this? KVM: nSVM: Raise event on nested VM exit if L1 doesn't intercept IRQs On Tue, Nov 29, 2022, Maxim Levitsky wrote: > If the L2 doesn't intercept interrupts, then the KVM will use vmcb02's s/the L2/L2, though don't you mean L1? > V_IRQ for L1 (to detect the interrupt window) "an interrupt window", i.e. there's not just one window. > In this case on the nested VM exit KVM might need to copy the V_IRQ bit s/the nested/nested > from the vmcb02 to the vmcb01, to continue waiting for the > interrupt window. > > To make it simple, just raise the KVM_REQ_EVENT request, which > execution will lead to the reenabling of the interrupt > window if needed. > > Note that this is a theoretical bug because the KVM already does raise s/the KVM/KVM > the KVM_REQ_EVENT request one each nested VM exit because the nested s/the KVM_REQ_EVENT/KVM_REQ_EVENT, and s/one/on > VM exit resets RFLAGS and the kvm_set_rflags() raises the > KVM_REQ_EVENT request in the response. > > However raising this request explicitly, together with > documenting why this is needed, is still preferred. > > Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com> > --- > arch/x86/kvm/svm/nested.c | 25 +++++++++++++++++++++++++ > 1 file changed, 25 insertions(+) > > diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c > index aad3145b2f62fe..e891318595113e 100644 > --- a/arch/x86/kvm/svm/nested.c > +++ b/arch/x86/kvm/svm/nested.c > @@ -1016,6 +1016,31 @@ int nested_svm_vmexit(struct vcpu_svm *svm) > > svm_switch_vmcb(svm, &svm->vmcb01); > > + /* Note about synchronizing some of int_ctl bits from vmcb02 to vmcb01: /* * Preferred block comment style... > + * > + * - V_IRQ, V_IRQ_VECTOR, V_INTR_PRIO_MASK, V_IGN_TPR: Drop the "-" to be consistent with the rest of the paragraphs. > + * If the L2 doesn't intercept interrupts, then > + * (even if the L2 does use virtual interrupt masking), KVM uses "L2" to refer to the thing running at L2. I think what you are referring to here is vmcb12? And that's controlled by L1. > + * KVM will use the vmcb02's V_INTR to detect interrupt window. s/the vmcb02/vmcb02 Which of the V_INTR fields does this refer to? Oooh, you're saying the KVM injects a virtual interrupt into L2 using vmcb02 in order to determine when L2 has IRQs enabled. Why does KVM do that? Why not pend the actual IRQ directly? > + * > + * In this case, the KVM raises the KVM_REQ_EVENT to ensure that interrupt window s/the KVM_REQ_EVENT/KVM_REQ_EVENT > + * is not lost and this implicitly copies these bits from vmcb02 to vmcb01 Too many pronouns. What do "this" and "these bits" refer to? > + * > + * V_TPR: > + * If the L2 doesn't use virtual interrupt masking, then the L1's vTPR > + * is stored in the vmcb02 but its value doesn't need to be copied from/to > + * vmcb01 because it is copied from/to the TPR APIC's register on > + * each VM entry/exit. > + * > + * V_GIF: > + * - If the nested vGIF is not used, KVM uses vmcb02's V_GIF for L1's V_GIF, Drop this "-" too. > + * however, the L1 vGIF is reset to false on each VM exit, thus > + * there is no need to copy it from vmcb02 to vmcb01. > + */ > + > + if (!nested_exit_on_intr(svm)) > + kvm_make_request(KVM_REQ_EVENT, &svm->vcpu); > + > if (unlikely(svm->lbrv_enabled && (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK))) { > svm_copy_lbrs(vmcb12, vmcb02); > svm_update_lbrv(vcpu); > -- > 2.26.3 >
On Sat, Jan 28, 2023, Sean Christopherson wrote: > > + * If the L2 doesn't intercept interrupts, then > > + * (even if the L2 does use virtual interrupt masking), > > KVM uses "L2" to refer to the thing running at L2. I think what you are referring > to here is vmcb12? And that's controlled by L1. > > > + * KVM will use the vmcb02's V_INTR to detect interrupt window. > > s/the vmcb02/vmcb02 > > Which of the V_INTR fields does this refer to? Oooh, you're saying the KVM injects > a virtual interrupt into L2 using vmcb02 in order to determine when L2 has IRQs > enabled. > > Why does KVM do that? Why not pend the actual IRQ directly? Duh, because KVM needs to gain control in if there are multiple pending events.
diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index aad3145b2f62fe..e891318595113e 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1016,6 +1016,31 @@ int nested_svm_vmexit(struct vcpu_svm *svm) svm_switch_vmcb(svm, &svm->vmcb01); + /* Note about synchronizing some of int_ctl bits from vmcb02 to vmcb01: + * + * - V_IRQ, V_IRQ_VECTOR, V_INTR_PRIO_MASK, V_IGN_TPR: + * If the L2 doesn't intercept interrupts, then + * (even if the L2 does use virtual interrupt masking), + * KVM will use the vmcb02's V_INTR to detect interrupt window. + * + * In this case, the KVM raises the KVM_REQ_EVENT to ensure that interrupt window + * is not lost and this implicitly copies these bits from vmcb02 to vmcb01 + * + * V_TPR: + * If the L2 doesn't use virtual interrupt masking, then the L1's vTPR + * is stored in the vmcb02 but its value doesn't need to be copied from/to + * vmcb01 because it is copied from/to the TPR APIC's register on + * each VM entry/exit. + * + * V_GIF: + * - If the nested vGIF is not used, KVM uses vmcb02's V_GIF for L1's V_GIF, + * however, the L1 vGIF is reset to false on each VM exit, thus + * there is no need to copy it from vmcb02 to vmcb01. + */ + + if (!nested_exit_on_intr(svm)) + kvm_make_request(KVM_REQ_EVENT, &svm->vcpu); + if (unlikely(svm->lbrv_enabled && (svm->nested.ctl.virt_ext & LBR_CTL_ENABLE_MASK))) { svm_copy_lbrs(vmcb12, vmcb02); svm_update_lbrv(vcpu);