[PATCH 07/19] KVM: SVM: Drop buggy and redundant AVIC "single logical dest" check

Sean Christopherson posted 19 patches 3 years, 7 months ago
There is a newer version of this series
[PATCH 07/19] KVM: SVM: Drop buggy and redundant AVIC "single logical dest" check
Posted by Sean Christopherson 3 years, 7 months ago
Use the already-calculated-and-sanity-checked destination bitmap when
processing a fast AVIC kick in logical mode, and drop the logical path's
flawed logic.  The intent of the check is to ensure the bitmap is a power
of two, whereas "icrh != (1 << avic)" effectively checks that the bitmap
is a power of two _and_ the target cluster is '0'.

Note, the flawed check isn't a functional issue, it simply means that KVM
will go down the slow path if the target cluster is non-zero.

Fixes: 8c9e639da435 ("KVM: SVM: Use target APIC ID to complete x2AVIC IRQs when possible")
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/svm/avic.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index 3c333cd2e752..14f567550a1e 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -411,15 +411,7 @@ static int avic_kick_target_vcpus_fast(struct kvm *kvm, struct kvm_lapic *source
 			 * Instead, calculate physical ID from logical ID in ICRH.
 			 */
 			int cluster = (icrh & 0xffff0000) >> 16;
-			int apic = ffs(icrh & 0xffff) - 1;
-
-			/*
-			 * If the x2APIC logical ID sub-field (i.e. icrh[15:0])
-			 * contains anything but a single bit, we cannot use the
-			 * fast path, because it is limited to a single vCPU.
-			 */
-			if (apic < 0 || icrh != (1 << apic))
-				return -EINVAL;
+			int apic = ffs(bitmap) - 1;
 
 			l1_physical_id = (cluster << 4) + apic;
 		}
-- 
2.37.2.672.g94769d06f0-goog
Re: [PATCH 07/19] KVM: SVM: Drop buggy and redundant AVIC "single logical dest" check
Posted by Maxim Levitsky 3 years, 7 months ago
On Wed, 2022-08-31 at 00:34 +0000, Sean Christopherson wrote:
> Use the already-calculated-and-sanity-checked destination bitmap when
> processing a fast AVIC kick in logical mode, and drop the logical path's
> flawed logic.  The intent of the check is to ensure the bitmap is a power
> of two, whereas "icrh != (1 << avic)" effectively checks that the bitmap
> is a power of two _and_ the target cluster is '0'.
> 
> Note, the flawed check isn't a functional issue, it simply means that KVM
> will go down the slow path if the target cluster is non-zero.
> 
> Fixes: 8c9e639da435 ("KVM: SVM: Use target APIC ID to complete x2AVIC IRQs when possible")
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  arch/x86/kvm/svm/avic.c | 10 +---------
>  1 file changed, 1 insertion(+), 9 deletions(-)
> 
> diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
> index 3c333cd2e752..14f567550a1e 100644
> --- a/arch/x86/kvm/svm/avic.c
> +++ b/arch/x86/kvm/svm/avic.c
> @@ -411,15 +411,7 @@ static int avic_kick_target_vcpus_fast(struct kvm *kvm, struct kvm_lapic *source
>  			 * Instead, calculate physical ID from logical ID in ICRH.
>  			 */
>  			int cluster = (icrh & 0xffff0000) >> 16;
> -			int apic = ffs(icrh & 0xffff) - 1;
> -
> -			/*
> -			 * If the x2APIC logical ID sub-field (i.e. icrh[15:0])
> -			 * contains anything but a single bit, we cannot use the
> -			 * fast path, because it is limited to a single vCPU.
> -			 */
> -			if (apic < 0 || icrh != (1 << apic))
> -				return -EINVAL;
> +			int apic = ffs(bitmap) - 1;
>  
>  			l1_physical_id = (cluster << 4) + apic;
>  		}

Oh, I didn't notice this bug. However isn't removing the check is wrong as well?

What if we do have multiple bits set in the bitmap? After you remove this code,
we will set IPI only to APIC which matches the 1st bit, no?
(The fast code only sends IPI to one vCPU)

Best regards,
	Maxim Levitsky
