From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6FDAF3E717B for ; Mon, 16 Mar 2026 19:36:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773689807; cv=none; b=PFImOWMbsmuRPFKo6giA+wbj6uLkbYZEgYldXbr8XgbNZaUIJaWDZHZf2t31FCdWA1lgzNoMf29F5Hy6+wXgus9OhKFesGAqFBJw0Q4j062UzhD3pYAUYTweHY0b823n1BZDMcM9CBW+4+3hZJZjnpN2rLwX+2FSfqold2+Zygw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773689807; c=relaxed/simple; bh=01fsWkTBHJ1C5emKVMM6FIFAjrwApmMJoIX4M60wS/E=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZP0xmt98p0ZkX+iyR7YB0ubO11qcSWzyThVWAWaAjrlutOxBx5WG0um1AJWGd4ksHntJ1gXssFtJ46Ee5OINJpcZ5fqsbmyILj0CyveBYhX9s5aUgfzssHRFYMRzyFcvfVuY80wdxZo/3snInSuBVPvloxqMhDr+KNLBMD62xyQ= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ka85Sj5E; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Ka85Sj5E" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5AADAC2BC9E; Mon, 16 Mar 2026 19:36:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1773689807; bh=01fsWkTBHJ1C5emKVMM6FIFAjrwApmMJoIX4M60wS/E=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ka85Sj5Eh2nlv0A/WOslpHiYKV+Q73MVxig8rv0VbiFYvRqDzhcCKX4RZMNBrIPiI nSp2TXQb4iBzi5LiJ7LkeixfMrHaQ81e2ZaRVhx4D9lzyiGnO+azzRZTOhgS9G7vbL i7tv5njNQpVVBb1+C9ocSZejs6HSLhlB8/THrO0IA7ZXOxaAAq11VZfajxfBBdZi2m kSdoIoeVy4/mpiLyNhm6e6fAPf8N29k0nAxLdbBhArxmcpfJYEeKpkd/uP7nd4Ft2I TywYOysRsymb4oI9yPRxJIh2V8EpEwU9+SDKnQtSyO4xzt4Y9AtDho6BAAAkRPZPSf YoYvvlacwAnHA== From: Sasha Levin To: stable@vger.kernel.org Cc: Sean Christopherson , Jim Mattson , "Naveen N Rao (AMD)" , "Maciej S. Szmigiero" , Paolo Bonzini , Sasha Levin Subject: [PATCH 6.6.y 3/3] KVM: SVM: Set/clear CR8 write interception when AVIC is (de)activated Date: Mon, 16 Mar 2026 15:36:43 -0400 Message-ID: <20260316193643.1358734-3-sashal@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260316193643.1358734-1-sashal@kernel.org> References: <2026031633-ranting-ditto-0e1b@gregkh> <20260316193643.1358734-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Sean Christopherson [ Upstream commit 87d0f901a9bd8ae6be57249c737f20ac0cace93d ] Explicitly set/clear CR8 write interception when AVIC is (de)activated to fix a bug where KVM leaves the interception enabled after AVIC is activated. E.g. if KVM emulates INIT=>WFS while AVIC is deactivated, CR8 will remain intercepted in perpetuity. On its own, the dangling CR8 intercept is "just" a performance issue, but combined with the TPR sync bug fixed by commit d02e48830e3f ("KVM: SVM: Sync TPR from LAPIC into VMCB::V_TPR even if AVIC is active"), the danging intercept is fatal to Windows guests as the TPR seen by hardware gets wildly out of sync with reality. Note, VMX isn't affected by the bug as TPR_THRESHOLD is explicitly ignored when Virtual Interrupt Delivery is enabled, i.e. when APICv is active in KVM's world. I.e. there's no need to trigger update_cr8_intercept(), this is firmly an SVM implementation flaw/detail. WARN if KVM gets a CR8 write #VMEXIT while AVIC is active, as KVM should never enter the guest with AVIC enabled and CR8 writes intercepted. Fixes: 3bbf3565f48c ("svm: Do not intercept CR8 when enable AVIC") Cc: stable@vger.kernel.org Cc: Jim Mattson Cc: Naveen N Rao (AMD) Cc: Maciej S. Szmigiero Reviewed-by: Naveen N Rao (AMD) Reviewed-by: Jim Mattson Link: https://patch.msgid.link/20260203190711.458413-3-seanjc@google.com Signed-off-by: Sean Christopherson [Squash fix to avic_deactivate_vmcb. - Paolo] Signed-off-by: Paolo Bonzini Signed-off-by: Sasha Levin --- arch/x86/kvm/svm/avic.c | 7 +++++-- arch/x86/kvm/svm/svm.c | 7 ++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c index ca7841bcbf1d7..b685bc4507e20 100644 --- a/arch/x86/kvm/svm/avic.c +++ b/arch/x86/kvm/svm/avic.c @@ -104,12 +104,12 @@ static void avic_activate_vmcb(struct vcpu_svm *svm) struct kvm_vcpu *vcpu = &svm->vcpu; vmcb->control.int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK); - vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK; vmcb->control.avic_physical_id |= avic_get_max_physical_id(vcpu); - vmcb->control.int_ctl |= AVIC_ENABLE_MASK; + svm_clr_intercept(svm, INTERCEPT_CR8_WRITE); + /* * Note: KVM supports hybrid-AVIC mode, where KVM emulates x2APIC MSR * accesses, while interrupt injection to a running vCPU can be @@ -141,6 +141,9 @@ static void avic_deactivate_vmcb(struct vcpu_svm *svm) vmcb->control.int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK); vmcb->control.avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK; + if (!sev_es_guest(svm->vcpu.kvm)) + svm_set_intercept(svm, INTERCEPT_CR8_WRITE); + /* * If running nested and the guest uses its own MSR bitmap, there * is no need to update L0's msr bitmap diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 9ddd1ee5f3123..74fac4a50e1ca 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -1261,8 +1261,7 @@ static void init_vmcb(struct kvm_vcpu *vcpu) svm_set_intercept(svm, INTERCEPT_CR0_WRITE); svm_set_intercept(svm, INTERCEPT_CR3_WRITE); svm_set_intercept(svm, INTERCEPT_CR4_WRITE); - if (!kvm_vcpu_apicv_active(vcpu)) - svm_set_intercept(svm, INTERCEPT_CR8_WRITE); + svm_set_intercept(svm, INTERCEPT_CR8_WRITE); set_dr_intercepts(svm); @@ -2806,9 +2805,11 @@ static int dr_interception(struct kvm_vcpu *vcpu) static int cr8_write_interception(struct kvm_vcpu *vcpu) { + u8 cr8_prev = kvm_get_cr8(vcpu); int r; - u8 cr8_prev = kvm_get_cr8(vcpu); + WARN_ON_ONCE(kvm_vcpu_apicv_active(vcpu)); + /* instruction emulation calls kvm_set_cr8() */ r = cr_interception(vcpu); if (lapic_in_kernel(vcpu)) -- 2.51.0