From nobody Mon Apr 6 20:11:03 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C1579C38145 for ; Sat, 3 Sep 2022 00:23:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231430AbiICAX0 (ORCPT ); Fri, 2 Sep 2022 20:23:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53656 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231229AbiICAXN (ORCPT ); Fri, 2 Sep 2022 20:23:13 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4DCFAF63EC for ; Fri, 2 Sep 2022 17:23:08 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 15-20020a63020f000000b0041b578f43f9so1888411pgc.11 for ; Fri, 02 Sep 2022 17:23:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date; bh=JZeHyptfyamN7lZXKlGrbewGaMXcgRQmHfG/o64cPog=; b=T9y5ihH4n9huwf0O2EGKUMPAC1qOYUJkAFO3JWQBaok9tqyIiImayQv5Otbai61XzN F2/Zu5jwnxDVAv/uk1tmzTDDDrDrNvL1eKSRnyt5Ku5B3+DPjIBvK3AtYxAFfcKpznTO 94+bxP0zR8q9OWSJNcasDLE8zI4X9EgvnnK9CMoMRuEHoxaewQr66IgsZmiJKg4OP+in 4aHPEMyEsgL5CW4wt14kum57uXw+kz8LdNIW3T77j5XNpA+PZx7xPqudpXrx8yag8VM0 Ri5cvncocD2yIxBuHC+qH64nHxHuvQ0DG0tFbXfbYjlc/kFH275/nzEgr4kUR9ZkCZkQ a6xA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date; bh=JZeHyptfyamN7lZXKlGrbewGaMXcgRQmHfG/o64cPog=; b=Gevw+mkMZTP7XwipVHFyyHHS2VhZ9arUPRj6uatE+IhgZM5l4kPt9I9oQT0IjgZh7g m0UxXcYj/dtKkq/fkUi0zdNBx++g9Zz6i0uQBGLcFrTjgdqRYo58JLuUydLEF868W7Xh UaGfjQeApePStGYAItW+bh61qQpz84jGLnXj+Yb79gAC6TsyaNQdu7yJfr5ehwk/S/o6 Nb7EH2fcDYhx8vI7iRbPq5wxreGC7DlSzb0r+eSDdUA9VqgfPuKFHwFvgyekwJJsKRhF Vj5vxvUpvYunSiYtIKpGJbP44EgxCh2lqR+jhzyq4rAZvA3i+I0eUmLmBBzE4UDuYxKc nrWQ== X-Gm-Message-State: ACgBeo3SbpkPpwURn7OACENtqphGQBZ9t32sPbj2H+EywZ02TdVJf5bG k2DosC6Z/F/ZkSoyyfiHvUr9naTjQeQ= X-Google-Smtp-Source: AA6agR6vdoeboYtgxxLRIZ616DTlaLOi8pSBgwhAZbgf8WMojNXS2NbATi0Iwzkfe/5VMEc8xQWHy26i5oM= X-Received: from zagreus.c.googlers.com ([fda3:e722:ac3:cc00:7f:e700:c0a8:5c37]) (user=seanjc job=sendgmr) by 2002:a63:8bc3:0:b0:42b:1bd2:9a6d with SMTP id j186-20020a638bc3000000b0042b1bd29a6dmr30984651pge.503.1662164587886; Fri, 02 Sep 2022 17:23:07 -0700 (PDT) Reply-To: Sean Christopherson Date: Sat, 3 Sep 2022 00:22:36 +0000 In-Reply-To: <20220903002254.2411750-1-seanjc@google.com> Mime-Version: 1.0 References: <20220903002254.2411750-1-seanjc@google.com> X-Mailer: git-send-email 2.37.2.789.g6183377224-goog Message-ID: <20220903002254.2411750-6-seanjc@google.com> Subject: [PATCH v2 05/23] KVM: SVM: Don't put/load AVIC when setting virtual APIC mode From: Sean Christopherson To: Sean Christopherson , Paolo Bonzini Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Suravee Suthikulpanit , Maxim Levitsky , Li RongQing Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move the VMCB updates from avic_refresh_apicv_exec_ctrl() into avic_set_virtual_apic_mode() and invert the dependency being said functions to avoid calling avic_vcpu_{load,put}() and avic_set_pi_irte_mode() when "only" setting the virtual APIC mode. avic_set_virtual_apic_mode() is invoked from common x86 with preemption enabled, which makes avic_vcpu_{load,put}() unhappy. Luckily, calling those and updating IRTE stuff is unnecessary as the only reason avic_set_virtual_apic_mode() is called is to handle transitions between xAPIC and x2APIC that don't also toggle APICv activation. And if activation doesn't change, there's no need to fiddle with the physical APIC ID table or update IRTE. The "full" refresh is guaranteed to be called if activation changes in this case as the only call to the "set" path is: kvm_vcpu_update_apicv(vcpu); static_call_cond(kvm_x86_set_virtual_apic_mode)(vcpu); and kvm_vcpu_update_apicv() invokes the refresh if activation changes: if (apic->apicv_active =3D=3D activate) goto out; apic->apicv_active =3D activate; kvm_apic_update_apicv(vcpu); static_call(kvm_x86_refresh_apicv_exec_ctrl)(vcpu); Rename the helper to reflect that it is also called during "refresh". WARNING: CPU: 183 PID: 49186 at arch/x86/kvm/svm/avic.c:1081 avic_vcpu_pu= t+0xde/0xf0 [kvm_amd] CPU: 183 PID: 49186 Comm: stable Tainted: G O 6.0.0-smp--= fcddbca45f0a-sink #34 Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 10.48.0 01/= 27/2022 RIP: 0010:avic_vcpu_put+0xde/0xf0 [kvm_amd] avic_refresh_apicv_exec_ctrl+0x142/0x1c0 [kvm_amd] avic_set_virtual_apic_mode+0x5a/0x70 [kvm_amd] kvm_lapic_set_base+0x149/0x1a0 [kvm] kvm_set_apic_base+0x8f/0xd0 [kvm] kvm_set_msr_common+0xa3a/0xdc0 [kvm] svm_set_msr+0x364/0x6b0 [kvm_amd] __kvm_set_msr+0xb8/0x1c0 [kvm] kvm_emulate_wrmsr+0x58/0x1d0 [kvm] msr_interception+0x1c/0x30 [kvm_amd] svm_invoke_exit_handler+0x31/0x100 [kvm_amd] svm_handle_exit+0xfc/0x160 [kvm_amd] vcpu_enter_guest+0x21bb/0x23e0 [kvm] vcpu_run+0x92/0x450 [kvm] kvm_arch_vcpu_ioctl_run+0x43e/0x6e0 [kvm] kvm_vcpu_ioctl+0x559/0x620 [kvm] Fixes: 05c4fe8c1bd9 ("KVM: SVM: Refresh AVIC configuration when changing AP= IC mode") Cc: stable@vger.kernel.org Cc: Suravee Suthikulpanit Cc: Maxim Levitsky Signed-off-by: Sean Christopherson --- arch/x86/kvm/svm/avic.c | 31 +++++++++++++++---------------- arch/x86/kvm/svm/svm.c | 2 +- arch/x86/kvm/svm/svm.h | 2 +- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index 19be5f1afaac..de7fcb3a544b 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -747,18 +747,6 @@ void avic_apicv_post_state_restore(struct kvm_vcpu *vc= pu) avic_handle_ldr_update(vcpu); } =20 -void avic_set_virtual_apic_mode(struct kvm_vcpu *vcpu) -{ - if (!lapic_in_kernel(vcpu) || avic_mode =3D=3D AVIC_MODE_NONE) - return; - - if (kvm_get_apic_mode(vcpu) =3D=3D LAPIC_MODE_INVALID) { - WARN_ONCE(true, "Invalid local APIC state (vcpu_id=3D%d)", vcpu->vcpu_id= ); - return; - } - avic_refresh_apicv_exec_ctrl(vcpu); -} - static int avic_set_pi_irte_mode(struct kvm_vcpu *vcpu, bool activate) { int ret =3D 0; @@ -1101,17 +1089,18 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu) WRITE_ONCE(*(svm->avic_physical_id_cache), entry); } =20 - -void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu) +void avic_refresh_virtual_apic_mode(struct kvm_vcpu *vcpu) { struct vcpu_svm *svm =3D to_svm(vcpu); struct vmcb *vmcb =3D svm->vmcb01.ptr; - bool activated =3D kvm_vcpu_apicv_active(vcpu); + + if (!lapic_in_kernel(vcpu) || avic_mode =3D=3D AVIC_MODE_NONE) + return; =20 if (!enable_apicv) return; =20 - if (activated) { + if (kvm_vcpu_apicv_active(vcpu)) { /** * During AVIC temporary deactivation, guest could update * APIC ID, DFR and LDR registers, which would not be trapped @@ -1125,6 +1114,16 @@ void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *v= cpu) avic_deactivate_vmcb(svm); } vmcb_mark_dirty(vmcb, VMCB_AVIC); +} + +void avic_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu) +{ + bool activated =3D kvm_vcpu_apicv_active(vcpu); + + if (!enable_apicv) + return; + + avic_refresh_virtual_apic_mode(vcpu); =20 if (activated) avic_vcpu_load(vcpu, vcpu->cpu); diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index f3813dbacb9f..2aa5069bafb2 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4807,7 +4807,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata =3D { .enable_nmi_window =3D svm_enable_nmi_window, .enable_irq_window =3D svm_enable_irq_window, .update_cr8_intercept =3D svm_update_cr8_intercept, - .set_virtual_apic_mode =3D avic_set_virtual_apic_mode, + .set_virtual_apic_mode =3D avic_refresh_virtual_apic_mode, .refresh_apicv_exec_ctrl =3D avic_refresh_apicv_exec_ctrl, .check_apicv_inhibit_reasons =3D avic_check_apicv_inhibit_reasons, .apicv_post_state_restore =3D avic_apicv_post_state_restore, diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 6a7686bf6900..7a95f50e80e7 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -646,7 +646,7 @@ void avic_vcpu_blocking(struct kvm_vcpu *vcpu); void avic_vcpu_unblocking(struct kvm_vcpu *vcpu); void avic_ring_doorbell(struct kvm_vcpu *vcpu); unsigned long avic_vcpu_get_apicv_inhibit_reasons(struct kvm_vcpu *vcpu); -void avic_set_virtual_apic_mode(struct kvm_vcpu *vcpu); +void avic_refresh_virtual_apic_mode(struct kvm_vcpu *vcpu); =20 =20 /* sev.c */ --=20 2.37.2.789.g6183377224-goog