diff options
Diffstat (limited to 'virt/kvm/ioapic.c')
-rw-r--r-- | virt/kvm/ioapic.c | 91 |
1 files changed, 34 insertions, 57 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 812801317e36..883fd0dc9b78 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -203,79 +203,56 @@ u32 kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest, | |||
203 | 203 | ||
204 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | 204 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) |
205 | { | 205 | { |
206 | u8 dest = ioapic->redirtbl[irq].fields.dest_id; | 206 | union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq]; |
207 | u8 dest_mode = ioapic->redirtbl[irq].fields.dest_mode; | 207 | unsigned long deliver_bitmask; |
208 | u8 delivery_mode = ioapic->redirtbl[irq].fields.delivery_mode; | ||
209 | u8 vector = ioapic->redirtbl[irq].fields.vector; | ||
210 | u8 trig_mode = ioapic->redirtbl[irq].fields.trig_mode; | ||
211 | u32 deliver_bitmask; | ||
212 | struct kvm_vcpu *vcpu; | 208 | struct kvm_vcpu *vcpu; |
213 | int vcpu_id, r = -1; | 209 | int vcpu_id, r = -1; |
214 | 210 | ||
215 | ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " | 211 | ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " |
216 | "vector=%x trig_mode=%x\n", | 212 | "vector=%x trig_mode=%x\n", |
217 | dest, dest_mode, delivery_mode, vector, trig_mode); | 213 | entry.fields.dest, entry.fields.dest_mode, |
214 | entry.fields.delivery_mode, entry.fields.vector, | ||
215 | entry.fields.trig_mode); | ||
218 | 216 | ||
219 | deliver_bitmask = kvm_ioapic_get_delivery_bitmask(ioapic, dest, | 217 | kvm_get_intr_delivery_bitmask(ioapic, &entry, &deliver_bitmask); |
220 | dest_mode); | ||
221 | if (!deliver_bitmask) { | 218 | if (!deliver_bitmask) { |
222 | ioapic_debug("no target on destination\n"); | 219 | ioapic_debug("no target on destination\n"); |
223 | return 0; | 220 | return 0; |
224 | } | 221 | } |
225 | 222 | ||
226 | switch (delivery_mode) { | 223 | /* Always delivery PIT interrupt to vcpu 0 */ |
227 | case IOAPIC_LOWEST_PRIORITY: | ||
228 | vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, vector, | ||
229 | deliver_bitmask); | ||
230 | #ifdef CONFIG_X86 | 224 | #ifdef CONFIG_X86 |
231 | if (irq == 0) | 225 | if (irq == 0) |
232 | vcpu = ioapic->kvm->vcpus[0]; | 226 | deliver_bitmask = 1; |
233 | #endif | 227 | #endif |
234 | if (vcpu != NULL) | 228 | |
235 | r = ioapic_inj_irq(ioapic, vcpu, vector, | 229 | for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) { |
236 | trig_mode, delivery_mode); | 230 | if (!(deliver_bitmask & (1 << vcpu_id))) |
237 | else | 231 | continue; |
238 | ioapic_debug("null lowest prio vcpu: " | 232 | deliver_bitmask &= ~(1 << vcpu_id); |
239 | "mask=%x vector=%x delivery_mode=%x\n", | 233 | vcpu = ioapic->kvm->vcpus[vcpu_id]; |
240 | deliver_bitmask, vector, IOAPIC_LOWEST_PRIORITY); | 234 | if (vcpu) { |
241 | break; | 235 | if (entry.fields.delivery_mode == |
242 | case IOAPIC_FIXED: | 236 | IOAPIC_LOWEST_PRIORITY || |
243 | #ifdef CONFIG_X86 | 237 | entry.fields.delivery_mode == IOAPIC_FIXED) { |
244 | if (irq == 0) | ||
245 | deliver_bitmask = 1; | ||
246 | #endif | ||
247 | for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) { | ||
248 | if (!(deliver_bitmask & (1 << vcpu_id))) | ||
249 | continue; | ||
250 | deliver_bitmask &= ~(1 << vcpu_id); | ||
251 | vcpu = ioapic->kvm->vcpus[vcpu_id]; | ||
252 | if (vcpu) { | ||
253 | if (r < 0) | 238 | if (r < 0) |
254 | r = 0; | 239 | r = 0; |
255 | r += ioapic_inj_irq(ioapic, vcpu, vector, | 240 | r += ioapic_inj_irq(ioapic, vcpu, |
256 | trig_mode, delivery_mode); | 241 | entry.fields.vector, |
257 | } | 242 | entry.fields.trig_mode, |
258 | } | 243 | entry.fields.delivery_mode); |
259 | break; | 244 | } else if (entry.fields.delivery_mode == IOAPIC_NMI) { |
260 | case IOAPIC_NMI: | ||
261 | for (vcpu_id = 0; deliver_bitmask != 0; vcpu_id++) { | ||
262 | if (!(deliver_bitmask & (1 << vcpu_id))) | ||
263 | continue; | ||
264 | deliver_bitmask &= ~(1 << vcpu_id); | ||
265 | vcpu = ioapic->kvm->vcpus[vcpu_id]; | ||
266 | if (vcpu) { | ||
267 | ioapic_inj_nmi(vcpu); | ||
268 | r = 1; | 245 | r = 1; |
269 | } | 246 | ioapic_inj_nmi(vcpu); |
270 | else | 247 | } else |
271 | ioapic_debug("NMI to vcpu %d failed\n", | 248 | ioapic_debug("unsupported delivery mode %x!\n", |
272 | vcpu->vcpu_id); | 249 | entry.fields.delivery_mode); |
273 | } | 250 | } else |
274 | break; | 251 | ioapic_debug("null destination vcpu: " |
275 | default: | 252 | "mask=%x vector=%x delivery_mode=%x\n", |
276 | printk(KERN_WARNING "Unsupported delivery mode %d\n", | 253 | entry.fields.deliver_bitmask, |
277 | delivery_mode); | 254 | entry.fields.vector, |
278 | break; | 255 | entry.fields.delivery_mode); |
279 | } | 256 | } |
280 | return r; | 257 | return r; |
281 | } | 258 | } |