@@ -115,26 +115,36 @@ static inline int apic_enabled(struct kvm_lapic *apic)
115115 (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY | \
116116 APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER)
117117
118- /* The logical map is definitely wrong if we have multiple
119- * modes at the same time. (Physical map is always right.)
120- */
121- static inline bool kvm_apic_logical_map_valid (struct kvm_apic_map * map )
122- {
123- return !(map -> mode & (map -> mode - 1 ));
124- }
125-
126- static inline void
127- apic_logical_id (struct kvm_apic_map * map , u32 dest_id , u16 * cid , u16 * lid )
128- {
129- unsigned lid_bits ;
130-
131- BUILD_BUG_ON (KVM_APIC_MODE_XAPIC_CLUSTER != 4 );
132- BUILD_BUG_ON (KVM_APIC_MODE_XAPIC_FLAT != 8 );
133- BUILD_BUG_ON (KVM_APIC_MODE_X2APIC != 16 );
134- lid_bits = map -> mode ;
118+ static inline bool kvm_apic_map_get_logical_dest (struct kvm_apic_map * map ,
119+ u32 dest_id , struct kvm_lapic * * * cluster , u16 * mask ) {
120+ switch (map -> mode ) {
121+ case KVM_APIC_MODE_X2APIC : {
122+ u32 offset = (dest_id >> 16 ) * 16 ;
123+ u32 max_apic_id = ARRAY_SIZE (map -> phys_map ) - 1 ;
124+
125+ if (offset <= max_apic_id ) {
126+ u8 cluster_size = min (max_apic_id - offset + 1 , 16U );
127+
128+ * cluster = & map -> phys_map [offset ];
129+ * mask = dest_id & (0xffff >> (16 - cluster_size ));
130+ } else {
131+ * mask = 0 ;
132+ }
135133
136- * cid = dest_id >> lid_bits ;
137- * lid = dest_id & ((1 << lid_bits ) - 1 );
134+ return true;
135+ }
136+ case KVM_APIC_MODE_XAPIC_FLAT :
137+ * cluster = map -> xapic_flat_map ;
138+ * mask = dest_id & 0xff ;
139+ return true;
140+ case KVM_APIC_MODE_XAPIC_CLUSTER :
141+ * cluster = map -> xapic_cluster_map [dest_id >> 4 ];
142+ * mask = dest_id & 0xf ;
143+ return true;
144+ default :
145+ /* Not optimized. */
146+ return false;
147+ }
138148}
139149
140150static void recalculate_apic_map (struct kvm * kvm )
@@ -152,7 +162,8 @@ static void recalculate_apic_map(struct kvm *kvm)
152162
153163 kvm_for_each_vcpu (i , vcpu , kvm ) {
154164 struct kvm_lapic * apic = vcpu -> arch .apic ;
155- u16 cid , lid ;
165+ struct kvm_lapic * * cluster ;
166+ u16 mask ;
156167 u32 ldr , aid ;
157168
158169 if (!kvm_apic_present (vcpu ))
@@ -174,13 +185,11 @@ static void recalculate_apic_map(struct kvm *kvm)
174185 new -> mode |= KVM_APIC_MODE_XAPIC_CLUSTER ;
175186 }
176187
177- if (!kvm_apic_logical_map_valid (new ))
188+ if (!kvm_apic_map_get_logical_dest (new , ldr , & cluster , & mask ))
178189 continue ;
179190
180- apic_logical_id (new , ldr , & cid , & lid );
181-
182- if (lid && cid < ARRAY_SIZE (new -> logical_map ))
183- new -> logical_map [cid ][ffs (lid ) - 1 ] = apic ;
191+ if (mask )
192+ cluster [ffs (mask ) - 1 ] = apic ;
184193 }
185194out :
186195 old = rcu_dereference_protected (kvm -> arch .apic_map ,
@@ -685,7 +694,6 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm,
685694{
686695 int i , lowest ;
687696 bool x2apic_ipi ;
688- u16 cid ;
689697
690698 if (irq -> shorthand == APIC_DEST_SELF && src ) {
691699 * dst = src ;
@@ -711,18 +719,11 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm,
711719 return true;
712720 }
713721
714- if (!kvm_apic_logical_map_valid (map ))
722+ * bitmap = 0 ;
723+ if (!kvm_apic_map_get_logical_dest (map , irq -> dest_id , dst ,
724+ (u16 * )bitmap ))
715725 return false;
716726
717- apic_logical_id (map , irq -> dest_id , & cid , (u16 * )bitmap );
718-
719- if (cid >= ARRAY_SIZE (map -> logical_map )) {
720- * bitmap = 0 ;
721- return true;
722- }
723-
724- * dst = map -> logical_map [cid ];
725-
726727 if (!kvm_lowest_prio_delivery (irq ))
727728 return true;
728729
0 commit comments