diff options
-rw-r--r-- | virt/kvm/ioapic.c | 46 | ||||
-rw-r--r-- | virt/kvm/ioapic.h | 5 | ||||
-rw-r--r-- | virt/kvm/irq_comm.c | 49 |
3 files changed, 49 insertions, 51 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 7c2cb2bd1199..ea268a8c37da 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -161,45 +161,6 @@ static void ioapic_inj_nmi(struct kvm_vcpu *vcpu) | |||
161 | kvm_vcpu_kick(vcpu); | 161 | kvm_vcpu_kick(vcpu); |
162 | } | 162 | } |
163 | 163 | ||
164 | void kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest, | ||
165 | u8 dest_mode, unsigned long *mask) | ||
166 | { | ||
167 | int i; | ||
168 | struct kvm *kvm = ioapic->kvm; | ||
169 | struct kvm_vcpu *vcpu; | ||
170 | |||
171 | ioapic_debug("dest %d dest_mode %d\n", dest, dest_mode); | ||
172 | |||
173 | *mask = 0; | ||
174 | if (dest_mode == 0) { /* Physical mode. */ | ||
175 | if (dest == 0xFF) { /* Broadcast. */ | ||
176 | for (i = 0; i < KVM_MAX_VCPUS; ++i) | ||
177 | if (kvm->vcpus[i] && kvm->vcpus[i]->arch.apic) | ||
178 | *mask |= 1 << i; | ||
179 | return; | ||
180 | } | ||
181 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
182 | vcpu = kvm->vcpus[i]; | ||
183 | if (!vcpu) | ||
184 | continue; | ||
185 | if (kvm_apic_match_physical_addr(vcpu->arch.apic, dest)) { | ||
186 | if (vcpu->arch.apic) | ||
187 | *mask = 1 << i; | ||
188 | break; | ||
189 | } | ||
190 | } | ||
191 | } else if (dest != 0) /* Logical mode, MDA non-zero. */ | ||
192 | for (i = 0; i < KVM_MAX_VCPUS; ++i) { | ||
193 | vcpu = kvm->vcpus[i]; | ||
194 | if (!vcpu) | ||
195 | continue; | ||
196 | if (vcpu->arch.apic && | ||
197 | kvm_apic_match_logical_addr(vcpu->arch.apic, dest)) | ||
198 | *mask |= 1 << vcpu->vcpu_id; | ||
199 | } | ||
200 | ioapic_debug("mask %x\n", *mask); | ||
201 | } | ||
202 | |||
203 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | 164 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) |
204 | { | 165 | { |
205 | union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq]; | 166 | union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq]; |
@@ -213,13 +174,12 @@ static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | |||
213 | entry.fields.delivery_mode, entry.fields.vector, | 174 | entry.fields.delivery_mode, entry.fields.vector, |
214 | entry.fields.trig_mode); | 175 | entry.fields.trig_mode); |
215 | 176 | ||
216 | bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); | ||
217 | |||
218 | /* Always delivery PIT interrupt to vcpu 0 */ | 177 | /* Always delivery PIT interrupt to vcpu 0 */ |
219 | #ifdef CONFIG_X86 | 178 | #ifdef CONFIG_X86 |
220 | if (irq == 0) | 179 | if (irq == 0) { |
180 | bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); | ||
221 | __set_bit(0, deliver_bitmask); | 181 | __set_bit(0, deliver_bitmask); |
222 | else | 182 | } else |
223 | #endif | 183 | #endif |
224 | kvm_get_intr_delivery_bitmask(ioapic, &entry, deliver_bitmask); | 184 | kvm_get_intr_delivery_bitmask(ioapic, &entry, deliver_bitmask); |
225 | 185 | ||
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h index 7275f87a11cd..c8032ab2a4e2 100644 --- a/virt/kvm/ioapic.h +++ b/virt/kvm/ioapic.h | |||
@@ -70,7 +70,8 @@ void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); | |||
70 | int kvm_ioapic_init(struct kvm *kvm); | 70 | int kvm_ioapic_init(struct kvm *kvm); |
71 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); | 71 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); |
72 | void kvm_ioapic_reset(struct kvm_ioapic *ioapic); | 72 | void kvm_ioapic_reset(struct kvm_ioapic *ioapic); |
73 | void kvm_ioapic_get_delivery_bitmask(struct kvm_ioapic *ioapic, u8 dest, | 73 | void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic, |
74 | u8 dest_mode, unsigned long *mask); | 74 | union kvm_ioapic_redirect_entry *entry, |
75 | unsigned long *deliver_bitmask); | ||
75 | 76 | ||
76 | #endif | 77 | #endif |
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; |