summaryrefslogtreecommitdiff
path: root/virt
diff options
context:
space:
mode:
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/ioapic.c5
-rw-r--r--virt/kvm/ioapic.h10
-rw-r--r--virt/kvm/irq_comm.c74
3 files changed, 31 insertions, 58 deletions
diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c
index b71c0442cecf..43969bbf127f 100644
--- a/virt/kvm/ioapic.c
+++ b/virt/kvm/ioapic.c
@@ -147,7 +147,10 @@ int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e)
DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS);
int i, r = -1;
- kvm_get_intr_delivery_bitmask(kvm, e, deliver_bitmask);
+ kvm_get_intr_delivery_bitmask(kvm, NULL, e->fields.dest_id,
+ e->fields.dest_mode,
+ e->fields.delivery_mode == IOAPIC_LOWEST_PRIORITY,
+ 0, deliver_bitmask);
if (find_first_bit(deliver_bitmask, KVM_MAX_VCPUS) >= KVM_MAX_VCPUS) {
ioapic_debug("no target on destination\n");
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index bedeea59cc1c..d996c7abc466 100644
--- a/virt/kvm/ioapic.h
+++ b/virt/kvm/ioapic.h
@@ -65,13 +65,15 @@ static inline struct kvm_ioapic *ioapic_irqchip(struct kvm *kvm)
}
struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
- unsigned long *bitmap);
+ unsigned long *bitmap);
+int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
+ int short_hand, int dest, int dest_mode);
void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
int kvm_ioapic_init(struct kvm *kvm);
int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
-void kvm_get_intr_delivery_bitmask(struct kvm *kvm,
- union kvm_ioapic_redirect_entry *entry,
- unsigned long *deliver_bitmask);
+void kvm_get_intr_delivery_bitmask(struct kvm *kvm, struct kvm_lapic *src,
+ int dest_id, int dest_mode, bool low_prio, int short_hand,
+ unsigned long *deliver_bitmask);
int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e);
#endif
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 35397a569b24..e43701c0a5c4 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -43,67 +43,35 @@ static int kvm_set_ioapic_irq(struct kvm_kernel_irq_routing_entry *e,
return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
}
-void kvm_get_intr_delivery_bitmask(struct kvm *kvm,
- union kvm_ioapic_redirect_entry *entry,
- unsigned long *deliver_bitmask)
+void kvm_get_intr_delivery_bitmask(struct kvm *kvm, struct kvm_lapic *src,
+ int dest_id, int dest_mode, bool low_prio, int short_hand,
+ unsigned long *deliver_bitmask)
{
int i;
struct kvm_vcpu *vcpu;
+ if (dest_mode == 0 && dest_id == 0xff && low_prio)
+ printk(KERN_INFO "kvm: apic: phys broadcast and lowest prio\n");
+
bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
+ for (i = 0; i < KVM_MAX_VCPUS; i++) {
+ vcpu = kvm->vcpus[i];
- if (entry->fields.dest_mode == 0) { /* Physical mode. */
- if (entry->fields.dest_id == 0xFF) { /* Broadcast. */
- for (i = 0; i < KVM_MAX_VCPUS; ++i)
- if (kvm->vcpus[i] && kvm->vcpus[i]->arch.apic)
- __set_bit(i, deliver_bitmask);
- /* Lowest priority shouldn't combine with broadcast */
- if (entry->fields.delivery_mode ==
- IOAPIC_LOWEST_PRIORITY && printk_ratelimit())
- printk(KERN_INFO "kvm: apic: phys broadcast "
- "and lowest prio\n");
- return;
- }
- for (i = 0; i < KVM_MAX_VCPUS; ++i) {
- vcpu = kvm->vcpus[i];
- if (!vcpu)
- continue;
- if (kvm_apic_match_physical_addr(vcpu->arch.apic,
- entry->fields.dest_id)) {
- if (vcpu->arch.apic)
- __set_bit(i, deliver_bitmask);
- break;
- }
- }
- } else if (entry->fields.dest_id != 0) /* Logical mode, MDA non-zero. */
- for (i = 0; i < KVM_MAX_VCPUS; ++i) {
- vcpu = kvm->vcpus[i];
- if (!vcpu)
- continue;
- if (vcpu->arch.apic &&
- kvm_apic_match_logical_addr(vcpu->arch.apic,
- entry->fields.dest_id))
- __set_bit(i, deliver_bitmask);
- }
+ if (!vcpu || !kvm_apic_present(vcpu))
+ continue;
- switch (entry->fields.delivery_mode) {
- case IOAPIC_LOWEST_PRIORITY:
- /* Select one in deliver_bitmask */
- vcpu = kvm_get_lowest_prio_vcpu(kvm,
- entry->fields.vector, deliver_bitmask);
- bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
- if (!vcpu)
- return;
- __set_bit(vcpu->vcpu_id, deliver_bitmask);
- break;
- case IOAPIC_FIXED:
- case IOAPIC_NMI:
- break;
- default:
- if (printk_ratelimit())
- printk(KERN_INFO "kvm: unsupported delivery mode %d\n",
- entry->fields.delivery_mode);
+ if (!kvm_apic_match_dest(vcpu, src, short_hand, dest_id,
+ dest_mode))
+ continue;
+
+ __set_bit(i, deliver_bitmask);
+ }
+
+ if (low_prio) {
+ vcpu = kvm_get_lowest_prio_vcpu(kvm, 0, deliver_bitmask);
bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
+ if (vcpu)
+ __set_bit(vcpu->vcpu_id, deliver_bitmask);
}
}