@@ -671,102 +671,120 @@ static void kvm_apic_disabled_lapic_found(struct kvm *kvm)
671
671
}
672
672
}
673
673
674
- bool kvm_irq_delivery_to_apic_fast (struct kvm * kvm , struct kvm_lapic * src ,
675
- struct kvm_lapic_irq * irq , int * r , struct dest_map * dest_map )
676
- {
677
- struct kvm_apic_map * map ;
678
- unsigned long bitmap = 1 ;
679
- struct kvm_lapic * * dst ;
680
- int i ;
681
- bool ret , x2apic_ipi ;
674
+ /* Return true if the interrupt can be handled by using *bitmap as index mask
675
+ * for valid destinations in *dst array.
676
+ * Return false if kvm_apic_map_get_dest_lapic did nothing useful.
677
+ * Note: we may have zero kvm_lapic destinations when we return true, which
678
+ * means that the interrupt should be dropped. In this case, *bitmap would be
679
+ * zero and *dst undefined.
680
+ */
681
+ static inline bool kvm_apic_map_get_dest_lapic (struct kvm * kvm ,
682
+ struct kvm_lapic * * src , struct kvm_lapic_irq * irq ,
683
+ struct kvm_apic_map * map , struct kvm_lapic * * * dst ,
684
+ unsigned long * bitmap )
685
+ {
686
+ int i , lowest ;
687
+ bool x2apic_ipi ;
688
+ u16 cid ;
689
+
690
+ if (irq -> shorthand == APIC_DEST_SELF && src ) {
691
+ * dst = src ;
692
+ * bitmap = 1 ;
693
+ return true;
694
+ } else if (irq -> shorthand )
695
+ return false;
682
696
683
- * r = -1 ;
697
+ x2apic_ipi = src && * src && apic_x2apic_mode (* src );
698
+ if (irq -> dest_id == (x2apic_ipi ? X2APIC_BROADCAST : APIC_BROADCAST ))
699
+ return false;
684
700
685
- if (irq -> shorthand == APIC_DEST_SELF ) {
686
- * r = kvm_apic_set_irq (src -> vcpu , irq , dest_map );
701
+ if (!map )
702
+ return false;
703
+
704
+ if (irq -> dest_mode == APIC_DEST_PHYSICAL ) {
705
+ if (irq -> dest_id >= ARRAY_SIZE (map -> phys_map )) {
706
+ * bitmap = 0 ;
707
+ } else {
708
+ * dst = & map -> phys_map [irq -> dest_id ];
709
+ * bitmap = 1 ;
710
+ }
687
711
return true;
688
712
}
689
713
690
- if (irq -> shorthand )
714
+ if (! kvm_apic_logical_map_valid ( map ) )
691
715
return false;
692
716
693
- x2apic_ipi = src && apic_x2apic_mode (src );
694
- if (irq -> dest_id == (x2apic_ipi ? X2APIC_BROADCAST : APIC_BROADCAST ))
695
- return false;
696
-
697
- ret = true;
698
- rcu_read_lock ();
699
- map = rcu_dereference (kvm -> arch .apic_map );
717
+ apic_logical_id (map , irq -> dest_id , & cid , (u16 * )bitmap );
700
718
701
- if (! map ) {
702
- ret = false ;
703
- goto out ;
719
+ if (cid >= ARRAY_SIZE ( map -> logical_map ) ) {
720
+ * bitmap = 0 ;
721
+ return true ;
704
722
}
705
723
706
- if (irq -> dest_mode == APIC_DEST_PHYSICAL ) {
707
- if (irq -> dest_id >= ARRAY_SIZE (map -> phys_map ))
708
- goto out ;
724
+ * dst = map -> logical_map [cid ];
709
725
710
- dst = & map -> phys_map [irq -> dest_id ];
711
- } else {
712
- u16 cid ;
726
+ if (!kvm_lowest_prio_delivery (irq ))
727
+ return true;
713
728
714
- if (!kvm_apic_logical_map_valid (map )) {
715
- ret = false;
716
- goto out ;
729
+ if (!kvm_vector_hashing_enabled ()) {
730
+ lowest = -1 ;
731
+ for_each_set_bit (i , bitmap , 16 ) {
732
+ if (!(* dst )[i ])
733
+ continue ;
734
+ if (lowest < 0 )
735
+ lowest = i ;
736
+ else if (kvm_apic_compare_prio ((* dst )[i ]-> vcpu ,
737
+ (* dst )[lowest ]-> vcpu ) < 0 )
738
+ lowest = i ;
717
739
}
740
+ } else {
741
+ if (!* bitmap )
742
+ return true;
718
743
719
- apic_logical_id (map , irq -> dest_id , & cid , (u16 * )& bitmap );
744
+ lowest = kvm_vector_to_index (irq -> vector , hweight16 (* bitmap ),
745
+ bitmap , 16 );
720
746
721
- if (cid >= ARRAY_SIZE (map -> logical_map ))
722
- goto out ;
747
+ if (!(* dst )[lowest ]) {
748
+ kvm_apic_disabled_lapic_found (kvm );
749
+ * bitmap = 0 ;
750
+ return true;
751
+ }
752
+ }
723
753
724
- dst = map -> logical_map [ cid ] ;
754
+ * bitmap = ( lowest >= 0 ) ? 1 << lowest : 0 ;
725
755
726
- if (! kvm_lowest_prio_delivery ( irq ))
727
- goto set_irq ;
756
+ return true;
757
+ }
728
758
729
- if (!kvm_vector_hashing_enabled ()) {
730
- int l = -1 ;
731
- for_each_set_bit (i , & bitmap , 16 ) {
732
- if (!dst [i ])
733
- continue ;
734
- if (l < 0 )
735
- l = i ;
736
- else if (kvm_apic_compare_prio (dst [i ]-> vcpu ,
737
- dst [l ]-> vcpu ) < 0 )
738
- l = i ;
739
- }
740
- bitmap = (l >= 0 ) ? 1 << l : 0 ;
741
- } else {
742
- int idx ;
743
- unsigned int dest_vcpus ;
759
+ bool kvm_irq_delivery_to_apic_fast (struct kvm * kvm , struct kvm_lapic * src ,
760
+ struct kvm_lapic_irq * irq , int * r , struct dest_map * dest_map )
761
+ {
762
+ struct kvm_apic_map * map ;
763
+ unsigned long bitmap ;
764
+ struct kvm_lapic * * dst = NULL ;
765
+ int i ;
766
+ bool ret ;
744
767
745
- dest_vcpus = hweight16 (bitmap );
746
- if (dest_vcpus == 0 )
747
- goto out ;
768
+ * r = -1 ;
748
769
749
- idx = kvm_vector_to_index (irq -> vector ,
750
- dest_vcpus , & bitmap , 16 );
770
+ if (irq -> shorthand == APIC_DEST_SELF ) {
771
+ * r = kvm_apic_set_irq (src -> vcpu , irq , dest_map );
772
+ return true;
773
+ }
751
774
752
- if (!dst [idx ]) {
753
- kvm_apic_disabled_lapic_found (kvm );
754
- goto out ;
755
- }
775
+ rcu_read_lock ();
776
+ map = rcu_dereference (kvm -> arch .apic_map );
756
777
757
- bitmap = (idx >= 0 ) ? 1 << idx : 0 ;
778
+ ret = kvm_apic_map_get_dest_lapic (kvm , & src , irq , map , & dst , & bitmap );
779
+ if (ret )
780
+ for_each_set_bit (i , & bitmap , 16 ) {
781
+ if (!dst [i ])
782
+ continue ;
783
+ if (* r < 0 )
784
+ * r = 0 ;
785
+ * r += kvm_apic_set_irq (dst [i ]-> vcpu , irq , dest_map );
758
786
}
759
- }
760
787
761
- set_irq :
762
- for_each_set_bit (i , & bitmap , 16 ) {
763
- if (!dst [i ])
764
- continue ;
765
- if (* r < 0 )
766
- * r = 0 ;
767
- * r += kvm_apic_set_irq (dst [i ]-> vcpu , irq , dest_map );
768
- }
769
- out :
770
788
rcu_read_unlock ();
771
789
return ret ;
772
790
}
@@ -789,78 +807,26 @@ bool kvm_intr_is_single_vcpu_fast(struct kvm *kvm, struct kvm_lapic_irq *irq,
789
807
struct kvm_vcpu * * dest_vcpu )
790
808
{
791
809
struct kvm_apic_map * map ;
810
+ unsigned long bitmap ;
811
+ struct kvm_lapic * * dst = NULL ;
792
812
bool ret = false;
793
- struct kvm_lapic * dst = NULL ;
794
813
795
814
if (irq -> shorthand )
796
815
return false;
797
816
798
817
rcu_read_lock ();
799
818
map = rcu_dereference (kvm -> arch .apic_map );
800
819
801
- if (!map )
802
- goto out ;
803
-
804
- if (irq -> dest_mode == APIC_DEST_PHYSICAL ) {
805
- if (irq -> dest_id == 0xFF )
806
- goto out ;
807
-
808
- if (irq -> dest_id >= ARRAY_SIZE (map -> phys_map ))
809
- goto out ;
810
-
811
- dst = map -> phys_map [irq -> dest_id ];
812
- if (dst && kvm_apic_present (dst -> vcpu ))
813
- * dest_vcpu = dst -> vcpu ;
814
- else
815
- goto out ;
816
- } else {
817
- u16 cid ;
818
- unsigned long bitmap = 1 ;
819
- int i , r = 0 ;
820
-
821
- if (!kvm_apic_logical_map_valid (map ))
822
- goto out ;
823
-
824
- apic_logical_id (map , irq -> dest_id , & cid , (u16 * )& bitmap );
825
-
826
- if (cid >= ARRAY_SIZE (map -> logical_map ))
827
- goto out ;
828
-
829
- if (kvm_vector_hashing_enabled () &&
830
- kvm_lowest_prio_delivery (irq )) {
831
- int idx ;
832
- unsigned int dest_vcpus ;
820
+ if (kvm_apic_map_get_dest_lapic (kvm , NULL , irq , map , & dst , & bitmap ) &&
821
+ hweight16 (bitmap ) == 1 ) {
822
+ unsigned long i = find_first_bit (& bitmap , 16 );
833
823
834
- dest_vcpus = hweight16 (bitmap );
835
- if (dest_vcpus == 0 )
836
- goto out ;
837
-
838
- idx = kvm_vector_to_index (irq -> vector , dest_vcpus ,
839
- & bitmap , 16 );
840
-
841
- dst = map -> logical_map [cid ][idx ];
842
- if (!dst ) {
843
- kvm_apic_disabled_lapic_found (kvm );
844
- goto out ;
845
- }
846
-
847
- * dest_vcpu = dst -> vcpu ;
848
- } else {
849
- for_each_set_bit (i , & bitmap , 16 ) {
850
- dst = map -> logical_map [cid ][i ];
851
- if (++ r == 2 )
852
- goto out ;
853
- }
854
-
855
- if (dst && kvm_apic_present (dst -> vcpu ))
856
- * dest_vcpu = dst -> vcpu ;
857
- else
858
- goto out ;
824
+ if (dst [i ]) {
825
+ * dest_vcpu = dst [i ]-> vcpu ;
826
+ ret = true;
859
827
}
860
828
}
861
829
862
- ret = true;
863
- out :
864
830
rcu_read_unlock ();
865
831
return ret ;
866
832
}
0 commit comments