.. | .. |
---|
46 | 46 | #include "lapic.h" |
---|
47 | 47 | #include "irq.h" |
---|
48 | 48 | |
---|
49 | | -#if 0 |
---|
50 | | -#define ioapic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) |
---|
51 | | -#else |
---|
52 | | -#define ioapic_debug(fmt, arg...) |
---|
53 | | -#endif |
---|
54 | 49 | static int ioapic_service(struct kvm_ioapic *vioapic, int irq, |
---|
55 | 50 | bool line_status); |
---|
| 51 | + |
---|
| 52 | +static void kvm_ioapic_update_eoi_one(struct kvm_vcpu *vcpu, |
---|
| 53 | + struct kvm_ioapic *ioapic, |
---|
| 54 | + int trigger_mode, |
---|
| 55 | + int pin); |
---|
56 | 56 | |
---|
57 | 57 | static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, |
---|
58 | 58 | unsigned long addr, |
---|
.. | .. |
---|
115 | 115 | union kvm_ioapic_redirect_entry *e; |
---|
116 | 116 | |
---|
117 | 117 | e = &ioapic->redirtbl[RTC_GSI]; |
---|
118 | | - if (!kvm_apic_match_dest(vcpu, NULL, 0, e->fields.dest_id, |
---|
119 | | - e->fields.dest_mode)) |
---|
| 118 | + if (!kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT, |
---|
| 119 | + e->fields.dest_id, |
---|
| 120 | + kvm_lapic_irq_dest_mode(!!e->fields.dest_mode))) |
---|
120 | 121 | return; |
---|
121 | 122 | |
---|
122 | 123 | new_val = kvm_apic_pending_eoi(vcpu, e->fields.vector); |
---|
.. | .. |
---|
158 | 159 | __rtc_irq_eoi_tracking_restore_one(vcpu); |
---|
159 | 160 | } |
---|
160 | 161 | |
---|
161 | | -static void rtc_irq_eoi(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu) |
---|
| 162 | +static void rtc_irq_eoi(struct kvm_ioapic *ioapic, struct kvm_vcpu *vcpu, |
---|
| 163 | + int vector) |
---|
162 | 164 | { |
---|
163 | | - if (test_and_clear_bit(vcpu->vcpu_id, |
---|
164 | | - ioapic->rtc_status.dest_map.map)) { |
---|
| 165 | + struct dest_map *dest_map = &ioapic->rtc_status.dest_map; |
---|
| 166 | + |
---|
| 167 | + /* RTC special handling */ |
---|
| 168 | + if (test_bit(vcpu->vcpu_id, dest_map->map) && |
---|
| 169 | + (vector == dest_map->vectors[vcpu->vcpu_id]) && |
---|
| 170 | + (test_and_clear_bit(vcpu->vcpu_id, |
---|
| 171 | + ioapic->rtc_status.dest_map.map))) { |
---|
165 | 172 | --ioapic->rtc_status.pending_eoi; |
---|
166 | 173 | rtc_status_pending_eoi_check_valid(ioapic); |
---|
167 | 174 | } |
---|
.. | .. |
---|
173 | 180 | return true; /* coalesced */ |
---|
174 | 181 | |
---|
175 | 182 | return false; |
---|
| 183 | +} |
---|
| 184 | + |
---|
| 185 | +static void ioapic_lazy_update_eoi(struct kvm_ioapic *ioapic, int irq) |
---|
| 186 | +{ |
---|
| 187 | + int i; |
---|
| 188 | + struct kvm_vcpu *vcpu; |
---|
| 189 | + union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq]; |
---|
| 190 | + |
---|
| 191 | + kvm_for_each_vcpu(i, vcpu, ioapic->kvm) { |
---|
| 192 | + if (!kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT, |
---|
| 193 | + entry->fields.dest_id, |
---|
| 194 | + entry->fields.dest_mode) || |
---|
| 195 | + kvm_apic_pending_eoi(vcpu, entry->fields.vector)) |
---|
| 196 | + continue; |
---|
| 197 | + |
---|
| 198 | + /* |
---|
| 199 | + * If no longer has pending EOI in LAPICs, update |
---|
| 200 | + * EOI for this vector. |
---|
| 201 | + */ |
---|
| 202 | + rtc_irq_eoi(ioapic, vcpu, entry->fields.vector); |
---|
| 203 | + break; |
---|
| 204 | + } |
---|
176 | 205 | } |
---|
177 | 206 | |
---|
178 | 207 | static int ioapic_set_irq(struct kvm_ioapic *ioapic, unsigned int irq, |
---|
.. | .. |
---|
193 | 222 | } |
---|
194 | 223 | |
---|
195 | 224 | /* |
---|
| 225 | + * AMD SVM AVIC accelerate EOI write iff the interrupt is edge |
---|
| 226 | + * triggered, in which case the in-kernel IOAPIC will not be able |
---|
| 227 | + * to receive the EOI. In this case, we do a lazy update of the |
---|
| 228 | + * pending EOI when trying to set IOAPIC irq. |
---|
| 229 | + */ |
---|
| 230 | + if (edge && kvm_apicv_activated(ioapic->kvm)) |
---|
| 231 | + ioapic_lazy_update_eoi(ioapic, irq); |
---|
| 232 | + |
---|
| 233 | + /* |
---|
196 | 234 | * Return 0 for coalesced interrupts; for edge-triggered interrupts, |
---|
197 | 235 | * this only happens if a previous edge has not been delivered due |
---|
198 | | - * do masking. For level interrupts, the remote_irr field tells |
---|
| 236 | + * to masking. For level interrupts, the remote_irr field tells |
---|
199 | 237 | * us if the interrupt is waiting for an EOI. |
---|
200 | 238 | * |
---|
201 | 239 | * RTC is special: it is edge-triggered, but userspace likes to know |
---|
.. | .. |
---|
257 | 295 | if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG || |
---|
258 | 296 | kvm_irq_has_notifier(ioapic->kvm, KVM_IRQCHIP_IOAPIC, index) || |
---|
259 | 297 | index == RTC_GSI) { |
---|
260 | | - if (kvm_apic_match_dest(vcpu, NULL, 0, |
---|
261 | | - e->fields.dest_id, e->fields.dest_mode) || |
---|
| 298 | + u16 dm = kvm_lapic_irq_dest_mode(!!e->fields.dest_mode); |
---|
| 299 | + |
---|
| 300 | + if (kvm_apic_match_dest(vcpu, NULL, APIC_DEST_NOSHORT, |
---|
| 301 | + e->fields.dest_id, dm) || |
---|
262 | 302 | kvm_apic_pending_eoi(vcpu, e->fields.vector)) |
---|
263 | 303 | __set_bit(e->fields.vector, |
---|
264 | 304 | ioapic_handled_vectors); |
---|
.. | .. |
---|
278 | 318 | { |
---|
279 | 319 | unsigned index; |
---|
280 | 320 | bool mask_before, mask_after; |
---|
281 | | - int old_remote_irr, old_delivery_status; |
---|
282 | 321 | union kvm_ioapic_redirect_entry *e; |
---|
| 322 | + int old_remote_irr, old_delivery_status, old_dest_id, old_dest_mode; |
---|
| 323 | + DECLARE_BITMAP(vcpu_bitmap, KVM_MAX_VCPUS); |
---|
283 | 324 | |
---|
284 | 325 | switch (ioapic->ioregsel) { |
---|
285 | 326 | case IOAPIC_REG_VERSION: |
---|
.. | .. |
---|
296 | 337 | default: |
---|
297 | 338 | index = (ioapic->ioregsel - 0x10) >> 1; |
---|
298 | 339 | |
---|
299 | | - ioapic_debug("change redir index %x val %x\n", index, val); |
---|
300 | 340 | if (index >= IOAPIC_NUM_PINS) |
---|
301 | 341 | return; |
---|
302 | 342 | index = array_index_nospec(index, IOAPIC_NUM_PINS); |
---|
.. | .. |
---|
305 | 345 | /* Preserve read-only fields */ |
---|
306 | 346 | old_remote_irr = e->fields.remote_irr; |
---|
307 | 347 | old_delivery_status = e->fields.delivery_status; |
---|
| 348 | + old_dest_id = e->fields.dest_id; |
---|
| 349 | + old_dest_mode = e->fields.dest_mode; |
---|
308 | 350 | if (ioapic->ioregsel & 1) { |
---|
309 | 351 | e->bits &= 0xffffffff; |
---|
310 | 352 | e->bits |= (u64) val << 32; |
---|
.. | .. |
---|
330 | 372 | if (e->fields.trig_mode == IOAPIC_LEVEL_TRIG |
---|
331 | 373 | && ioapic->irr & (1 << index)) |
---|
332 | 374 | ioapic_service(ioapic, index, false); |
---|
333 | | - kvm_make_scan_ioapic_request(ioapic->kvm); |
---|
| 375 | + if (e->fields.delivery_mode == APIC_DM_FIXED) { |
---|
| 376 | + struct kvm_lapic_irq irq; |
---|
| 377 | + |
---|
| 378 | + irq.vector = e->fields.vector; |
---|
| 379 | + irq.delivery_mode = e->fields.delivery_mode << 8; |
---|
| 380 | + irq.dest_mode = |
---|
| 381 | + kvm_lapic_irq_dest_mode(!!e->fields.dest_mode); |
---|
| 382 | + irq.level = false; |
---|
| 383 | + irq.trig_mode = e->fields.trig_mode; |
---|
| 384 | + irq.shorthand = APIC_DEST_NOSHORT; |
---|
| 385 | + irq.dest_id = e->fields.dest_id; |
---|
| 386 | + irq.msi_redir_hint = false; |
---|
| 387 | + bitmap_zero(vcpu_bitmap, KVM_MAX_VCPUS); |
---|
| 388 | + kvm_bitmap_or_dest_vcpus(ioapic->kvm, &irq, |
---|
| 389 | + vcpu_bitmap); |
---|
| 390 | + if (old_dest_mode != e->fields.dest_mode || |
---|
| 391 | + old_dest_id != e->fields.dest_id) { |
---|
| 392 | + /* |
---|
| 393 | + * Update vcpu_bitmap with vcpus specified in |
---|
| 394 | + * the previous request as well. This is done to |
---|
| 395 | + * keep ioapic_handled_vectors synchronized. |
---|
| 396 | + */ |
---|
| 397 | + irq.dest_id = old_dest_id; |
---|
| 398 | + irq.dest_mode = |
---|
| 399 | + kvm_lapic_irq_dest_mode( |
---|
| 400 | + !!e->fields.dest_mode); |
---|
| 401 | + kvm_bitmap_or_dest_vcpus(ioapic->kvm, &irq, |
---|
| 402 | + vcpu_bitmap); |
---|
| 403 | + } |
---|
| 404 | + kvm_make_scan_ioapic_request_mask(ioapic->kvm, |
---|
| 405 | + vcpu_bitmap); |
---|
| 406 | + } else { |
---|
| 407 | + kvm_make_scan_ioapic_request(ioapic->kvm); |
---|
| 408 | + } |
---|
334 | 409 | break; |
---|
335 | 410 | } |
---|
336 | 411 | } |
---|
.. | .. |
---|
346 | 421 | entry->fields.remote_irr)) |
---|
347 | 422 | return -1; |
---|
348 | 423 | |
---|
349 | | - ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " |
---|
350 | | - "vector=%x trig_mode=%x\n", |
---|
351 | | - entry->fields.dest_id, entry->fields.dest_mode, |
---|
352 | | - entry->fields.delivery_mode, entry->fields.vector, |
---|
353 | | - entry->fields.trig_mode); |
---|
354 | | - |
---|
355 | 424 | irqe.dest_id = entry->fields.dest_id; |
---|
356 | 425 | irqe.vector = entry->fields.vector; |
---|
357 | | - irqe.dest_mode = entry->fields.dest_mode; |
---|
| 426 | + irqe.dest_mode = kvm_lapic_irq_dest_mode(!!entry->fields.dest_mode); |
---|
358 | 427 | irqe.trig_mode = entry->fields.trig_mode; |
---|
359 | 428 | irqe.delivery_mode = entry->fields.delivery_mode << 8; |
---|
360 | 429 | irqe.level = 1; |
---|
361 | | - irqe.shorthand = 0; |
---|
| 430 | + irqe.shorthand = APIC_DEST_NOSHORT; |
---|
362 | 431 | irqe.msi_redir_hint = false; |
---|
363 | 432 | |
---|
364 | 433 | if (irqe.trig_mode == IOAPIC_EDGE_TRIG) |
---|
.. | .. |
---|
430 | 499 | } |
---|
431 | 500 | |
---|
432 | 501 | #define IOAPIC_SUCCESSIVE_IRQ_MAX_COUNT 10000 |
---|
433 | | - |
---|
434 | | -static void __kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, |
---|
435 | | - struct kvm_ioapic *ioapic, int vector, int trigger_mode) |
---|
| 502 | +static void kvm_ioapic_update_eoi_one(struct kvm_vcpu *vcpu, |
---|
| 503 | + struct kvm_ioapic *ioapic, |
---|
| 504 | + int trigger_mode, |
---|
| 505 | + int pin) |
---|
436 | 506 | { |
---|
437 | | - struct dest_map *dest_map = &ioapic->rtc_status.dest_map; |
---|
438 | 507 | struct kvm_lapic *apic = vcpu->arch.apic; |
---|
439 | | - int i; |
---|
| 508 | + union kvm_ioapic_redirect_entry *ent = &ioapic->redirtbl[pin]; |
---|
440 | 509 | |
---|
441 | | - /* RTC special handling */ |
---|
442 | | - if (test_bit(vcpu->vcpu_id, dest_map->map) && |
---|
443 | | - vector == dest_map->vectors[vcpu->vcpu_id]) |
---|
444 | | - rtc_irq_eoi(ioapic, vcpu); |
---|
| 510 | + /* |
---|
| 511 | + * We are dropping lock while calling ack notifiers because ack |
---|
| 512 | + * notifier callbacks for assigned devices call into IOAPIC |
---|
| 513 | + * recursively. Since remote_irr is cleared only after call |
---|
| 514 | + * to notifiers if the same vector will be delivered while lock |
---|
| 515 | + * is dropped it will be put into irr and will be delivered |
---|
| 516 | + * after ack notifier returns. |
---|
| 517 | + */ |
---|
| 518 | + spin_unlock(&ioapic->lock); |
---|
| 519 | + kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, pin); |
---|
| 520 | + spin_lock(&ioapic->lock); |
---|
445 | 521 | |
---|
446 | | - for (i = 0; i < IOAPIC_NUM_PINS; i++) { |
---|
447 | | - union kvm_ioapic_redirect_entry *ent = &ioapic->redirtbl[i]; |
---|
| 522 | + if (trigger_mode != IOAPIC_LEVEL_TRIG || |
---|
| 523 | + kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI) |
---|
| 524 | + return; |
---|
448 | 525 | |
---|
449 | | - if (ent->fields.vector != vector) |
---|
450 | | - continue; |
---|
451 | | - |
---|
452 | | - /* |
---|
453 | | - * We are dropping lock while calling ack notifiers because ack |
---|
454 | | - * notifier callbacks for assigned devices call into IOAPIC |
---|
455 | | - * recursively. Since remote_irr is cleared only after call |
---|
456 | | - * to notifiers if the same vector will be delivered while lock |
---|
457 | | - * is dropped it will be put into irr and will be delivered |
---|
458 | | - * after ack notifier returns. |
---|
459 | | - */ |
---|
460 | | - spin_unlock(&ioapic->lock); |
---|
461 | | - kvm_notify_acked_irq(ioapic->kvm, KVM_IRQCHIP_IOAPIC, i); |
---|
462 | | - spin_lock(&ioapic->lock); |
---|
463 | | - |
---|
464 | | - if (trigger_mode != IOAPIC_LEVEL_TRIG || |
---|
465 | | - kvm_lapic_get_reg(apic, APIC_SPIV) & APIC_SPIV_DIRECTED_EOI) |
---|
466 | | - continue; |
---|
467 | | - |
---|
468 | | - ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG); |
---|
469 | | - ent->fields.remote_irr = 0; |
---|
470 | | - if (!ent->fields.mask && (ioapic->irr & (1 << i))) { |
---|
471 | | - ++ioapic->irq_eoi[i]; |
---|
472 | | - if (ioapic->irq_eoi[i] == IOAPIC_SUCCESSIVE_IRQ_MAX_COUNT) { |
---|
473 | | - /* |
---|
474 | | - * Real hardware does not deliver the interrupt |
---|
475 | | - * immediately during eoi broadcast, and this |
---|
476 | | - * lets a buggy guest make slow progress |
---|
477 | | - * even if it does not correctly handle a |
---|
478 | | - * level-triggered interrupt. Emulate this |
---|
479 | | - * behavior if we detect an interrupt storm. |
---|
480 | | - */ |
---|
481 | | - schedule_delayed_work(&ioapic->eoi_inject, HZ / 100); |
---|
482 | | - ioapic->irq_eoi[i] = 0; |
---|
483 | | - trace_kvm_ioapic_delayed_eoi_inj(ent->bits); |
---|
484 | | - } else { |
---|
485 | | - ioapic_service(ioapic, i, false); |
---|
486 | | - } |
---|
| 526 | + ASSERT(ent->fields.trig_mode == IOAPIC_LEVEL_TRIG); |
---|
| 527 | + ent->fields.remote_irr = 0; |
---|
| 528 | + if (!ent->fields.mask && (ioapic->irr & (1 << pin))) { |
---|
| 529 | + ++ioapic->irq_eoi[pin]; |
---|
| 530 | + if (ioapic->irq_eoi[pin] == IOAPIC_SUCCESSIVE_IRQ_MAX_COUNT) { |
---|
| 531 | + /* |
---|
| 532 | + * Real hardware does not deliver the interrupt |
---|
| 533 | + * immediately during eoi broadcast, and this |
---|
| 534 | + * lets a buggy guest make slow progress |
---|
| 535 | + * even if it does not correctly handle a |
---|
| 536 | + * level-triggered interrupt. Emulate this |
---|
| 537 | + * behavior if we detect an interrupt storm. |
---|
| 538 | + */ |
---|
| 539 | + schedule_delayed_work(&ioapic->eoi_inject, HZ / 100); |
---|
| 540 | + ioapic->irq_eoi[pin] = 0; |
---|
| 541 | + trace_kvm_ioapic_delayed_eoi_inj(ent->bits); |
---|
487 | 542 | } else { |
---|
488 | | - ioapic->irq_eoi[i] = 0; |
---|
| 543 | + ioapic_service(ioapic, pin, false); |
---|
489 | 544 | } |
---|
| 545 | + } else { |
---|
| 546 | + ioapic->irq_eoi[pin] = 0; |
---|
490 | 547 | } |
---|
491 | 548 | } |
---|
492 | 549 | |
---|
493 | 550 | void kvm_ioapic_update_eoi(struct kvm_vcpu *vcpu, int vector, int trigger_mode) |
---|
494 | 551 | { |
---|
| 552 | + int i; |
---|
495 | 553 | struct kvm_ioapic *ioapic = vcpu->kvm->arch.vioapic; |
---|
496 | 554 | |
---|
497 | 555 | spin_lock(&ioapic->lock); |
---|
498 | | - __kvm_ioapic_update_eoi(vcpu, ioapic, vector, trigger_mode); |
---|
| 556 | + rtc_irq_eoi(ioapic, vcpu, vector); |
---|
| 557 | + for (i = 0; i < IOAPIC_NUM_PINS; i++) { |
---|
| 558 | + union kvm_ioapic_redirect_entry *ent = &ioapic->redirtbl[i]; |
---|
| 559 | + |
---|
| 560 | + if (ent->fields.vector != vector) |
---|
| 561 | + continue; |
---|
| 562 | + kvm_ioapic_update_eoi_one(vcpu, ioapic, trigger_mode, i); |
---|
| 563 | + } |
---|
499 | 564 | spin_unlock(&ioapic->lock); |
---|
500 | 565 | } |
---|
501 | 566 | |
---|
.. | .. |
---|
518 | 583 | if (!ioapic_in_range(ioapic, addr)) |
---|
519 | 584 | return -EOPNOTSUPP; |
---|
520 | 585 | |
---|
521 | | - ioapic_debug("addr %lx\n", (unsigned long)addr); |
---|
522 | 586 | ASSERT(!(addr & 0xf)); /* check alignment */ |
---|
523 | 587 | |
---|
524 | 588 | addr &= 0xff; |
---|
.. | .. |
---|
561 | 625 | if (!ioapic_in_range(ioapic, addr)) |
---|
562 | 626 | return -EOPNOTSUPP; |
---|
563 | 627 | |
---|
564 | | - ioapic_debug("ioapic_mmio_write addr=%p len=%d val=%p\n", |
---|
565 | | - (void*)addr, len, val); |
---|
566 | 628 | ASSERT(!(addr & 0xf)); /* check alignment */ |
---|
567 | 629 | |
---|
568 | 630 | switch (len) { |
---|
.. | .. |
---|
625 | 687 | struct kvm_ioapic *ioapic; |
---|
626 | 688 | int ret; |
---|
627 | 689 | |
---|
628 | | - ioapic = kzalloc(sizeof(struct kvm_ioapic), GFP_KERNEL); |
---|
| 690 | + ioapic = kzalloc(sizeof(struct kvm_ioapic), GFP_KERNEL_ACCOUNT); |
---|
629 | 691 | if (!ioapic) |
---|
630 | 692 | return -ENOMEM; |
---|
631 | 693 | spin_lock_init(&ioapic->lock); |
---|