mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Yosry Ahmed <yosry@kernel.org>
To: Sean Christopherson <seanjc@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	Jim Mattson <jmattson@google.com>,
	kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
	Yosry Ahmed <yosry@kernel.org>,
	stable@vger.kernel.org, Stefan Teodorescu <fane@google.com>
Subject: [PATCH] KVM: SVM: Update tracked pCPU on pCPU switch
Date: Mon, 12 Oct 2026 22:47:36 +0000	[thread overview]
Message-ID: <20261012224736.2306637-1-yosry@kernel.org> (raw)

When a pCPU switch is detected in pre_svm_run(), update the tracked pCPU
and mark all fields dirty in both VMCBs (if nested is initialized), in
addition to resetting the ASID generation in both VMCBs.

Commit bf260dc9e7b8 ("KVM: SVM: Trigger new ASID allocation in both
VMCBs on pCPU switch") reset the ASID generation in both VMCBs on a pCPU
switch, but only updated the tracked pCPU for the active VMCB to avoid
unnecessarily dirtying the inactive VMCB. Leaving the inactive VMCB's
tracked pCPU set to an old pCPU still allows an ASID allocated on one
pCPU to be used on another:

- vCPU runs with both vmcb01 and vmcb02 on pCPU A (both track cpu=A).
- With vmcb01 active, vCPU migrates to pCPU B. vmcb01.cpu is updated to
B, asid_generation is reset to 0 in both VMCBs, and a new ASID is
allocated on pCPU B (setting vmcb01.asid_generation = gen_B).
vmcb02.cpu remains A.
- vCPU switches to vmcb02 and migrates back to pCPU A before
pre_svm_run(). Because vmcb02.cpu is still A, no pCPU switch is
detected, leaving vmcb01 with cpu=B and asid_generation=gen_B.
Because vmcb02.asid_generation is 0, a new ASID (asid_A) is allocated
on pCPU A.
- vCPU switches back to vmcb01 and migrates to pCPU B. Neither a pCPU
change nor a generation mismatch is detected for vmcb01, so VMRUN on
pCPU B uses asid_A (allocated on pCPU A), which may collide with
another vCPU on pCPU B.

Because the per-VMCB cpu tracking is shared between ASID management and
per-pCPU hardware VMCB clean bits, also mark both VMCBs dirty when
updating their tracked pCPU so that the inactive VMCB does not run with
stale clean bits when later entered on the new pCPU.

Fixes: bf260dc9e7b8 ("KVM: SVM: Trigger new ASID allocation in both VMCBs on pCPU switch")
Cc: stable@vger.kernel.org
Reported-by: Stefan Teodorescu <fane@google.com>
Signed-off-by: Yosry Ahmed <yosry@kernel.org>
---
 arch/x86/kvm/svm/svm.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 136069dfcd44f..0a0af0cbb6bba 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3880,7 +3880,8 @@ static int pre_svm_run(struct kvm_vcpu *vcpu)
 
 	/*
 	 * If the previous VMRUN of the VMCB occurred on a different physical
-	 * cpu, then mark the VMCB dirty as hardware's clean bits are per pCPU.
+	 * cpu, mark the VMCB dirty and reset the ASID generation, as hardware's
+	 * clean bits and ASIDs are per pCPU.
 	 *
 	 * Reset the ASID generation in both VMCBs. This will lead to assigning
 	 * a new ASID now, and then again when switching to the other VMCB.
@@ -3892,13 +3893,22 @@ static int pre_svm_run(struct kvm_vcpu *vcpu)
 	 * - The new VMCB does not detect a pCPU change and runs on pCPU A with
 	 *   the new ASID allocated on pCPU B, which is potentially used by
 	 *   another vCPU/VM.
+	 *
+	 * Note that dirtying both VMCBs is not strictly needed, but the per-CPU
+	 * tracking is shared for both ASID and clean bits, and that CPU must
+	 * match where the ASID was allocated.
 	 */
 	if (unlikely(svm->current_vmcb->cpu != vcpu->cpu)) {
-		vmcb_mark_all_dirty(svm->vmcb);
-		svm->current_vmcb->cpu = vcpu->cpu;
+		vmcb_mark_all_dirty(svm->vmcb01.ptr);
+		svm->vmcb01.cpu = vcpu->cpu;
 		svm->vmcb01.asid_generation = 0;
-		svm->nested.vmcb02.asid_generation = 0;
-        }
+
+		if (svm->nested.initialized) {
+			svm->nested.vmcb02.cpu = vcpu->cpu;
+			svm->nested.vmcb02.asid_generation = 0;
+			vmcb_mark_all_dirty(svm->nested.vmcb02.ptr);
+		}
+	}
 
 	if (is_sev_guest(vcpu))
 		return pre_sev_run(svm, vcpu->cpu);
-- 
2.56.0.385.gd3acb90ef8-goog


             reply	other threads:[~2026-10-12 22:47 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-12 22:47 Yosry Ahmed [this message]
2026-10-12 23:58 ` Jim Mattson
2026-10-13 14:49   ` Yosry Ahmed
2026-10-13 17:54     ` Jim Mattson
2026-10-13 18:11       ` Yosry Ahmed
2026-10-13 18:59         ` Jim Mattson
2026-10-13 19:30           ` Yosry Ahmed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261012224736.2306637-1-yosry@kernel.org \
    --to=yosry@kernel.org \
    --cc=fane@google.com \
    --cc=jmattson@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®