| @@ -616,17 +616,30 @@ static bool kvm_apic_match_logical_addr(struct kvm_lapic *apic, u32 mda) · 615 unmodified lines |
| 616 | } | 616 | } |
| 617 | } | 617 | } |
| 618 | | 618 | |
| 619 | /* KVM APIC implementation has two quirks | 619 | /* The KVM local APIC implementation has two quirks: |
| 620 | * - dest always begins at 0 while xAPIC MDA has offset 24, | 620 | * |
| 621 | * - IOxAPIC messages have to be delivered (directly) to x2APIC. | 621 | * - the xAPIC MDA stores the destination at bits 24-31, while this |
| | 622 | * is not true of struct kvm_lapic_irq's dest_id field. This is |
| | 623 | * just a quirk in the API and is not problematic. |
| | 624 | * |
| | 625 | * - in-kernel IOAPIC messages have to be delivered directly to |
| | 626 | * x2APIC, because the kernel does not support interrupt remapping. |
| | 627 | * In order to support broadcast without interrupt remapping, x2APIC |
| | 628 | * rewrites the destination of non-IPI messages from APIC_BROADCAST |
| | 629 | * to X2APIC_BROADCAST. |
| | 630 | * |
| | 631 | * The broadcast quirk can be disabled with KVM_CAP_X2APIC_API. This is |
| | 632 | * important when userspace wants to use x2APIC-format MSIs, because |
| | 633 | * APIC_BROADCAST (0xff) is a legal route for "cluster 0, CPUs 0-7". |
| 622 | */ | 634 | */ |
| 623 | static u32 kvm_apic_mda(unsigned int dest_id, struct kvm_lapic *source, | 635 | static u32 kvm_apic_mda(struct kvm_vcpu *vcpu, unsigned int dest_id, |
| 624 | struct kvm_lapic *target) | 636 | struct kvm_lapic *source, struct kvm_lapic *target) |
| 625 | { | 637 | { |
| 626 | bool ipi = source != NULL; | 638 | bool ipi = source != NULL; |
| 627 | bool x2apic_mda = apic_x2apic_mode(ipi ? source : target); | 639 | bool x2apic_mda = apic_x2apic_mode(ipi ? source : target); |
| 628 | | 640 | |
| 629 | if (!ipi && dest_id == APIC_BROADCAST && x2apic_mda) | 641 | if (!vcpu->kvm->arch.x2apic_broadcast_quirk_disabled && |
| | 642 | !ipi && dest_id == APIC_BROADCAST && x2apic_mda) |
| 630 | return X2APIC_BROADCAST; | 643 | return X2APIC_BROADCAST; |
| 631 | | 644 | |
| 632 | return x2apic_mda ? dest_id : SET_APIC_DEST_FIELD(dest_id); | 645 | return x2apic_mda ? dest_id : SET_APIC_DEST_FIELD(dest_id); |
| @@ -636,7 +649,7 @@ bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, · 3 unmodified lines |
| 636 | int short_hand, unsigned int dest, int dest_mode) | 649 | int short_hand, unsigned int dest, int dest_mode) |
| 637 | { | 650 | { |
| 638 | struct kvm_lapic *target = vcpu->arch.apic; | 651 | struct kvm_lapic *target = vcpu->arch.apic; |
| 639 | u32 mda = kvm_apic_mda(dest, source, target); | 652 | u32 mda = kvm_apic_mda(vcpu, dest, source, target); |
| 640 | | 653 | |
| 641 | apic_debug("target %p, source %p, dest 0x%x, " | 654 | apic_debug("target %p, source %p, dest 0x%x, " |
| 642 | "dest_mode 0x%x, short_hand 0x%x\n", | 655 | "dest_mode 0x%x, short_hand 0x%x\n", |
| @@ -688,6 +701,25 @@ static void kvm_apic_disabled_lapic_found(struct kvm *kvm) · 45 unmodified lines |
| 688 | } | 701 | } |
| 689 | } | 702 | } |
| 690 | | 703 | |
| | 704 | static bool kvm_apic_is_broadcast_dest(struct kvm *kvm, struct kvm_lapic **src, |
| | 705 | struct kvm_lapic_irq *irq, struct kvm_apic_map *map) |
| | 706 | { |
| | 707 | if (kvm->arch.x2apic_broadcast_quirk_disabled) { |
| | 708 | if ((irq->dest_id == APIC_BROADCAST && |
| | 709 | map->mode != KVM_APIC_MODE_X2APIC)) |
| | 710 | return true; |
| | 711 | if (irq->dest_id == X2APIC_BROADCAST) |
| | 712 | return true; |
| | 713 | } else { |
| | 714 | bool x2apic_ipi = src && *src && apic_x2apic_mode(*src); |
| | 715 | if (irq->dest_id == (x2apic_ipi ? |
| | 716 | X2APIC_BROADCAST : APIC_BROADCAST)) |
| | 717 | return true; |
| | 718 | } |
| | 719 | |
| | 720 | return false; |
| | 721 | } |
| | 722 | |
| 691 | /* Return true if the interrupt can be handled by using *bitmap as index mask | 723 | /* Return true if the interrupt can be handled by using *bitmap as index mask |
| 692 | * for valid destinations in *dst array. | 724 | * for valid destinations in *dst array. |
| 693 | * Return false if kvm_apic_map_get_dest_lapic did nothing useful. | 725 | * Return false if kvm_apic_map_get_dest_lapic did nothing useful. |
| @@ -701,7 +733,6 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm, · 7 unmodified lines |
| 701 | unsigned long *bitmap) | 733 | unsigned long *bitmap) |
| 702 | { | 734 | { |
| 703 | int i, lowest; | 735 | int i, lowest; |
| 704 | bool x2apic_ipi; | | |
| 705 | | 736 | |
| 706 | if (irq->shorthand == APIC_DEST_SELF && src) { | 737 | if (irq->shorthand == APIC_DEST_SELF && src) { |
| 707 | *dst = src; | 738 | *dst = src; |
| @@ -710,11 +741,7 @@ static inline bool kvm_apic_map_get_dest_lapic(struct kvm *kvm, · 2 unmodified lines |
| 710 | } else if (irq->shorthand) | 741 | } else if (irq->shorthand) |
| 711 | return false; | 742 | return false; |
| 712 | | 743 | |
| 713 | x2apic_ipi = src && *src && apic_x2apic_mode(*src); | 744 | if (!map || kvm_apic_is_broadcast_dest(kvm, src, irq, map)) |
| 714 | if (irq->dest_id == (x2apic_ipi ? X2APIC_BROADCAST : APIC_BROADCAST)) | | |
| 715 | return false; | | |
| 716 | | | |
| 717 | if (!map) | | |
| 718 | return false; | 745 | return false; |
| 719 | | 746 | |
| 720 | if (irq->dest_mode == APIC_DEST_PHYSICAL) { | 747 | if (irq->dest_mode == APIC_DEST_PHYSICAL) { |