Re: [PATCH 07/19] KVM: SVM: Drop buggy and redundant AVIC "single logical dest" check
Posted by Sean Christopherson 3 years, 7 months ago
On Wed, Aug 31, 2022, Maxim Levitsky wrote:
> On Wed, 2022-08-31 at 00:34 +0000, Sean Christopherson wrote:
> > Use the already-calculated-and-sanity-checked destination bitmap when
> > processing a fast AVIC kick in logical mode, and drop the logical path's
> > flawed logic.  The intent of the check is to ensure the bitmap is a power
> > of two, whereas "icrh != (1 << avic)" effectively checks that the bitmap
> > is a power of two _and_ the target cluster is '0'.
> > 
> > Note, the flawed check isn't a functional issue, it simply means that KVM
> > will go down the slow path if the target cluster is non-zero.
> > 
> > Fixes: 8c9e639da435 ("KVM: SVM: Use target APIC ID to complete x2AVIC IRQs when possible")
> > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > ---
> >  arch/x86/kvm/svm/avic.c | 10 +---------
> >  1 file changed, 1 insertion(+), 9 deletions(-)
> > 
> > diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
> > index 3c333cd2e752..14f567550a1e 100644
> > --- a/arch/x86/kvm/svm/avic.c
> > +++ b/arch/x86/kvm/svm/avic.c
> > @@ -411,15 +411,7 @@ static int avic_kick_target_vcpus_fast(struct kvm *kvm, struct kvm_lapic *source
> >  			 * Instead, calculate physical ID from logical ID in ICRH.
> >  			 */
> >  			int cluster = (icrh & 0xffff0000) >> 16;
> > -			int apic = ffs(icrh & 0xffff) - 1;
> > -
> > -			/*
> > -			 * If the x2APIC logical ID sub-field (i.e. icrh[15:0])
> > -			 * contains anything but a single bit, we cannot use the
> > -			 * fast path, because it is limited to a single vCPU.
> > -			 */
> > -			if (apic < 0 || icrh != (1 << apic))
> > -				return -EINVAL;
> > +			int apic = ffs(bitmap) - 1;
> >  
> >  			l1_physical_id = (cluster << 4) + apic;
> >  		}
> 
> Oh, I didn't notice this bug. However isn't removing the check is wrong as well?
> 
> What if we do have multiple bits set in the bitmap? After you remove this code,
> we will set IPI only to APIC which matches the 1st bit, no?

The common code (out of sight here) already ensures the bitmap has exactly one bit set:

                if (unlikely(!bitmap))
                        /* guest bug: nobody to send the logical interrupt to */
                        return 0;

                if (!is_power_of_2(bitmap))
                        /* multiple logical destinations, use slow path */
                        return -EINVAL;

                logid_index = cluster + __ffs(bitmap);
Re: [PATCH 07/19] KVM: SVM: Drop buggy and redundant AVIC "single logical dest" check
Posted by Maxim Levitsky 3 years, 7 months ago
On Wed, 2022-08-31 at 16:37 +0000, Sean Christopherson wrote:
> On Wed, Aug 31, 2022, Maxim Levitsky wrote:
> > On Wed, 2022-08-31 at 00:34 +0000, Sean Christopherson wrote:
> > > Use the already-calculated-and-sanity-checked destination bitmap when
> > > processing a fast AVIC kick in logical mode, and drop the logical path's
> > > flawed logic.  The intent of the check is to ensure the bitmap is a power
> > > of two, whereas "icrh != (1 << avic)" effectively checks that the bitmap
> > > is a power of two _and_ the target cluster is '0'.
> > > 
> > > Note, the flawed check isn't a functional issue, it simply means that KVM
> > > will go down the slow path if the target cluster is non-zero.
> > > 
> > > Fixes: 8c9e639da435 ("KVM: SVM: Use target APIC ID to complete x2AVIC IRQs when possible")
> > > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > > ---
> > >  arch/x86/kvm/svm/avic.c | 10 +---------
> > >  1 file changed, 1 insertion(+), 9 deletions(-)
> > > 
> > > diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
> > > index 3c333cd2e752..14f567550a1e 100644
> > > --- a/arch/x86/kvm/svm/avic.c
> > > +++ b/arch/x86/kvm/svm/avic.c
> > > @@ -411,15 +411,7 @@ static int avic_kick_target_vcpus_fast(struct kvm *kvm, struct kvm_lapic *source
> > >  			 * Instead, calculate physical ID from logical ID in ICRH.
> > >  			 */
> > >  			int cluster = (icrh & 0xffff0000) >> 16;
> > > -			int apic = ffs(icrh & 0xffff) - 1;
> > > -
> > > -			/*
> > > -			 * If the x2APIC logical ID sub-field (i.e. icrh[15:0])
> > > -			 * contains anything but a single bit, we cannot use the
> > > -			 * fast path, because it is limited to a single vCPU.
> > > -			 */
> > > -			if (apic < 0 || icrh != (1 << apic))
> > > -				return -EINVAL;
> > > +			int apic = ffs(bitmap) - 1;
> > >  
> > >  			l1_physical_id = (cluster << 4) + apic;
> > >  		}
> > 
> > Oh, I didn't notice this bug. However isn't removing the check is wrong as well?
> > 
> > What if we do have multiple bits set in the bitmap? After you remove this code,
> > we will set IPI only to APIC which matches the 1st bit, no?
> 
> The common code (out of sight here) already ensures the bitmap has exactly one bit set:
> 
>                 if (unlikely(!bitmap))
>                         /* guest bug: nobody to send the logical interrupt to */
>                         return 0;
> 
>                 if (!is_power_of_2(bitmap))
>                         /* multiple logical destinations, use slow path */
>                         return -EINVAL;
> 
>                 logid_index = cluster + __ffs(bitmap);
> 
Ah right, but again because the patch that added x2apic logic after I already added should not
be added. I vote again to just revert it.

Best regards,
	Maxim Levitsky