diff options
Diffstat (limited to 'virt/kvm/ioapic.c')
-rw-r--r-- | virt/kvm/ioapic.c | 57 |
1 files changed, 16 insertions, 41 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index 43969bbf127f..1eddae94bab3 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c | |||
@@ -142,58 +142,33 @@ static void ioapic_write_indirect(struct kvm_ioapic *ioapic, u32 val) | |||
142 | } | 142 | } |
143 | } | 143 | } |
144 | 144 | ||
145 | int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e) | ||
146 | { | ||
147 | DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS); | ||
148 | int i, r = -1; | ||
149 | |||
150 | kvm_get_intr_delivery_bitmask(kvm, NULL, e->fields.dest_id, | ||
151 | e->fields.dest_mode, | ||
152 | e->fields.delivery_mode == IOAPIC_LOWEST_PRIORITY, | ||
153 | 0, deliver_bitmask); | ||
154 | |||
155 | if (find_first_bit(deliver_bitmask, KVM_MAX_VCPUS) >= KVM_MAX_VCPUS) { | ||
156 | ioapic_debug("no target on destination\n"); | ||
157 | return r; | ||
158 | } | ||
159 | |||
160 | while ((i = find_first_bit(deliver_bitmask, KVM_MAX_VCPUS)) | ||
161 | < KVM_MAX_VCPUS) { | ||
162 | struct kvm_vcpu *vcpu = kvm->vcpus[i]; | ||
163 | __clear_bit(i, deliver_bitmask); | ||
164 | if (vcpu) { | ||
165 | if (r < 0) | ||
166 | r = 0; | ||
167 | r += kvm_apic_set_irq(vcpu, e->fields.vector, | ||
168 | e->fields.delivery_mode, | ||
169 | e->fields.trig_mode); | ||
170 | } else | ||
171 | ioapic_debug("null destination vcpu: " | ||
172 | "mask=%x vector=%x delivery_mode=%x\n", | ||
173 | e->fields.deliver_bitmask, | ||
174 | e->fields.vector, e->fields.delivery_mode); | ||
175 | } | ||
176 | return r; | ||
177 | } | ||
178 | |||
179 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) | 145 | static int ioapic_deliver(struct kvm_ioapic *ioapic, int irq) |
180 | { | 146 | { |
181 | union kvm_ioapic_redirect_entry entry = ioapic->redirtbl[irq]; | 147 | union kvm_ioapic_redirect_entry *entry = &ioapic->redirtbl[irq]; |
148 | struct kvm_lapic_irq irqe; | ||
182 | 149 | ||
183 | ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " | 150 | ioapic_debug("dest=%x dest_mode=%x delivery_mode=%x " |
184 | "vector=%x trig_mode=%x\n", | 151 | "vector=%x trig_mode=%x\n", |
185 | entry.fields.dest, entry.fields.dest_mode, | 152 | entry->fields.dest, entry->fields.dest_mode, |
186 | entry.fields.delivery_mode, entry.fields.vector, | 153 | entry->fields.delivery_mode, entry->fields.vector, |
187 | entry.fields.trig_mode); | 154 | entry->fields.trig_mode); |
155 | |||
156 | irqe.dest_id = entry->fields.dest_id; | ||
157 | irqe.vector = entry->fields.vector; | ||
158 | irqe.dest_mode = entry->fields.dest_mode; | ||
159 | irqe.trig_mode = entry->fields.trig_mode; | ||
160 | irqe.delivery_mode = entry->fields.delivery_mode << 8; | ||
161 | irqe.level = 1; | ||
162 | irqe.shorthand = 0; | ||
188 | 163 | ||
189 | #ifdef CONFIG_X86 | 164 | #ifdef CONFIG_X86 |
190 | /* Always delivery PIT interrupt to vcpu 0 */ | 165 | /* Always delivery PIT interrupt to vcpu 0 */ |
191 | if (irq == 0) { | 166 | if (irq == 0) { |
192 | entry.fields.dest_mode = 0; /* Physical mode. */ | 167 | irqe.dest_mode = 0; /* Physical mode. */ |
193 | entry.fields.dest_id = ioapic->kvm->vcpus[0]->vcpu_id; | 168 | irqe.dest_id = ioapic->kvm->vcpus[0]->vcpu_id; |
194 | } | 169 | } |
195 | #endif | 170 | #endif |
196 | return ioapic_deliver_entry(ioapic->kvm, &entry); | 171 | return kvm_irq_delivery_to_apic(ioapic->kvm, NULL, &irqe); |
197 | } | 172 | } |
198 | 173 | ||
199 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) | 174 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level) |