aboutsummaryrefslogtreecommitdiffstats
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 b71c0442cec..43969bbf127 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)
147 DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS); 147 DECLARE_BITMAP(deliver_bitmask, KVM_MAX_VCPUS);
148 int i, r = -1; 148 int i, r = -1;
149 149
150 kvm_get_intr_delivery_bitmask(kvm, e, deliver_bitmask); 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);
151 154
152 if (find_first_bit(deliver_bitmask, KVM_MAX_VCPUS) >= KVM_MAX_VCPUS) { 155 if (find_first_bit(deliver_bitmask, KVM_MAX_VCPUS) >= KVM_MAX_VCPUS) {
153 ioapic_debug("no target on destination\n"); 156 ioapic_debug("no target on destination\n");
diff --git a/virt/kvm/ioapic.h b/virt/kvm/ioapic.h
index bedeea59cc1..d996c7abc46 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)
65} 65}
66 66
67struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector, 67struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector,
68 unsigned long *bitmap); 68 unsigned long *bitmap);
69int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
70 int short_hand, int dest, int dest_mode);
69void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); 71void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode);
70int kvm_ioapic_init(struct kvm *kvm); 72int kvm_ioapic_init(struct kvm *kvm);
71int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); 73int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level);
72void kvm_ioapic_reset(struct kvm_ioapic *ioapic); 74void kvm_ioapic_reset(struct kvm_ioapic *ioapic);
73void kvm_get_intr_delivery_bitmask(struct kvm *kvm, 75void kvm_get_intr_delivery_bitmask(struct kvm *kvm, struct kvm_lapic *src,
74 union kvm_ioapic_redirect_entry *entry, 76 int dest_id, int dest_mode, bool low_prio, int short_hand,
75 unsigned long *deliver_bitmask); 77 unsigned long *deliver_bitmask);
76int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e); 78int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e);
77#endif 79#endif
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index 35397a569b2..e43701c0a5c 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,
43 return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level); 43 return kvm_ioapic_set_irq(kvm->arch.vioapic, e->irqchip.pin, level);
44} 44}
45 45
46void kvm_get_intr_delivery_bitmask(struct kvm *kvm, 46void kvm_get_intr_delivery_bitmask(struct kvm *kvm, struct kvm_lapic *src,
47 union kvm_ioapic_redirect_entry *entry, 47 int dest_id, int dest_mode, bool low_prio, int short_hand,
48 unsigned long *deliver_bitmask) 48 unsigned long *deliver_bitmask)
49{ 49{
50 int i; 50 int i;
51 struct kvm_vcpu *vcpu; 51 struct kvm_vcpu *vcpu;
52 52
53 if (dest_mode == 0 && dest_id == 0xff && low_prio)
54 printk(KERN_INFO "kvm: apic: phys broadcast and lowest prio\n");
55
53 bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); 56 bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
57 for (i = 0; i < KVM_MAX_VCPUS; i++) {
58 vcpu = kvm->vcpus[i];
54 59
55 if (entry->fields.dest_mode == 0) { /* Physical mode. */ 60 if (!vcpu || !kvm_apic_present(vcpu))
56 if (entry->fields.dest_id == 0xFF) { /* Broadcast. */ 61 continue;
57 for (i = 0; i < KVM_MAX_VCPUS; ++i)
58 if (kvm->vcpus[i] && kvm->vcpus[i]->arch.apic)
59 __set_bit(i, deliver_bitmask);
60 /* Lowest priority shouldn't combine with broadcast */
61 if (entry->fields.delivery_mode ==
62 IOAPIC_LOWEST_PRIORITY && printk_ratelimit())
63 printk(KERN_INFO "kvm: apic: phys broadcast "
64 "and lowest prio\n");
65 return;
66 }
67 for (i = 0; i < KVM_MAX_VCPUS; ++i) {
68 vcpu = kvm->vcpus[i];
69 if (!vcpu)
70 continue;
71 if (kvm_apic_match_physical_addr(vcpu->arch.apic,
72 entry->fields.dest_id)) {
73 if (vcpu->arch.apic)
74 __set_bit(i, deliver_bitmask);
75 break;
76 }
77 }
78 } else if (entry->fields.dest_id != 0) /* Logical mode, MDA non-zero. */
79 for (i = 0; i < KVM_MAX_VCPUS; ++i) {
80 vcpu = kvm->vcpus[i];
81 if (!vcpu)
82 continue;
83 if (vcpu->arch.apic &&
84 kvm_apic_match_logical_addr(vcpu->arch.apic,
85 entry->fields.dest_id))
86 __set_bit(i, deliver_bitmask);
87 }
88 62
89 switch (entry->fields.delivery_mode) { 63 if (!kvm_apic_match_dest(vcpu, src, short_hand, dest_id,
90 case IOAPIC_LOWEST_PRIORITY: 64 dest_mode))
91 /* Select one in deliver_bitmask */ 65 continue;
92 vcpu = kvm_get_lowest_prio_vcpu(kvm, 66
93 entry->fields.vector, deliver_bitmask); 67 __set_bit(i, deliver_bitmask);
94 bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); 68 }
95 if (!vcpu) 69
96 return; 70 if (low_prio) {
97 __set_bit(vcpu->vcpu_id, deliver_bitmask); 71 vcpu = kvm_get_lowest_prio_vcpu(kvm, 0, deliver_bitmask);
98 break;
99 case IOAPIC_FIXED:
100 case IOAPIC_NMI:
101 break;
102 default:
103 if (printk_ratelimit())
104 printk(KERN_INFO "kvm: unsupported delivery mode %d\n",
105 entry->fields.delivery_mode);
106 bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS); 72 bitmap_zero(deliver_bitmask, KVM_MAX_VCPUS);
73 if (vcpu)
74 __set_bit(vcpu->vcpu_id, deliver_bitmask);
107 } 75 }
108} 76}
109 77