All of lore.kernel.org
 help / color / mirror / Atom feed
From: Maxim Levitsky <mlevitsk@redhat.com>
To: Sean Christopherson <seanjc@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	kvm@vger.kernel.org,
	"open list:X86 ARCHITECTURE (32-BIT AND 64-BIT)" 
	<linux-kernel@vger.kernel.org>,
	Wanpeng Li <wanpengli@tencent.com>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Joerg Roedel <joro@8bytes.org>, "H. Peter Anvin" <hpa@zytor.com>,
	Vitaly Kuznetsov <vkuznets@redhat.com>,
	Borislav Petkov <bp@alien8.de>,
	"maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT)"
	<x86@kernel.org>, Ingo Molnar <mingo@redhat.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Jim Mattson <jmattson@google.com>
Subject: Re: [PATCH 3/6] KVM: SVM: fix AVIC race of host->guest IPI delivery vs AVIC inhibition
Date: Thu, 09 Dec 2021 17:33:33 +0200	[thread overview]
Message-ID: <14c4784b5e2bfbe813964485b46052315b533744.camel@redhat.com> (raw)
In-Reply-To: <YbIgb4V7jcx2tZ0R@google.com>

On Thu, 2021-12-09 at 15:27 +0000, Sean Christopherson wrote:
> On Thu, Dec 09, 2021, Maxim Levitsky wrote:
> > On Thu, 2021-12-09 at 15:11 +0100, Paolo Bonzini wrote:
> > > On 12/9/21 12:54, Maxim Levitsky wrote:
> > > > If svm_deliver_avic_intr is called just after the target vcpu's AVIC got
> > > > inhibited, it might read a stale value of vcpu->arch.apicv_active
> > > > which can lead to the target vCPU not noticing the interrupt.
> > > > 
> > > > Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
> > > > ---
> > > >   arch/x86/kvm/svm/avic.c | 16 +++++++++++++---
> > > >   1 file changed, 13 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
> > > > index 859ad2dc50f1..8c1b934bfa9b 100644
> > > > --- a/arch/x86/kvm/svm/avic.c
> > > > +++ b/arch/x86/kvm/svm/avic.c
> > > > @@ -691,6 +691,15 @@ int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
> > > >   	 * automatically process AVIC interrupts at VMRUN.
> > > >   	 */
> > > >   	if (vcpu->mode == IN_GUEST_MODE) {
> > > > +
> > > > +		/*
> > > > +		 * At this point we had read the vcpu->arch.apicv_active == true
> > > > +		 * and the vcpu->mode == IN_GUEST_MODE.
> > > > +		 * Since we have a memory barrier after setting IN_GUEST_MODE,
> > > > +		 * it ensures that AVIC inhibition is complete and thus
> > > > +		 * the target is really running with AVIC enabled.
> > > > +		 */
> > > > +
> > > >   		int cpu = READ_ONCE(vcpu->cpu);
> > > 
> > > I don't think it's correct.  The vCPU has apicv_active written (in 
> > > kvm_vcpu_update_apicv) before vcpu->mode.
> > 
> > I thought that we have a full memory barrier just prior to setting IN_GUEST_MODE
> > thus if I see vcpu->mode == IN_GUEST_MODE then I'll see correct apicv_active value.
> > But apparently the memory barrier is after setting vcpu->mode.
> > 
> > 
> > > For the acquire/release pair to work properly you need to 1) read 
> > > apicv_active *after* vcpu->mode here 2) use store_release and 
> > > load_acquire for vcpu->mode, respectively in vcpu_enter_guest and here.
> > 
> > store_release for vcpu->mode in vcpu_enter_guest means a write barrier just before setting it,
> > which I expected to be there.
> > 
> > And yes I see now, I need a read barrier here as well. I am still learning this.
> 
> Sans barriers and comments, can't this be written as returning an "error" if the
> vCPU is not IN_GUEST_MODE?  Effectively the same thing, but a little more precise
> and it avoids duplicating the lapic.c code.

