diff options
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/ioapic.c | 5 | ||||
-rw-r--r-- | virt/kvm/ioapic.h | 10 | ||||
-rw-r--r-- | virt/kvm/irq_comm.c | 74 |
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 | ||
67 | struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector, | 67 | struct kvm_vcpu *kvm_get_lowest_prio_vcpu(struct kvm *kvm, u8 vector, |
68 | unsigned long *bitmap); | 68 | unsigned long *bitmap); |
69 | int kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source, | ||
70 | int short_hand, int dest, int dest_mode); | ||
69 | void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); | 71 | void kvm_ioapic_update_eoi(struct kvm *kvm, int vector, int trigger_mode); |
70 | int kvm_ioapic_init(struct kvm *kvm); | 72 | int kvm_ioapic_init(struct kvm *kvm); |
71 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); | 73 | int kvm_ioapic_set_irq(struct kvm_ioapic *ioapic, int irq, int level); |
72 | void kvm_ioapic_reset(struct kvm_ioapic *ioapic); | 74 | void kvm_ioapic_reset(struct kvm_ioapic *ioapic); |
73 | void kvm_get_intr_delivery_bitmask(struct kvm *kvm, | 75 | void 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); |
76 | int ioapic_deliver_entry(struct kvm *kvm, union kvm_ioapic_redirect_entry *e); | 78 | int 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 | ||
46 | void kvm_get_intr_delivery_bitmask(struct kvm *kvm, | 46 | void 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 | ||