@@ -106,7 +106,7 @@ static u32 next_vm_id = 0;
106106static bool next_vm_id_wrapped = 0 ;
107107static DEFINE_SPINLOCK (svm_vm_data_hash_lock );
108108static bool x2avic_enabled ;
109-
109+ static u32 x2avic_max_physical_id ;
110110
111111static void avic_set_x2apic_msr_interception (struct vcpu_svm * svm ,
112112 bool intercept )
@@ -158,12 +158,40 @@ static void avic_set_x2apic_msr_interception(struct vcpu_svm *svm,
158158 svm -> x2avic_msrs_intercepted = intercept ;
159159}
160160
161+ static u32 __avic_get_max_physical_id (struct kvm * kvm , struct kvm_vcpu * vcpu )
162+ {
163+ u32 arch_max ;
164+
165+ /*
166+ * Return the largest size (x2APIC) when querying without a vCPU, e.g.
167+ * to allocate the per-VM table..
168+ */
169+ if (x2avic_enabled && (!vcpu || apic_x2apic_mode (vcpu -> arch .apic )))
170+ arch_max = x2avic_max_physical_id ;
171+ else
172+ arch_max = AVIC_MAX_PHYSICAL_ID ;
173+
174+ /*
175+ * Despite its name, KVM_CAP_MAX_VCPU_ID represents the maximum APIC ID
176+ * plus one, so the max possible APIC ID is one less than that.
177+ */
178+ return min (kvm -> arch .max_vcpu_ids - 1 , arch_max );
179+ }
180+
181+ static u32 avic_get_max_physical_id (struct kvm_vcpu * vcpu )
182+ {
183+ return __avic_get_max_physical_id (vcpu -> kvm , vcpu );
184+ }
185+
161186static void avic_activate_vmcb (struct vcpu_svm * svm )
162187{
163188 struct vmcb * vmcb = svm -> vmcb01 .ptr ;
189+ struct kvm_vcpu * vcpu = & svm -> vcpu ;
164190
165191 vmcb -> control .int_ctl &= ~(AVIC_ENABLE_MASK | X2APIC_MODE_MASK );
192+
166193 vmcb -> control .avic_physical_id &= ~AVIC_PHYSICAL_MAX_INDEX_MASK ;
194+ vmcb -> control .avic_physical_id |= avic_get_max_physical_id (vcpu );
167195
168196 vmcb -> control .int_ctl |= AVIC_ENABLE_MASK ;
169197
@@ -176,7 +204,7 @@ static void avic_activate_vmcb(struct vcpu_svm *svm)
176204 */
177205 if (x2avic_enabled && apic_x2apic_mode (svm -> vcpu .arch .apic )) {
178206 vmcb -> control .int_ctl |= X2APIC_MODE_MASK ;
179- vmcb -> control . avic_physical_id |= X2AVIC_MAX_PHYSICAL_ID ;
207+
180208 /* Disabling MSR intercept for x2APIC registers */
181209 avic_set_x2apic_msr_interception (svm , false);
182210 } else {
@@ -186,8 +214,6 @@ static void avic_activate_vmcb(struct vcpu_svm *svm)
186214 */
187215 kvm_make_request (KVM_REQ_TLB_FLUSH_CURRENT , & svm -> vcpu );
188216
189- /* For xAVIC and hybrid-xAVIC modes */
190- vmcb -> control .avic_physical_id |= AVIC_MAX_PHYSICAL_ID ;
191217 /* Enabling MSR intercept for x2APIC registers */
192218 avic_set_x2apic_msr_interception (svm , true);
193219 }
@@ -247,6 +273,30 @@ static int avic_ga_log_notifier(u32 ga_tag)
247273 return 0 ;
248274}
249275
276+ static int avic_get_physical_id_table_order (struct kvm * kvm )
277+ {
278+ /* Provision for the maximum physical ID supported in x2avic mode */
279+ return get_order ((__avic_get_max_physical_id (kvm , NULL ) + 1 ) * sizeof (u64 ));
280+ }
281+
282+ int avic_alloc_physical_id_table (struct kvm * kvm )
283+ {
284+ struct kvm_svm * kvm_svm = to_kvm_svm (kvm );
285+
286+ if (!irqchip_in_kernel (kvm ) || !enable_apicv )
287+ return 0 ;
288+
289+ if (kvm_svm -> avic_physical_id_table )
290+ return 0 ;
291+
292+ kvm_svm -> avic_physical_id_table = (void * )__get_free_pages (GFP_KERNEL_ACCOUNT | __GFP_ZERO ,
293+ avic_get_physical_id_table_order (kvm ));
294+ if (!kvm_svm -> avic_physical_id_table )
295+ return - ENOMEM ;
296+
297+ return 0 ;
298+ }
299+
250300void avic_vm_destroy (struct kvm * kvm )
251301{
252302 unsigned long flags ;
@@ -256,7 +306,8 @@ void avic_vm_destroy(struct kvm *kvm)
256306 return ;
257307
258308 free_page ((unsigned long )kvm_svm -> avic_logical_id_table );
259- free_page ((unsigned long )kvm_svm -> avic_physical_id_table );
309+ free_pages ((unsigned long )kvm_svm -> avic_physical_id_table ,
310+ avic_get_physical_id_table_order (kvm ));
260311
261312 spin_lock_irqsave (& svm_vm_data_hash_lock , flags );
262313 hash_del (& kvm_svm -> hnode );
@@ -274,10 +325,6 @@ int avic_vm_init(struct kvm *kvm)
274325 if (!enable_apicv )
275326 return 0 ;
276327
277- kvm_svm -> avic_physical_id_table = (void * )get_zeroed_page (GFP_KERNEL_ACCOUNT );
278- if (!kvm_svm -> avic_physical_id_table )
279- goto free_avic ;
280-
281328 kvm_svm -> avic_logical_id_table = (void * )get_zeroed_page (GFP_KERNEL_ACCOUNT );
282329 if (!kvm_svm -> avic_logical_id_table )
283330 goto free_avic ;
@@ -342,7 +389,7 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
342389 * fully initialized AVIC.
343390 */
344391 if ((!x2avic_enabled && id > AVIC_MAX_PHYSICAL_ID ) ||
345- (id > X2AVIC_MAX_PHYSICAL_ID )) {
392+ (id > x2avic_max_physical_id )) {
346393 kvm_set_apicv_inhibit (vcpu -> kvm , APICV_INHIBIT_REASON_PHYSICAL_ID_TOO_BIG );
347394 vcpu -> arch .apic -> apicv_active = false;
348395 return 0 ;
@@ -562,7 +609,7 @@ int avic_incomplete_ipi_interception(struct kvm_vcpu *vcpu)
562609 u32 icrh = svm -> vmcb -> control .exit_info_1 >> 32 ;
563610 u32 icrl = svm -> vmcb -> control .exit_info_1 ;
564611 u32 id = svm -> vmcb -> control .exit_info_2 >> 32 ;
565- u32 index = svm -> vmcb -> control .exit_info_2 & 0x1FF ;
612+ u32 index = svm -> vmcb -> control .exit_info_2 & AVIC_PHYSICAL_MAX_INDEX_MASK ;
566613 struct kvm_lapic * apic = vcpu -> arch .apic ;
567614
568615 trace_kvm_avic_incomplete_ipi (vcpu -> vcpu_id , icrh , icrl , id , index );
@@ -962,7 +1009,8 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu,
9621009 if (WARN_ON (h_physical_id & ~AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK ))
9631010 return ;
9641011
965- if (WARN_ON_ONCE (vcpu -> vcpu_id * sizeof (entry ) >= PAGE_SIZE ))
1012+ if (WARN_ON_ONCE (vcpu -> vcpu_id * sizeof (entry ) >=
1013+ PAGE_SIZE << avic_get_physical_id_table_order (vcpu -> kvm )))
9661014 return ;
9671015
9681016 /*
@@ -1024,7 +1072,8 @@ static void __avic_vcpu_put(struct kvm_vcpu *vcpu, enum avic_vcpu_action action)
10241072
10251073 lockdep_assert_preemption_disabled ();
10261074
1027- if (WARN_ON_ONCE (vcpu -> vcpu_id * sizeof (entry ) >= PAGE_SIZE ))
1075+ if (WARN_ON_ONCE (vcpu -> vcpu_id * sizeof (entry ) >=
1076+ PAGE_SIZE << avic_get_physical_id_table_order (vcpu -> kvm )))
10281077 return ;
10291078
10301079 /*
@@ -1226,10 +1275,15 @@ bool __init avic_hardware_setup(void)
12261275
12271276 /* AVIC is a prerequisite for x2AVIC. */
12281277 x2avic_enabled = boot_cpu_has (X86_FEATURE_X2AVIC );
1229- if (x2avic_enabled )
1230- pr_info ("x2AVIC enabled\n" );
1231- else
1278+ if (x2avic_enabled ) {
1279+ if (cpu_feature_enabled (X86_FEATURE_X2AVIC_EXT ))
1280+ x2avic_max_physical_id = X2AVIC_4K_MAX_PHYSICAL_ID ;
1281+ else
1282+ x2avic_max_physical_id = X2AVIC_MAX_PHYSICAL_ID ;
1283+ pr_info ("x2AVIC enabled (max %u vCPUs)\n" , x2avic_max_physical_id + 1 );
1284+ } else {
12321285 svm_x86_ops .allow_apicv_in_x2apic_without_x2apic_virtualization = true;
1286+ }
12331287
12341288 /*
12351289 * Disable IPI virtualization for AMD Family 17h CPUs (Zen1 and Zen2)
0 commit comments