Yes, beside the fact that we already set the vIRR bit so if I return -1 here, it will be set again..
(and these are set using atomic ops)

I don't know how much that matters except the fact that while a vCPU runs a nested guest,
callers wishing to send IPI to it, will go through this code path a lot 
(even when I implement nested AVIC as it is a separate thing which is used by L2 only).

Best regards,
	Maxim Levitsky

> 
> diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
> index 26ed5325c593..cddf7a8da3ea 100644
> --- a/arch/x86/kvm/svm/avic.c
> +++ b/arch/x86/kvm/svm/avic.c
> @@ -671,7 +671,7 @@ void svm_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
> 
>  int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
>  {
> -       if (!vcpu->arch.apicv_active)
> +       if (vcpu->mode != IN_GUEST_MODE || !vcpu->arch.apicv_active)
>                 return -1;
> 
>         kvm_lapic_set_irr(vec, vcpu->arch.apic);
> @@ -706,8 +706,9 @@ int svm_deliver_avic_intr(struct kvm_vcpu *vcpu, int vec)
>                 put_cpu();
>         } else {
>                 /*
> -                * Wake the vCPU if it was blocking.  KVM will then detect the
> -                * pending IRQ when checking if the vCPU has a wake event.
> +                * Wake the vCPU if it is blocking.  If the vCPU exited the
> +                * guest since the previous vcpu->mode check, it's guaranteed
> +                * to see the event before re-enterring the guest.
>                  */
>                 kvm_vcpu_wake_up(vcpu);
>         }
> 



  reply	other threads:[~2021-12-09 15:33 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-09 11:54 [PATCH 0/6] RFC: KVM: SVM: Allow L1's AVIC to co-exist with nesting Maxim Levitsky
2021-12-09 11:54 ` [PATCH 1/6] KVM: SVM: allow to force AVIC to be enabled Maxim Levitsky
2021-12-09 11:54 ` [PATCH 2/6] KVM: x86: add a tracepoint for APICv/AVIC interrupt delivery Maxim Levitsky
2021-12-09 11:54 ` [PATCH 3/6] KVM: SVM: fix AVIC race of host->guest IPI delivery vs AVIC inhibition Maxim Levitsky
2021-12-09 14:11   ` Paolo Bonzini
2021-12-09 14:26     ` Maxim Levitsky
2021-12-09 15:27       ` Sean Christopherson
2021-12-09 15:33         ` Maxim Levitsky [this message]
2021-12-09 15:35           ` Maxim Levitsky
2021-12-09 11:54 ` [PATCH 4/6] KVM: SVM: fix races in the AVIC incomplete IPI delivery to vCPUs Maxim Levitsky
2021-12-09 15:38   ` Sean Christopherson
2021-12-10 11:37     ` Paolo Bonzini
2021-12-09 11:54 ` [PATCH 5/6] KVM: x86: never clear irr_pending in kvm_apic_update_apicv Maxim Levitsky
2021-12-09 14:12   ` Paolo Bonzini
2021-12-09 15:03     ` Maxim Levitsky
2021-12-10 12:07   ` Paolo Bonzini
2021-12-10 12:20     ` Maxim Levitsky
2021-12-10 12:47       ` Maxim Levitsky
2021-12-10 13:03         ` Paolo Bonzini
2021-12-10 13:10           ` Maxim Levitsky
2021-12-09 11:54 ` [PATCH 6/6] KVM: SVM: allow AVIC to co-exist with a nested guest running Maxim Levitsky

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=14c4784b5e2bfbe813964485b46052315b533744.camel@redhat.com \
    --to=mlevitsk@redhat.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=jmattson@google.com \
    --cc=joro@8bytes.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=tglx@linutronix.de \
    --cc=vkuznets@redhat.com \
    --cc=wanpengli@tencent.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.