diff options
author | Radim Krčmář <rkrcmar@redhat.com> | 2015-02-12 13:41:34 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-04-08 04:47:01 -0400 |
commit | 3b5a5ffa928a3f875b0d5dd284eeb7c322e1688a (patch) | |
tree | 34ce2fe7e308d821549c1e7d3c88e60386636365 /arch/x86/kvm/lapic.c | |
parent | 3548a259f6990d8cb4f520e6c14f4b45b1f2fd38 (diff) |
KVM: x86: simplify kvm_apic_map
recalculate_apic_map() uses two passes over all VCPUs. This is a relic
from time when we selected a global mode in the first pass and set up
the optimized table in the second pass (to have a consistent mode).
Recent changes made mixed mode unoptimized and we can do it in one pass.
Format of logical MDA is a function of the mode, so we encode it in
apic_logical_id() and drop obsoleted variables from the struct.
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
Message-Id: <1423766494-26150-5-git-send-email-rkrcmar@redhat.com>
[Add lid_bits temporary in apic_logical_id. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r-- | arch/x86/kvm/lapic.c | 78 |
1 files changed, 28 insertions, 50 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index fa4bd89ea381..11a0af113f27 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -141,6 +141,20 @@ static inline bool kvm_apic_logical_map_valid(struct kvm_apic_map *map) | |||
141 | return !(map->mode & (map->mode - 1)); | 141 | return !(map->mode & (map->mode - 1)); |
142 | } | 142 | } |
143 | 143 | ||
144 | static inline void | ||
145 | apic_logical_id(struct kvm_apic_map *map, u32 dest_id, u16 *cid, u16 *lid) | ||
146 | { | ||
147 | unsigned lid_bits; | ||
148 | |||
149 | BUILD_BUG_ON(KVM_APIC_MODE_XAPIC_CLUSTER != 4); | ||
150 | BUILD_BUG_ON(KVM_APIC_MODE_XAPIC_FLAT != 8); | ||
151 | BUILD_BUG_ON(KVM_APIC_MODE_X2APIC != 16); | ||
152 | lid_bits = map->mode; | ||
153 | |||
154 | *cid = dest_id >> lid_bits; | ||
155 | *lid = dest_id & ((1 << lid_bits) - 1); | ||
156 | } | ||
157 | |||
144 | static void recalculate_apic_map(struct kvm *kvm) | 158 | static void recalculate_apic_map(struct kvm *kvm) |
145 | { | 159 | { |
146 | struct kvm_apic_map *new, *old = NULL; | 160 | struct kvm_apic_map *new, *old = NULL; |
@@ -154,49 +168,6 @@ static void recalculate_apic_map(struct kvm *kvm) | |||
154 | if (!new) | 168 | if (!new) |
155 | goto out; | 169 | goto out; |
156 | 170 | ||
157 | new->ldr_bits = 8; | ||
158 | /* flat mode is default */ | ||
159 | new->cid_shift = 8; | ||
160 | new->cid_mask = 0; | ||
161 | new->lid_mask = 0xff; | ||
162 | |||
163 | kvm_for_each_vcpu(i, vcpu, kvm) { | ||
164 | struct kvm_lapic *apic = vcpu->arch.apic; | ||
165 | |||
166 | if (!kvm_apic_present(vcpu)) | ||
167 | continue; | ||
168 | |||
169 | if (apic_x2apic_mode(apic)) { | ||
170 | new->ldr_bits = 32; | ||
171 | new->cid_shift = 16; | ||
172 | new->cid_mask = new->lid_mask = 0xffff; | ||
173 | new->mode |= KVM_APIC_MODE_X2APIC; | ||
174 | } else if (kvm_apic_get_reg(apic, APIC_LDR)) { | ||
175 | if (kvm_apic_get_reg(apic, APIC_DFR) == | ||
176 | APIC_DFR_CLUSTER) { | ||
177 | new->cid_shift = 4; | ||
178 | new->cid_mask = 0xf; | ||
179 | new->lid_mask = 0xf; | ||
180 | new->mode |= KVM_APIC_MODE_XAPIC_CLUSTER; | ||
181 | } else { | ||
182 | new->cid_shift = 8; | ||
183 | new->cid_mask = 0; | ||
184 | new->lid_mask = 0xff; | ||
185 | new->mode |= KVM_APIC_MODE_XAPIC_FLAT; | ||
186 | } | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * All APICs have to be configured in the same mode by an OS. | ||
191 | * We take advatage of this while building logical id loockup | ||
192 | * table. After reset APICs are in software disabled mode, so if | ||
193 | * we find apic with different setting we assume this is the mode | ||
194 | * OS wants all apics to be in; build lookup table accordingly. | ||
195 | */ | ||
196 | if (kvm_apic_sw_enabled(apic)) | ||
197 | break; | ||
198 | } | ||
199 | |||
200 | kvm_for_each_vcpu(i, vcpu, kvm) { | 171 | kvm_for_each_vcpu(i, vcpu, kvm) { |
201 | struct kvm_lapic *apic = vcpu->arch.apic; | 172 | struct kvm_lapic *apic = vcpu->arch.apic; |
202 | u16 cid, lid; | 173 | u16 cid, lid; |
@@ -207,15 +178,25 @@ static void recalculate_apic_map(struct kvm *kvm) | |||
207 | 178 | ||
208 | aid = kvm_apic_id(apic); | 179 | aid = kvm_apic_id(apic); |
209 | ldr = kvm_apic_get_reg(apic, APIC_LDR); | 180 | ldr = kvm_apic_get_reg(apic, APIC_LDR); |
210 | cid = apic_cluster_id(new, ldr); | ||
211 | lid = apic_logical_id(new, ldr); | ||
212 | 181 | ||
213 | if (aid < ARRAY_SIZE(new->phys_map)) | 182 | if (aid < ARRAY_SIZE(new->phys_map)) |
214 | new->phys_map[aid] = apic; | 183 | new->phys_map[aid] = apic; |
215 | 184 | ||
216 | if (!kvm_apic_logical_map_valid(new)); | 185 | if (apic_x2apic_mode(apic)) { |
186 | new->mode |= KVM_APIC_MODE_X2APIC; | ||
187 | } else if (ldr) { | ||
188 | ldr = GET_APIC_LOGICAL_ID(ldr); | ||
189 | if (kvm_apic_get_reg(apic, APIC_DFR) == APIC_DFR_FLAT) | ||
190 | new->mode |= KVM_APIC_MODE_XAPIC_FLAT; | ||
191 | else | ||
192 | new->mode |= KVM_APIC_MODE_XAPIC_CLUSTER; | ||
193 | } | ||
194 | |||
195 | if (!kvm_apic_logical_map_valid(new)) | ||
217 | continue; | 196 | continue; |
218 | 197 | ||
198 | apic_logical_id(new, ldr, &cid, &lid); | ||
199 | |||
219 | if (lid && cid < ARRAY_SIZE(new->logical_map)) | 200 | if (lid && cid < ARRAY_SIZE(new->logical_map)) |
220 | new->logical_map[cid][ffs(lid) - 1] = apic; | 201 | new->logical_map[cid][ffs(lid) - 1] = apic; |
221 | } | 202 | } |
@@ -732,7 +713,6 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src, | |||
732 | 713 | ||
733 | dst = &map->phys_map[irq->dest_id]; | 714 | dst = &map->phys_map[irq->dest_id]; |
734 | } else { | 715 | } else { |
735 | u32 mda = irq->dest_id << (32 - map->ldr_bits); | ||
736 | u16 cid; | 716 | u16 cid; |
737 | 717 | ||
738 | if (!kvm_apic_logical_map_valid(map)) { | 718 | if (!kvm_apic_logical_map_valid(map)) { |
@@ -740,15 +720,13 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src, | |||
740 | goto out; | 720 | goto out; |
741 | } | 721 | } |
742 | 722 | ||
743 | cid = apic_cluster_id(map, mda); | 723 | apic_logical_id(map, irq->dest_id, &cid, (u16 *)&bitmap); |
744 | 724 | ||
745 | if (cid >= ARRAY_SIZE(map->logical_map)) | 725 | if (cid >= ARRAY_SIZE(map->logical_map)) |
746 | goto out; | 726 | goto out; |
747 | 727 | ||
748 | dst = map->logical_map[cid]; | 728 | dst = map->logical_map[cid]; |
749 | 729 | ||
750 | bitmap = apic_logical_id(map, mda); | ||
751 | |||
752 | if (irq->delivery_mode == APIC_DM_LOWEST) { | 730 | if (irq->delivery_mode == APIC_DM_LOWEST) { |
753 | int l = -1; | 731 | int l = -1; |
754 | for_each_set_bit(i, &bitmap, 16) { | 732 | for_each_set_bit(i, &bitmap, 16) { |