| .. | .. |
|---|
| 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); |
|---|