@@ -327,18 +327,61 @@ static void avic_kick_vcpu(struct kvm_vcpu *vcpu, u32 icrl)
327327 icrl & APIC_VECTOR_MASK );
328328}
329329
330+ static void avic_kick_vcpu_by_physical_id (struct kvm * kvm , u32 physical_id ,
331+ u32 icrl )
332+ {
333+ /*
334+ * KVM inhibits AVIC if any vCPU ID diverges from the vCPUs APIC ID,
335+ * i.e. APIC ID == vCPU ID.
336+ */
337+ struct kvm_vcpu * target_vcpu = kvm_get_vcpu_by_id (kvm , physical_id );
338+
339+ /* Once again, nothing to do if the target vCPU doesn't exist. */
340+ if (unlikely (!target_vcpu ))
341+ return ;
342+
343+ avic_kick_vcpu (target_vcpu , icrl );
344+ }
345+
346+ static void avic_kick_vcpu_by_logical_id (struct kvm * kvm , u32 * avic_logical_id_table ,
347+ u32 logid_index , u32 icrl )
348+ {
349+ u32 physical_id ;
350+
351+ if (avic_logical_id_table ) {
352+ u32 logid_entry = avic_logical_id_table [logid_index ];
353+
354+ /* Nothing to do if the logical destination is invalid. */
355+ if (unlikely (!(logid_entry & AVIC_LOGICAL_ID_ENTRY_VALID_MASK )))
356+ return ;
357+
358+ physical_id = logid_entry &
359+ AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK ;
360+ } else {
361+ /*
362+ * For x2APIC, the logical APIC ID is a read-only value that is
363+ * derived from the x2APIC ID, thus the x2APIC ID can be found
364+ * by reversing the calculation (stored in logid_index). Note,
365+ * bits 31:20 of the x2APIC ID aren't propagated to the logical
366+ * ID, but KVM limits the x2APIC ID limited to KVM_MAX_VCPU_IDS.
367+ */
368+ physical_id = logid_index ;
369+ }
370+
371+ avic_kick_vcpu_by_physical_id (kvm , physical_id , icrl );
372+ }
373+
330374/*
331375 * A fast-path version of avic_kick_target_vcpus(), which attempts to match
332376 * destination APIC ID to vCPU without looping through all vCPUs.
333377 */
334378static int avic_kick_target_vcpus_fast (struct kvm * kvm , struct kvm_lapic * source ,
335379 u32 icrl , u32 icrh , u32 index )
336380{
337- u32 l1_physical_id , dest ;
338- struct kvm_vcpu * target_vcpu ;
339381 int dest_mode = icrl & APIC_DEST_MASK ;
340382 int shorthand = icrl & APIC_SHORT_MASK ;
341383 struct kvm_svm * kvm_svm = to_kvm_svm (kvm );
384+ u32 dest ;
342385
343386 if (shorthand != APIC_DEST_NOSHORT )
344387 return - EINVAL ;
@@ -355,14 +398,14 @@ static int avic_kick_target_vcpus_fast(struct kvm *kvm, struct kvm_lapic *source
355398 if (!apic_x2apic_mode (source ) && dest == APIC_BROADCAST )
356399 return - EINVAL ;
357400
358- l1_physical_id = dest ;
359-
360- if (WARN_ON_ONCE (l1_physical_id != index ))
401+ if (WARN_ON_ONCE (dest != index ))
361402 return - EINVAL ;
362403
404+ avic_kick_vcpu_by_physical_id (kvm , dest , icrl );
363405 } else {
364- u32 bitmap , cluster ;
365- int logid_index ;
406+ u32 * avic_logical_id_table ;
407+ unsigned long bitmap , i ;
408+ u32 cluster ;
366409
367410 if (apic_x2apic_mode (source )) {
368411 /* 16 bit dest mask, 16 bit cluster id */
@@ -382,50 +425,21 @@ static int avic_kick_target_vcpus_fast(struct kvm *kvm, struct kvm_lapic *source
382425 if (unlikely (!bitmap ))
383426 return 0 ;
384427
385- if (!is_power_of_2 (bitmap ))
386- /* multiple logical destinations, use slow path */
387- return - EINVAL ;
388-
389- logid_index = cluster + __ffs (bitmap );
390-
391- if (apic_x2apic_mode (source )) {
392- /*
393- * For x2APIC, the logical APIC ID is a read-only value
394- * that is derived from the x2APIC ID, thus the x2APIC
395- * ID can be found by reversing the calculation (done
396- * above). Note, bits 31:20 of the x2APIC ID are not
397- * propagated to the logical ID, but KVM limits the
398- * x2APIC ID limited to KVM_MAX_VCPU_IDS.
399- */
400- l1_physical_id = logid_index ;
401- } else {
402- u32 * avic_logical_id_table =
403- page_address (kvm_svm -> avic_logical_id_table_page );
404-
405- u32 logid_entry = avic_logical_id_table [logid_index ];
406-
407- if (WARN_ON_ONCE (index != logid_index ))
408- return - EINVAL ;
409-
410- /* Nothing to do if the logical destination is invalid. */
411- if (unlikely (!(logid_entry & AVIC_LOGICAL_ID_ENTRY_VALID_MASK )))
412- return 0 ;
428+ if (apic_x2apic_mode (source ))
429+ avic_logical_id_table = NULL ;
430+ else
431+ avic_logical_id_table = page_address (kvm_svm -> avic_logical_id_table_page );
413432
414- l1_physical_id = logid_entry &
415- AVIC_LOGICAL_ID_ENTRY_GUEST_PHYSICAL_ID_MASK ;
416- }
433+ /*
434+ * AVIC is inhibited if vCPUs aren't mapped 1:1 with logical
435+ * IDs, thus each bit in the destination is guaranteed to map
436+ * to at most one vCPU.
437+ */
438+ for_each_set_bit (i , & bitmap , 16 )
439+ avic_kick_vcpu_by_logical_id (kvm , avic_logical_id_table ,
440+ cluster + i , icrl );
417441 }
418442
419- /*
420- * KVM inhibits AVIC if any vCPU ID diverges from the vCPUs APIC ID,
421- * i.e. APIC ID == vCPU ID. Once again, nothing to do if the target
422- * vCPU doesn't exist.
423- */
424- target_vcpu = kvm_get_vcpu_by_id (kvm , l1_physical_id );
425- if (unlikely (!target_vcpu ))
426- return 0 ;
427-
428- avic_kick_vcpu (target_vcpu , icrl );
429443 return 0 ;
430444}
431445
0 commit comments