Message ID | 20221117143242.102721-11-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 q4csp434749wrr; Thu, 17 Nov 2022 06:38:15 -0800 (PST) X-Google-Smtp-Source: AA0mqf6n/yGcaeqxMPqziq7NWFiXQXNuhSHNF0twHHuRIiC1guJwJNGrW0YSaO5DRGztIXkJOPLz X-Received: by 2002:a17:90a:88f:b0:215:d767:4863 with SMTP id v15-20020a17090a088f00b00215d7674863mr3012993pjc.233.1668695895602; Thu, 17 Nov 2022 06:38:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1668695895; cv=none; d=google.com; s=arc-20160816; b=K23oa7eZxWF0TeL3wbzZ6ZOzGsLLrdV136eD8M/g77p0iKaqcEWI/A1rzUymxunr5Y ZreP6gw1ZdyWwkFoWwna9IBZz1GHqemkLuDJ9hht/C04X6WZEIFFsvRDQY1/uuvFS9tG pPw2oZpzBgQeak+mrasB/78dpYnbNB/6FMttwdiBdmk2st9A2A9Nty3Gea2ATaUcuTkx 1aJux1YHVcHPCRA9bBdBiN0gMFKOGRrejfxDV+0r/cZxtoLrBwf1XzypR4uQC/6K37Ty 78i4SBV8r8wNA3cXTdoHOcLwsfQCbPsl4HgfSsGbAq8rGWV+stsmRF0J0hj6By3VQhng Pi0A== 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=TaydI4I4+Qlz5zavVfjLBmIIDcUhBXwzZ2N6s+mdb+g=; b=cQtgN4XrfDrIYMcXH+JJuwfFOIRGeRdrnLE20goxkAcawz+tfB8oGBDvsEUbMMTqqh U+yV9H7iQLj4WqFYX/qDkiKxDyJcu/p3bVTJGoMX+BfiZl2O8z1KL1Rz0AyYtS28nMzV uLOVsfEpmYFa4mKwbWwSIKO3Y5oT3eSYvHESRo2xpTdCAeiCywA6Lqj2uv5gG7+wtpWA LZZqNfKflMBBiNbl+xsTiN9asVmuaQu7RIG3M0K+It/cNXQSbPDnC5YFknNuCsR8MPFx r8usQ/Oi+fCpd0q2GuPo1+Rr5bm+Q3lyYtmVANSBBN4x1LSJoYe99sjej98qbD68Kc1B f0Kg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@redhat.com header.s=mimecast20190719 header.b=c08Ss+gB; 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 w8-20020aa79548000000b0057189df52d4si952585pfq.3.2022.11.17.06.38.02; Thu, 17 Nov 2022 06:38:15 -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=c08Ss+gB; 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 S240462AbiKQOfu (ORCPT <rfc822;a1648639935@gmail.com> + 99 others); Thu, 17 Nov 2022 09:35:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59234 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240449AbiKQOeh (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 17 Nov 2022 09:34:37 -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 0C17F17E35 for <linux-kernel@vger.kernel.org>; Thu, 17 Nov 2022 06:33:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1668695613; 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=TaydI4I4+Qlz5zavVfjLBmIIDcUhBXwzZ2N6s+mdb+g=; b=c08Ss+gBfkz5KXqxrzPgMow9O1mAuQFhMioGNBV4b8Tt/3A0ZW+zMyuLghElDpuJKvM2PT 8J6txAL2fMD0/8R2o72dKksuACCfFcRpNZYWi5An0jZx+Z86XcHR4Rr+SIkBiXpr2PzK9G EzmjQ1IY+H5/TUu9yJatvO/pPrj1Mvs= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-539-BQIktnTiOPaOrejF1IjLKA-1; Thu, 17 Nov 2022 09:33:25 -0500 X-MC-Unique: BQIktnTiOPaOrejF1IjLKA-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id A86A994AB03; Thu, 17 Nov 2022 14:33:24 +0000 (UTC) Received: from amdlaptop.tlv.redhat.com (dhcp-4-238.tlv.redhat.com [10.35.4.238]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2CD852166B29; Thu, 17 Nov 2022 14:33:21 +0000 (UTC) From: Maxim Levitsky <mlevitsk@redhat.com> To: kvm@vger.kernel.org Cc: Paolo Bonzini <pbonzini@redhat.com>, Ingo Molnar <mingo@redhat.com>, "H. Peter Anvin" <hpa@zytor.com>, Dave Hansen <dave.hansen@linux.intel.com>, linux-kernel@vger.kernel.org, Peter Zijlstra <peterz@infradead.org>, Thomas Gleixner <tglx@linutronix.de>, Sandipan Das <sandipan.das@amd.com>, Daniel Sneddon <daniel.sneddon@linux.intel.com>, Jing Liu <jing2.liu@intel.com>, Josh Poimboeuf <jpoimboe@kernel.org>, Wyes Karny <wyes.karny@amd.com>, Borislav Petkov <bp@alien8.de>, Babu Moger <babu.moger@amd.com>, Pawan Gupta <pawan.kumar.gupta@linux.intel.com>, Sean Christopherson <seanjc@google.com>, Jim Mattson <jmattson@google.com>, x86@kernel.org, Maxim Levitsky <mlevitsk@redhat.com>, Santosh Shukla <santosh.shukla@amd.com> Subject: [PATCH 10/13] KVM: SVM: Add VNMI support in inject_nmi Date: Thu, 17 Nov 2022 16:32:39 +0200 Message-Id: <20221117143242.102721-11-mlevitsk@redhat.com> In-Reply-To: <20221117143242.102721-1-mlevitsk@redhat.com> References: <20221117143242.102721-1-mlevitsk@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 3.1 on 10.11.54.6 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?1749754467566691781?= X-GMAIL-MSGID: =?utf-8?q?1749754467566691781?= |
Series |
SVM: vNMI (with my fixes)
|
|
Commit Message
Maxim Levitsky
Nov. 17, 2022, 2:32 p.m. UTC
From: Santosh Shukla <santosh.shukla@amd.com> Inject the NMI by setting V_NMI in the VMCB interrupt control. processor will clear V_NMI to acknowledge processing has started and will keep the V_NMI_MASK set until the processor is done with processing the NMI event. Also, handle the nmi_l1_to_l2 case such that when it is true then NMI to be injected originally comes from L1's VMCB12 EVENTINJ field. So adding a check for that case. Signed-off-by: Santosh Shukla <santosh.shukla@amd.com> Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> --- arch/x86/kvm/svm/svm.c | 7 +++++++ 1 file changed, 7 insertions(+)
Comments
On Thu, Nov 17, 2022, Maxim Levitsky wrote: > From: Santosh Shukla <santosh.shukla@amd.com> > > Inject the NMI by setting V_NMI in the VMCB interrupt control. processor > will clear V_NMI to acknowledge processing has started and will keep the > V_NMI_MASK set until the processor is done with processing the NMI event. > > Also, handle the nmi_l1_to_l2 case such that when it is true then > NMI to be injected originally comes from L1's VMCB12 EVENTINJ field. > So adding a check for that case. > > Signed-off-by: Santosh Shukla <santosh.shukla@amd.com> > Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> > --- > arch/x86/kvm/svm/svm.c | 7 +++++++ > 1 file changed, 7 insertions(+) > > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c > index eaa30f8ace518d..9ebfbd0d4b467e 100644 > --- a/arch/x86/kvm/svm/svm.c > +++ b/arch/x86/kvm/svm/svm.c > @@ -3479,7 +3479,14 @@ static void pre_svm_run(struct kvm_vcpu *vcpu) > static void svm_inject_nmi(struct kvm_vcpu *vcpu) > { > struct vcpu_svm *svm = to_svm(vcpu); > + struct vmcb *vmcb = NULL; As written, no need to initialize vmcb. Might be a moot point depending on the final form of the code. > + if (is_vnmi_enabled(svm) && !svm->nmi_l1_to_l2) { Checking nmi_l1_to_l2 is wrong. KVM should directly re-inject any NMI that was already recognized by hardware, not just those that were originally injected by L1. If another event comes along, e.g. SMI, because an event (NMI) is already injected, KVM will send a hardware IRQ to interrupt the guest and forcea a VM-Exit so that the SMI can be injected. If hardware does the (IMO) sane thing and prioritizes "real" IRQs over virtual NMIs, the IRQ VM-Exit will occur before the virtual NMI is processed and KVM will incorrectly service the SMI before the NMI. I believe the correct way to handle this is to add a @reinjected param to ->inject_nmi(), a la ->inject_irq(). That would also allow adding a sanity check that KVM never attempts to inject an NMI into L2 if NMIs are supposed to trigger VM-Exit. This is the least ugly code I could come up with. Note, if vNMI is enabled, hardare sets V_NMI_MASKED if an NMI is injected through event_inj. static void svm_inject_nmi(struct kvm_vcpu *vcpu, bool reinjected) { struct vcpu_svm *svm = to_svm(vcpu); /* * Except for re-injection, KVM should never inject an NMI into L2 if * NMIs are supposed to exit from L2 to L1. */ WARN_ON_ONCE(!reinjected && is_guest_mode(vcpu) && nested_exit_on_nmi(svm)); if (is_vnmi_enabled(svm)) { if (!reinjected) svm->vmcb->control.int_ctl |= V_NMI_PENDING; else svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI; ++vcpu->stat.nmi_injections; return; } svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI; if (svm->nmi_l1_to_l2) return; vcpu->arch.hflags |= HF_NMI_MASK; if (!sev_es_guest(vcpu->kvm)) svm_set_intercept(svm, INTERCEPT_IRET); ++vcpu->stat.nmi_injections; }
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index eaa30f8ace518d..9ebfbd0d4b467e 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3479,7 +3479,14 @@ static void pre_svm_run(struct kvm_vcpu *vcpu) static void svm_inject_nmi(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm = to_svm(vcpu); + struct vmcb *vmcb = NULL; + if (is_vnmi_enabled(svm) && !svm->nmi_l1_to_l2) { + vmcb = get_vnmi_vmcb(svm); + vmcb->control.int_ctl |= V_NMI_PENDING; + ++vcpu->stat.nmi_injections; + return; + } svm->vmcb->control.event_inj = SVM_EVTINJ_VALID | SVM_EVTINJ_TYPE_NMI; if (svm->nmi_l1_to_l2)