From: Yosry Ahmed <yosry.ahmed@linux.dev>
To: Sean Christopherson <seanjc@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Maxim Levitsky <mlevitsk@redhat.com>,
x86@kernel.org, kvm@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH 7/7] KVM: SVM: Share more code between pre_sev_run() and pre_svm_run()
Date: Mon, 17 Mar 2025 19:36:47 +0000 [thread overview]
Message-ID: <Z9h5z1TkhA7o2eiG@google.com> (raw)
In-Reply-To: <20250313215540.4171762-8-yosry.ahmed@linux.dev>
On Thu, Mar 13, 2025 at 09:55:40PM +0000, Yosry Ahmed wrote:
> pre_svm_run() and pre_sev_run() now do some redundant work, and the
> control flow is not super clear. Specifically:
> - Both functions check if the ASID in the VMCB is the expected one.
> - Both functions check if the vCPU moved to a different physical CPU.
> - Both functions issue an ASID TLB flush if needed.
>
> Pass the ASID and whether or not SEV requires a TLB flush from
> pre_sev_run() to pre_svm_run(), and use the logic there instead.
> pre_sev_run() now only performs SEV-specific checks.
>
> Note that pre_sev_run() used svm->vcpu.arch.last_vmentry_cpu to check if
> the vCPU moved to a different physical CPU, while pre_svm_run uses
> svm->current_vmcb->cpu. The former tracks the CPU per vCPU, while the
> latter tracks it per VMCB. For SEV, they both should be equivalent since
> there is a single VMCB per-vCPU (nested is not supported).
>
> Signed-off-by: Yosry Ahmed <yosry.ahmed@linux.dev>
> ---
> arch/x86/kvm/svm/sev.c | 27 ++++++++++-----------------
> arch/x86/kvm/svm/svm.c | 10 ++++++----
> arch/x86/kvm/svm/svm.h | 2 +-
> 3 files changed, 17 insertions(+), 22 deletions(-)
>
> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
> index 1ee04d6b9356b..607139757f8ff 100644
> --- a/arch/x86/kvm/svm/sev.c
> +++ b/arch/x86/kvm/svm/sev.c
> @@ -3451,11 +3451,11 @@ void sev_es_unmap_ghcb(struct vcpu_svm *svm)
> svm->sev_es.ghcb = NULL;
> }
>
> -int pre_sev_run(struct vcpu_svm *svm, int cpu)
> +int pre_sev_run(struct vcpu_svm *svm, unsigned int *asid, bool *need_flush)
> {
> + int cpu = svm->vcpu.cpu;
> struct svm_cpu_data *sd = per_cpu_ptr(&svm_data, cpu);
> struct kvm *kvm = svm->vcpu.kvm;
> - unsigned int asid = sev_get_asid(kvm);
>
> /*
> * Reject KVM_RUN if userspace attempts to run the vCPU with an invalid
> @@ -3465,24 +3465,17 @@ int pre_sev_run(struct vcpu_svm *svm, int cpu)
> if (sev_es_guest(kvm) && !VALID_PAGE(svm->vmcb->control.vmsa_pa))
> return -EINVAL;
>
> - if (WARN_ON_ONCE(svm->vmcb->control.asid != asid)) {
> - svm->vmcb->control.asid = asid;
> - vmcb_mark_dirty(svm->vmcb, VMCB_ASID);
> - }
> -
> /*
> - * Flush guest TLB:
> - *
> - * 1) when different VMCB for the same ASID is to be run on the same host CPU.
> - * 2) or this VMCB was executed on different host CPU in previous VMRUNs.
> + * Flush the guest TLB when a difference VMCB for the same ASID is to be
> + * run on the same host CPU. The caller will also flush the TLB if the
> + * VMCB was executed on a different host CPU in previous VMRUNs.
> */
> - if (sd->sev_vmcbs[asid] == svm->vmcb &&
> - svm->vcpu.arch.last_vmentry_cpu == cpu)
> - return 0;
> + *asid = sev_get_asid(kvm);
> + if (sd->sev_vmcbs[*asid] != svm->vmcb) {
> + sd->sev_vmcbs[*asid] = svm->vmcb;
> + *need_flush = true;
> + }
>
> - sd->sev_vmcbs[asid] = svm->vmcb;
> - svm_vmcb_set_flush_asid(svm->vmcb);
> - vmcb_mark_dirty(svm->vmcb, VMCB_ASID);
> return 0;
> }
>
> diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
> index c5e2733fb856d..6b338d84e7b93 100644
> --- a/arch/x86/kvm/svm/svm.c
> +++ b/arch/x86/kvm/svm/svm.c
> @@ -3615,21 +3615,23 @@ static int pre_svm_run(struct kvm_vcpu *vcpu)
> {
> struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
> struct vcpu_svm *svm = to_svm(vcpu);
> + unsigned int asid = kvm_svm->asid;
> + bool sev_need_flush = false;
> +
> + if (sev_guest(vcpu->kvm) && pre_sev_run(svm, &asid, &sev_need_flush))
> + return -1;
>
> /*
> * If the previous VMRUN of the VMCB occurred on a different physical
> * CPU, then mark the VMCB dirty and flush the ASID. Hardware's
> * VMCB clean bits are per logical CPU, as are KVM's ASID assignments.
> */
> - if (unlikely(svm->current_vmcb->cpu != vcpu->cpu)) {
> + if (unlikely(sev_need_flush || svm->current_vmcb->cpu != vcpu->cpu)) {
> svm_vmcb_set_flush_asid(svm->vmcb);
> vmcb_mark_all_dirty(svm->vmcb);
> svm->current_vmcb->cpu = vcpu->cpu;
> }
>
> - if (sev_guest(vcpu->kvm))
> - return pre_sev_run(svm, vcpu->cpu);
> -
> /* Flush the ASID on every VMRUN if kvm_svm->asid allocation failed */
> if (unlikely(!kvm_svm->asid))
This should now check 'asid' instead of 'kvm_svm->asid'.
Same for the WARN below.
> svm_vmcb_set_flush_asid(svm->vmcb);
> diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
> index 4c6664ba4048d..f25e99c79d07d 100644
> --- a/arch/x86/kvm/svm/svm.h
> +++ b/arch/x86/kvm/svm/svm.h
> @@ -754,7 +754,7 @@ void avic_refresh_virtual_apic_mode(struct kvm_vcpu *vcpu);
>
> /* sev.c */
>
> -int pre_sev_run(struct vcpu_svm *svm, int cpu);
> +int pre_sev_run(struct vcpu_svm *svm, unsigned int *asid, bool *need_flush);
> void sev_init_vmcb(struct vcpu_svm *svm);
> void sev_vcpu_after_set_cpuid(struct vcpu_svm *svm);
> int sev_es_string_io(struct vcpu_svm *svm, int size, unsigned int port, int in);
> --
> 2.49.0.rc1.451.g8f38331e32-goog
>
next prev parent reply other threads:[~2025-03-17 19:37 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-03-13 21:55 [PATCH 0/7] Make ASIDs static for SVM Yosry Ahmed
2025-03-13 21:55 ` [PATCH 1/7] KVM: VMX: Generalize VPID allocation to be vendor-neutral Yosry Ahmed
2025-03-13 21:55 ` [PATCH 2/7] KVM: SVM: Use cached local variable in init_vmcb() Yosry Ahmed
2025-03-13 21:55 ` [PATCH 3/7] KVM: SVM: Add helpers to set/clear ASID flush Yosry Ahmed
2025-03-13 21:55 ` [PATCH 4/7] KVM: SVM: Flush everything if FLUSHBYASID is not available Yosry Ahmed
2025-03-13 21:55 ` [PATCH 5/7] KVM: SVM: Flush the ASID when running on a new CPU Yosry Ahmed
2025-03-13 21:55 ` [PATCH 6/7] KVM: SVM: Use a single ASID per VM Yosry Ahmed
2025-03-14 0:47 ` Yosry Ahmed
2025-03-17 21:11 ` Yosry Ahmed
2025-03-17 21:44 ` Jim Mattson
2025-03-17 22:13 ` Yosry Ahmed
2025-03-13 21:55 ` [PATCH 7/7] KVM: SVM: Share more code between pre_sev_run() and pre_svm_run() Yosry Ahmed
2025-03-17 19:36 ` Yosry Ahmed [this message]
2025-03-20 18:17 ` [PATCH 0/7] Make ASIDs static for SVM 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=Z9h5z1TkhA7o2eiG@google.com \
--to=yosry.ahmed@linux.dev \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mlevitsk@redhat.com \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
--cc=x86@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.