diff options
author | Radim Krčmář <rkrcmar@redhat.com> | 2015-02-12 13:41:33 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-04-08 04:47:01 -0400 |
commit | 3548a259f6990d8cb4f520e6c14f4b45b1f2fd38 (patch) | |
tree | 05ccddb27cac89d62a30168d20b5a15a4f8e4f8f /arch/x86/kvm | |
parent | 9ea369b032d87b88f1a47187b51ad4321dea5766 (diff) |
KVM: x86: avoid logical_map when it is invalid
We want to support mixed modes and the easiest solution is to avoid
optimizing those weird and unlikely scenarios.
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
Message-Id: <1423766494-26150-4-git-send-email-rkrcmar@redhat.com>
[Add comment above KVM_APIC_MODE_* defines. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/x86/kvm')
-rw-r--r-- | arch/x86/kvm/lapic.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index d45f00ba7440..fa4bd89ea381 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c | |||
@@ -133,6 +133,14 @@ static inline int kvm_apic_id(struct kvm_lapic *apic) | |||
133 | return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff; | 133 | return (kvm_apic_get_reg(apic, APIC_ID) >> 24) & 0xff; |
134 | } | 134 | } |
135 | 135 | ||
136 | /* The logical map is definitely wrong if we have multiple | ||
137 | * modes at the same time. (Physical map is always right.) | ||
138 | */ | ||
139 | static inline bool kvm_apic_logical_map_valid(struct kvm_apic_map *map) | ||
140 | { | ||
141 | return !(map->mode & (map->mode - 1)); | ||
142 | } | ||
143 | |||
136 | static void recalculate_apic_map(struct kvm *kvm) | 144 | static void recalculate_apic_map(struct kvm *kvm) |
137 | { | 145 | { |
138 | struct kvm_apic_map *new, *old = NULL; | 146 | struct kvm_apic_map *new, *old = NULL; |
@@ -162,16 +170,19 @@ static void recalculate_apic_map(struct kvm *kvm) | |||
162 | new->ldr_bits = 32; | 170 | new->ldr_bits = 32; |
163 | new->cid_shift = 16; | 171 | new->cid_shift = 16; |
164 | new->cid_mask = new->lid_mask = 0xffff; | 172 | new->cid_mask = new->lid_mask = 0xffff; |
173 | new->mode |= KVM_APIC_MODE_X2APIC; | ||
165 | } else if (kvm_apic_get_reg(apic, APIC_LDR)) { | 174 | } else if (kvm_apic_get_reg(apic, APIC_LDR)) { |
166 | if (kvm_apic_get_reg(apic, APIC_DFR) == | 175 | if (kvm_apic_get_reg(apic, APIC_DFR) == |
167 | APIC_DFR_CLUSTER) { | 176 | APIC_DFR_CLUSTER) { |
168 | new->cid_shift = 4; | 177 | new->cid_shift = 4; |
169 | new->cid_mask = 0xf; | 178 | new->cid_mask = 0xf; |
170 | new->lid_mask = 0xf; | 179 | new->lid_mask = 0xf; |
180 | new->mode |= KVM_APIC_MODE_XAPIC_CLUSTER; | ||
171 | } else { | 181 | } else { |
172 | new->cid_shift = 8; | 182 | new->cid_shift = 8; |
173 | new->cid_mask = 0; | 183 | new->cid_mask = 0; |
174 | new->lid_mask = 0xff; | 184 | new->lid_mask = 0xff; |
185 | new->mode |= KVM_APIC_MODE_XAPIC_FLAT; | ||
175 | } | 186 | } |
176 | } | 187 | } |
177 | 188 | ||
@@ -201,6 +212,10 @@ static void recalculate_apic_map(struct kvm *kvm) | |||
201 | 212 | ||
202 | if (aid < ARRAY_SIZE(new->phys_map)) | 213 | if (aid < ARRAY_SIZE(new->phys_map)) |
203 | new->phys_map[aid] = apic; | 214 | new->phys_map[aid] = apic; |
215 | |||
216 | if (!kvm_apic_logical_map_valid(new)); | ||
217 | continue; | ||
218 | |||
204 | if (lid && cid < ARRAY_SIZE(new->logical_map)) | 219 | if (lid && cid < ARRAY_SIZE(new->logical_map)) |
205 | new->logical_map[cid][ffs(lid) - 1] = apic; | 220 | new->logical_map[cid][ffs(lid) - 1] = apic; |
206 | } | 221 | } |
@@ -718,7 +733,14 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src, | |||
718 | dst = &map->phys_map[irq->dest_id]; | 733 | dst = &map->phys_map[irq->dest_id]; |
719 | } else { | 734 | } else { |
720 | u32 mda = irq->dest_id << (32 - map->ldr_bits); | 735 | u32 mda = irq->dest_id << (32 - map->ldr_bits); |
721 | u16 cid = apic_cluster_id(map, mda); | 736 | u16 cid; |
737 | |||
738 | if (!kvm_apic_logical_map_valid(map)) { | ||
739 | ret = false; | ||
740 | goto out; | ||
741 | } | ||
742 | |||
743 | cid = apic_cluster_id(map, mda); | ||
722 | 744 | ||
723 | if (cid >= ARRAY_SIZE(map->logical_map)) | 745 | if (cid >= ARRAY_SIZE(map->logical_map)) |
724 | goto out; | 746 | goto out; |