diff options
Diffstat (limited to 'virt/kvm/irq_comm.c')
-rw-r--r-- | virt/kvm/irq_comm.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index d165e056f79b..1c6ff6d1b842 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c | |||
@@ -47,15 +47,54 @@ void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic, | |||
47 | union kvm_ioapic_redirect_entry *entry, | 47 | union kvm_ioapic_redirect_entry *entry, |
48 | unsigned long *deliver_bitmask) | 48 | unsigned long *deliver_bitmask) |
49 | { | 49 | { |
50 | int i; | ||
51 | struct kvm *kvm = ioapic->kvm; | ||
50 | struct kvm_vcpu *vcpu; | 52 | struct kvm_vcpu *vcpu; |
51 | 53 | ||
52 | kvm_ioapic_get_delivery_bitmask(ioapic, entry->fields.dest_id, | 54 | bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); |
53 | entry->fields.dest_mode, | 55 | |
54 | deliver_bitmask); | 56 | if (entry->fields.dest_mode == 0) { /* Physical mode. */ |
57 | if (entry->fields.dest_id == 0xFF) { /* Broadcast. */ | ||
58 | for (i = 0; i < KVM_MAX_VCPUS; ++i) | ||
59 | if (kvm->vcpus[i] && kvm->vcpus[i]->arch.apic) | ||
60 | __set_bit(i, deliver_bitmask); | ||
61 | /* Lowest priority shouldn't combine with broadcast */ | ||
62 | if (entry->fields.delivery_mode == | ||
63 | IOAPIC_LOWEST_PRIORITY && printk_ratelimit()) | ||
64 | printk(KERN_INFO "kvm: apic: phys broadcast " | ||
65 | "and lowest prio\n"); | ||
66 | return; | ||
67 | } | ||
68 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
69 | vcpu = kvm->vcpus[i]; | ||
70 | if (!vcpu) | ||
71 | continue; | ||
72 | if (kvm_apic_match_physical_addr(vcpu->arch.apic, | ||
73 | entry->fields.dest_id)) { | ||
74 | if (vcpu->arch.apic) | ||
75 | __set_bit(i, deliver_bitmask); | ||
76 | break; | ||
77 | } | ||
78 | } | ||
79 | } else if (entry->fields.dest_id != 0) /* Logical mode, MDA non-zero. */ | ||
80 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
81 | vcpu = kvm->vcpus[i]; | ||
82 | if (!vcpu) | ||
83 | continue; | ||
84 | if (vcpu->arch.apic && | ||
85 | kvm_apic_match_logical_addr(vcpu->arch.apic, | ||
86 | entry->fields.dest_id)) | ||
87 | __set_bit(i, deliver_bitmask); | ||
88 | } | ||
89 | |||
55 | switch (entry->fields.delivery_mode) { | 90 | switch (entry->fields.delivery_mode) { |
56 | case IOAPIC_LOWEST_PRIORITY: | 91 | case IOAPIC_LOWEST_PRIORITY: |
92 | /* Select one in deliver_bitmask */ | ||
57 | vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, | 93 | vcpu = kvm_get_lowest_prio_vcpu(ioapic->kvm, |
58 | entry->fields.vector, deliver_bitmask); | 94 | entry->fields.vector, deliver_bitmask); |
95 | bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); | ||
96 | if (!vcpu) | ||
97 | return; | ||
59 | __set_bit(vcpu->vcpu_id, deliver_bitmask); | 98 | __set_bit(vcpu->vcpu_id, deliver_bitmask); |
60 | break; | 99 | break; |
61 | case IOAPIC_FIXED: | 100 | case IOAPIC_FIXED: |
@@ -65,7 +104,7 @@ void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic, | |||
65 | if (printk_ratelimit()) | 104 | if (printk_ratelimit()) |
66 | printk(KERN_INFO "kvm: unsupported delivery mode %d\n", | 105 | printk(KERN_INFO "kvm: unsupported delivery mode %d\n", |
67 | entry->fields.delivery_mode); | 106 | entry->fields.delivery_mode); |
68 | *deliver_bitmask = 0; | 107 | bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); |
69 | } | 108 | } |
70 | } | 109 | } |
71 | 110 | ||
@@ -80,8 +119,6 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | |||
80 | 119 | ||
81 | BUG_ON(!ioapic); | 120 | BUG_ON(!ioapic); |
82 | 121 | ||
83 | bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); | ||
84 | |||
85 | entry.bits = 0; | 122 | entry.bits = 0; |
86 | entry.fields.dest_id = (e->msi.address_lo & | 123 | entry.fields.dest_id = (e->msi.address_lo & |
87 | MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; | 124 | MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; |