From: Maxim Levitsky <mlevitsk@redhat.com>
To: Sean Christopherson <seanjc@google.com>,
Paolo Bonzini <pbonzini@redhat.com>
Cc: Vitaly Kuznetsov <vkuznets@redhat.com>,
Wanpeng Li <wanpengli@tencent.com>,
Jim Mattson <jmattson@google.com>, Joerg Roedel <joro@8bytes.org>,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 2/2] KVM: x86: Simplify APICv update request logic
Date: Sun, 10 Oct 2021 15:49:10 +0300 [thread overview]
Message-ID: <c446956c622d5f6561f5248c7f686033ffc2ee69.camel@redhat.com> (raw)
In-Reply-To: <20211009010135.4031460-3-seanjc@google.com>
On Fri, 2021-10-08 at 18:01 -0700, Sean Christopherson wrote:
> Drop confusing and flawed code that intentionally sets that per-VM APICv
> inhibit mask after sending KVM_REQ_APICV_UPDATE to all vCPUs. The code
> is confusing because it's not obvious that there's no race between a CPU
> seeing the request and consuming the new mask. The code works only
> because the request handling path takes the same lock, i.e. responding
> vCPUs will be blocked until the full update completes.
Actually this code is here on purpose:
While it is true that the main reader of apicv_inhibit_reasons (KVM_REQ_APICV_UPDATE handler)
does take the kvm->arch.apicv_update_lock lock, so it will see the correct value
regardless of this patch, the reason why this code first raises the KVM_REQ_APICV_UPDATE
and only then updates the arch.apicv_inhibit_reasons is that I put a warning into svm_vcpu_run
which checks that per cpu AVIC inhibit state matches the global AVIC inhibit state.
That warning proved to be very useful to ensure that AVIC inhibit works correctly.
If this patch is applied, the warning can no longer work reliably unless
it takes the apicv_update_lock which will have a performance hit.
The reason is that if we just update apicv_inhibit_reasons, we can race
with vCPU which is about to re-enter the guest mode and trigger this warning.
Best regards,
Maxim Levitsky
>
> The concept is flawed because ordering the mask update after the request
> can't be relied upon for correct behavior. The only guarantee provided
> by kvm_make_all_cpus_request() is that all vCPUs exited the guest. It
> does not guarantee all vCPUs are waiting on the lock. E.g. a VCPU could
> be in the process of handling an emulated MMIO APIC access page fault
> that occurred before the APICv update was initiated, and thus toggling
> and reading the per-VM field would be racy. If correctness matters, KVM
> either needs to use the per-vCPU status (if appropriate), take the lock,
> or have some other mechanism that guarantees the per-VM status is correct.
>
> Cc: Maxim Levitsky <mlevitsk@redhat.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
> arch/x86/kvm/x86.c | 16 +++++++---------
> 1 file changed, 7 insertions(+), 9 deletions(-)
>
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 4a52a08707de..960c2d196843 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -9431,29 +9431,27 @@ EXPORT_SYMBOL_GPL(kvm_vcpu_update_apicv);
>
> void __kvm_request_apicv_update(struct kvm *kvm, bool activate, ulong bit)
> {
> - unsigned long old, new;
> + unsigned long old;
>
> if (!kvm_x86_ops.check_apicv_inhibit_reasons ||
> !static_call(kvm_x86_check_apicv_inhibit_reasons)(bit))
> return;
>
> - old = new = kvm->arch.apicv_inhibit_reasons;
> + old = kvm->arch.apicv_inhibit_reasons;
>
> if (activate)
> - __clear_bit(bit, &new);
> + __clear_bit(bit, &kvm->arch.apicv_inhibit_reasons);
> else
> - __set_bit(bit, &new);
> + __set_bit(bit, &kvm->arch.apicv_inhibit_reasons);
>
> - if (!!old != !!new) {
> + if (!!old != !!kvm->arch.apicv_inhibit_reasons) {
> trace_kvm_apicv_update_request(activate, bit);
> kvm_make_all_cpus_request(kvm, KVM_REQ_APICV_UPDATE);
> - kvm->arch.apicv_inhibit_reasons = new;
> - if (new) {
> + if (kvm->arch.apicv_inhibit_reasons) {
> unsigned long gfn = gpa_to_gfn(APIC_DEFAULT_PHYS_BASE);
> kvm_zap_gfn_range(kvm, gfn, gfn+1);
> }
> - } else
> - kvm->arch.apicv_inhibit_reasons = new;
> + }
> }
> EXPORT_SYMBOL_GPL(__kvm_request_apicv_update);
>
next prev parent reply other threads:[~2021-10-10 12:49 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-09 1:01 [PATCH 0/2] KVM: x86: Fix and cleanup for recent AVIC changes Sean Christopherson
2021-10-09 1:01 ` [PATCH 1/2] KVM: x86/mmu: Use vCPU's APICv status when handling APIC_ACCESS memslot Sean Christopherson
2021-10-10 12:47 ` Maxim Levitsky
2021-10-09 1:01 ` [PATCH 2/2] KVM: x86: Simplify APICv update request logic Sean Christopherson
2021-10-10 12:49 ` Maxim Levitsky [this message]
2021-10-11 17:55 ` Sean Christopherson
2021-10-10 12:37 ` [PATCH 0/2] KVM: x86: Fix and cleanup for recent AVIC changes Maxim Levitsky
2021-10-11 14:27 ` Sean Christopherson
2021-10-11 16:58 ` Sean Christopherson
2021-10-12 9:53 ` Maxim Levitsky
2021-10-15 16:15 ` Sean Christopherson
2021-10-15 16:23 ` Paolo Bonzini
2021-10-15 16:36 ` Sean Christopherson
2021-10-15 17:50 ` Paolo Bonzini
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=c446956c622d5f6561f5248c7f686033ffc2ee69.camel@redhat.com \
--to=mlevitsk@redhat.com \
--cc=jmattson@google.com \
--cc=joro@8bytes.org \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
--cc=vkuznets@redhat.com \
--cc=wanpengli@tencent.com \
/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®