@@ -115,26 +115,36 @@ static inline int apic_enabled(struct kvm_lapic *apic)
115
115
(LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY | \
116
116
APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER)
117
117
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
+ }
135
133
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
+ }
138
148
}
139
149
140
150
static void recalculate_apic_map (struct kvm * kvm )
@@ -152,7 +162,8 @@ static void recalculate_apic_map(struct kvm *kvm)
152
162
153
163
kvm_for_each_vcpu (i , vcpu , kvm ) {
154
164
struct kvm_lapic * apic = vcpu -> arch .apic ;
155
- u16 cid , lid ;
165
+ struct kvm_lapic * * cluster ;
166
+ u16 mask ;
156
167
u32 ldr , aid ;
157
168
158
169
if (!kvm_apic_present (vcpu ))
@@ -174,13 +185,11 @@ static void recalculate_apic_map(struct kvm *kvm)
174
185
new -> mode |= KVM_APIC_MODE_XAPIC_CLUSTER ;
175
186
}
176
187
177
- if (!kvm_apic_logical_map_valid (new ))
188
+ if (!kvm_apic_map_get_logical_dest (new , ldr , & cluster , & mask ))
178
189
continue ;
179
190
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 ;
184
193
}
185
194
out :
186
195
old = rcu_dereference_protected (kvm -> arch .apic_map ,
@@ -685,7 +694,6 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm,
685
694
{
686
695
int i , lowest ;
687
696
bool x2apic_ipi ;
688
- u16 cid ;
689
697
690
698
if (irq -> shorthand == APIC_DEST_SELF && src ) {
691
699
* dst = src ;
@@ -711,18 +719,11 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm,
711
719
return true;
712
720
}
713
721
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 ))
715
725
return false;
716
726
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
-
726
727
if (!kvm_lowest_prio_delivery (irq ))
727
728
return true;
728
729
0 commit comments