[PATCH v3 13/62] KVM: SVM: Drop redundant check in AVIC code on ID during vCPU creation

Sean Christopherson posted 62 patches 4 months ago
[PATCH v3 13/62] KVM: SVM: Drop redundant check in AVIC code on ID during vCPU creation
Posted by Sean Christopherson 4 months ago
Drop avic_get_physical_id_entry()'s compatibility check on the incoming
ID, as its sole caller, avic_init_backing_page(), performs the exact same
check.  Drop avic_get_physical_id_entry() entirely as the only remaining
functionality is getting the address of the Physical ID table, and
accessing the array without an immediate bounds check is kludgy.

Opportunistically add a compile-time assertion to ensure the vcpu_id can't
result in a bounds overflow, e.g. if KVM (really) messed up a maximum
physical ID #define, as well as run-time assertions so that a NULL pointer
dereference is morphed into a safer WARN().

No functional change intended.

Tested-by: Sairaj Kodilkar <sarunkod@amd.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/svm/avic.c | 37 +++++++++++++++----------------------
 1 file changed, 15 insertions(+), 22 deletions(-)

diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index f0a74b102c57..948bab48083b 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -256,26 +256,12 @@ void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb)
 		avic_deactivate_vmcb(svm);
 }
 
-static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu,
-				       unsigned int index)
-{
-	u64 *avic_physical_id_table;
-	struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
-
-	if ((!x2avic_enabled && index > AVIC_MAX_PHYSICAL_ID) ||
-	    (index > X2AVIC_MAX_PHYSICAL_ID))
-		return NULL;
-
-	avic_physical_id_table = page_address(kvm_svm->avic_physical_id_table_page);
-
-	return &avic_physical_id_table[index];
-}
-
 static int avic_init_backing_page(struct kvm_vcpu *vcpu)
 {
-	u64 *entry, new_entry;
-	int id = vcpu->vcpu_id;
+	struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
 	struct vcpu_svm *svm = to_svm(vcpu);
+	u32 id = vcpu->vcpu_id;
+	u64 *table, new_entry;
 
 	/*
 	 * Inhibit AVIC if the vCPU ID is bigger than what is supported by AVIC
@@ -291,6 +277,9 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
 		return 0;
 	}
 
+	BUILD_BUG_ON((AVIC_MAX_PHYSICAL_ID + 1) * sizeof(*table) > PAGE_SIZE ||
+		     (X2AVIC_MAX_PHYSICAL_ID + 1) * sizeof(*table) > PAGE_SIZE);
+
 	if (WARN_ON_ONCE(!vcpu->arch.apic->regs))
 		return -EINVAL;
 
@@ -309,9 +298,7 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
 	}
 
 	/* Setting AVIC backing page address in the phy APIC ID table */
-	entry = avic_get_physical_id_entry(vcpu, id);
-	if (!entry)
-		return -EINVAL;
+	table = page_address(kvm_svm->avic_physical_id_table_page);
 
 	/* Note, fls64() returns the bit position, +1. */
 	BUILD_BUG_ON(__PHYSICAL_MASK_SHIFT >
@@ -319,9 +306,9 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
 
 	new_entry = avic_get_backing_page_address(svm) |
 		    AVIC_PHYSICAL_ID_ENTRY_VALID_MASK;
-	WRITE_ONCE(*entry, new_entry);
+	WRITE_ONCE(table[id], new_entry);
 
-	svm->avic_physical_id_cache = entry;
+	svm->avic_physical_id_cache = &table[id];
 
 	return 0;
 }
@@ -1004,6 +991,9 @@ void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 	if (WARN_ON(h_physical_id & ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK))
 		return;
 
+	if (WARN_ON_ONCE(!svm->avic_physical_id_cache))
+		return;
+
 	/*
 	 * No need to update anything if the vCPU is blocking, i.e. if the vCPU
 	 * is being scheduled in after being preempted.  The CPU entries in the
@@ -1044,6 +1034,9 @@ void avic_vcpu_put(struct kvm_vcpu *vcpu)
 
 	lockdep_assert_preemption_disabled();
 
+	if (WARN_ON_ONCE(!svm->avic_physical_id_cache))
+		return;
+
 	/*
 	 * Note, reading the Physical ID entry outside of ir_list_lock is safe
 	 * as only the pCPU that has loaded (or is loading) the vCPU is allowed
-- 
2.50.0.rc1.591.g9c95f17f64-goog
Re: [PATCH v3 13/62] KVM: SVM: Drop redundant check in AVIC code on ID during vCPU creation
Posted by Naveen N Rao 3 months, 3 weeks ago
On Wed, Jun 11, 2025 at 03:45:16PM -0700, Sean Christopherson wrote:
>  static int avic_init_backing_page(struct kvm_vcpu *vcpu)
>  {
> -	u64 *entry, new_entry;
> -	int id = vcpu->vcpu_id;
> +	struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
>  	struct vcpu_svm *svm = to_svm(vcpu);
> +	u32 id = vcpu->vcpu_id;
> +	u64 *table, new_entry;
>  
>  	/*
>  	 * Inhibit AVIC if the vCPU ID is bigger than what is supported by AVIC
> @@ -291,6 +277,9 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
>  		return 0;
>  	}
>  
> +	BUILD_BUG_ON((AVIC_MAX_PHYSICAL_ID + 1) * sizeof(*table) > PAGE_SIZE ||
> +		     (X2AVIC_MAX_PHYSICAL_ID + 1) * sizeof(*table) > PAGE_SIZE);
						    ^^^^^^^^^^^^^^
Renaming new_entry to just 'entry' and using sizeof(entry) makes this 
more readable for me. Otherwise, for this patch:
Reviewed-by: Naveen N Rao (AMD) <naveen@kernel.org>


As an aside, there are a few static asserts to validate some of the 
related macros. Can this also be a static_assert(), or is there is 
reason to prefer BUILD_BUG_ON()?


- Naveen
Re: [PATCH v3 13/62] KVM: SVM: Drop redundant check in AVIC code on ID during vCPU creation
Posted by Sean Christopherson 3 months, 3 weeks ago
On Tue, Jun 17, 2025, Naveen N Rao wrote:
> On Wed, Jun 11, 2025 at 03:45:16PM -0700, Sean Christopherson wrote:
> >  static int avic_init_backing_page(struct kvm_vcpu *vcpu)
> >  {
> > -	u64 *entry, new_entry;
> > -	int id = vcpu->vcpu_id;
> > +	struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
> >  	struct vcpu_svm *svm = to_svm(vcpu);
> > +	u32 id = vcpu->vcpu_id;
> > +	u64 *table, new_entry;
> >  
> >  	/*
> >  	 * Inhibit AVIC if the vCPU ID is bigger than what is supported by AVIC
> > @@ -291,6 +277,9 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
> >  		return 0;
> >  	}
> >  
> > +	BUILD_BUG_ON((AVIC_MAX_PHYSICAL_ID + 1) * sizeof(*table) > PAGE_SIZE ||
> > +		     (X2AVIC_MAX_PHYSICAL_ID + 1) * sizeof(*table) > PAGE_SIZE);
> 						    ^^^^^^^^^^^^^^
> Renaming new_entry to just 'entry' and using sizeof(entry) makes this 
> more readable for me.

Good call, though I think it makes sense to do that on top so as to minimize the
churn in this patch.  I'll post a patch, unless you want the honors?

> Otherwise, for this patch:
> Reviewed-by: Naveen N Rao (AMD) <naveen@kernel.org>
> 
> As an aside, there are a few static asserts to validate some of the 
> related macros. Can this also be a static_assert(), or is there is 
> reason to prefer BUILD_BUG_ON()?

For this particular assertion, static_assert() would be fine.  That said,
BUILD_BUG_ON() is slightly preferred in this context.

The advantage of BUILD_BUG_ON() is that it works so long as the condition is
compile-time constant, whereas static_assert() requires the condition to an
integer constant expression.  E.g. BUILD_BUG_ON() can be used so long as the
condition is eventually resolved to a constant, whereas static_assert() has
stricter requirements.

E.g. the fls64() assert below is fully resolved at compile time, but isn't a
purely constant expression, i.e. that one *needs* to be BUILD_BUG_ON().

--
arch/x86/kvm/svm/avic.c: In function ‘avic_init_backing_page’:
arch/x86/kvm/svm/avic.c:293:45: error: expression in static assertion is not constant
  293 |         static_assert(__PHYSICAL_MASK_SHIFT <=
include/linux/build_bug.h:78:56: note: in definition of macro ‘__static_assert’
   78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
      |                                                        ^~~~
arch/x86/kvm/svm/avic.c:293:9: note: in expansion of macro ‘static_assert’
  293 |         static_assert(__PHYSICAL_MASK_SHIFT <=
      |         ^~~~~~~~~~~~~
make[5]: *** [scripts/Makefile.build:203: arch/x86/kvm/svm/avic.o] Error 1
--

The downside of BUILD_BUG_ON() is that it can't be used at global scope, i.e.
needs to be called from a function.

As a result, when adding an assertion in a function, using BUILD_BUG_ON() is
slightly preferred, because it's less likely to break in the future.  E.g. if
X2AVIC_MAX_PHYSICAL_ID were changed to something that is a compile-time constant,
but for whatever reason isn't a pure integer constant.
Re: [PATCH v3 13/62] KVM: SVM: Drop redundant check in AVIC code on ID during vCPU creation
Posted by Naveen N Rao 3 months, 3 weeks ago
On Tue, Jun 17, 2025 at 09:33:20AM -0700, Sean Christopherson wrote:
> On Tue, Jun 17, 2025, Naveen N Rao wrote:
> > On Wed, Jun 11, 2025 at 03:45:16PM -0700, Sean Christopherson wrote:
> > >  static int avic_init_backing_page(struct kvm_vcpu *vcpu)
> > >  {
> > > -	u64 *entry, new_entry;
> > > -	int id = vcpu->vcpu_id;
> > > +	struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
> > >  	struct vcpu_svm *svm = to_svm(vcpu);
> > > +	u32 id = vcpu->vcpu_id;
> > > +	u64 *table, new_entry;
> > >  
> > >  	/*
> > >  	 * Inhibit AVIC if the vCPU ID is bigger than what is supported by AVIC
> > > @@ -291,6 +277,9 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
> > >  		return 0;
> > >  	}
> > >  
> > > +	BUILD_BUG_ON((AVIC_MAX_PHYSICAL_ID + 1) * sizeof(*table) > PAGE_SIZE ||
> > > +		     (X2AVIC_MAX_PHYSICAL_ID + 1) * sizeof(*table) > PAGE_SIZE);
> > 						    ^^^^^^^^^^^^^^
> > Renaming new_entry to just 'entry' and using sizeof(entry) makes this 
> > more readable for me.
> 
> Good call, though I think it makes sense to do that on top so as to minimize the
> churn in this patch.  I'll post a patch, unless you want the honors?

Not at all, please feel free to add a patch (or not, given that this 
will be a trivial change).

> 
> > Otherwise, for this patch:
> > Reviewed-by: Naveen N Rao (AMD) <naveen@kernel.org>
> > 
> > As an aside, there are a few static asserts to validate some of the 
> > related macros. Can this also be a static_assert(), or is there is 
> > reason to prefer BUILD_BUG_ON()?
> 
> For this particular assertion, static_assert() would be fine.  That said,
> BUILD_BUG_ON() is slightly preferred in this context.
> 
> The advantage of BUILD_BUG_ON() is that it works so long as the condition is
> compile-time constant, whereas static_assert() requires the condition to an
> integer constant expression.  E.g. BUILD_BUG_ON() can be used so long as the
> condition is eventually resolved to a constant, whereas static_assert() has
> stricter requirements.
> 
> E.g. the fls64() assert below is fully resolved at compile time, but isn't a
> purely constant expression, i.e. that one *needs* to be BUILD_BUG_ON().
> 
> --
> arch/x86/kvm/svm/avic.c: In function ‘avic_init_backing_page’:
> arch/x86/kvm/svm/avic.c:293:45: error: expression in static assertion is not constant
>   293 |         static_assert(__PHYSICAL_MASK_SHIFT <=
> include/linux/build_bug.h:78:56: note: in definition of macro ‘__static_assert’
>    78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
>       |                                                        ^~~~
> arch/x86/kvm/svm/avic.c:293:9: note: in expansion of macro ‘static_assert’
>   293 |         static_assert(__PHYSICAL_MASK_SHIFT <=
>       |         ^~~~~~~~~~~~~
> make[5]: *** [scripts/Makefile.build:203: arch/x86/kvm/svm/avic.o] Error 1
> --
> 
> The downside of BUILD_BUG_ON() is that it can't be used at global scope, i.e.
> needs to be called from a function.
> 
> As a result, when adding an assertion in a function, using BUILD_BUG_ON() is
> slightly preferred, because it's less likely to break in the future.  E.g. if
> X2AVIC_MAX_PHYSICAL_ID were changed to something that is a compile-time constant,
> but for whatever reason isn't a pure integer constant.

Understood, thanks for the explanation.


- Naveen