diff options
Diffstat (limited to 'virt/kvm/irq_comm.c')
-rw-r--r-- | virt/kvm/irq_comm.c | 51 |
1 files changed, 40 insertions, 11 deletions
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index ddc17f0e2f35..001663ff401a 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/kvm_host.h> | 22 | #include <linux/kvm_host.h> |
23 | #include <trace/events/kvm.h> | ||
23 | 24 | ||
24 | #include <asm/msidef.h> | 25 | #include <asm/msidef.h> |
25 | #ifdef CONFIG_IA64 | 26 | #ifdef CONFIG_IA64 |
@@ -62,14 +63,14 @@ int kvm_irq_delivery_to_apic(struct kvm *kvm, struct kvm_lapic *src, | |||
62 | int i, r = -1; | 63 | int i, r = -1; |
63 | struct kvm_vcpu *vcpu, *lowest = NULL; | 64 | struct kvm_vcpu *vcpu, *lowest = NULL; |
64 | 65 | ||
66 | WARN_ON(!mutex_is_locked(&kvm->irq_lock)); | ||
67 | |||
65 | if (irq->dest_mode == 0 && irq->dest_id == 0xff && | 68 | if (irq->dest_mode == 0 && irq->dest_id == 0xff && |
66 | kvm_is_dm_lowest_prio(irq)) | 69 | kvm_is_dm_lowest_prio(irq)) |
67 | printk(KERN_INFO "kvm: apic: phys broadcast and lowest prio\n"); | 70 | printk(KERN_INFO "kvm: apic: phys broadcast and lowest prio\n"); |
68 | 71 | ||
69 | for (i = 0; i < KVM_MAX_VCPUS; i++) { | 72 | kvm_for_each_vcpu(i, vcpu, kvm) { |
70 | vcpu = kvm->vcpus[i]; | 73 | if (!kvm_apic_present(vcpu)) |
71 | |||
72 | if (!vcpu || !kvm_apic_present(vcpu)) | ||
73 | continue; | 74 | continue; |
74 | 75 | ||
75 | if (!kvm_apic_match_dest(vcpu, src, irq->shorthand, | 76 | if (!kvm_apic_match_dest(vcpu, src, irq->shorthand, |
@@ -99,6 +100,8 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | |||
99 | { | 100 | { |
100 | struct kvm_lapic_irq irq; | 101 | struct kvm_lapic_irq irq; |
101 | 102 | ||
103 | trace_kvm_msi_set_irq(e->msi.address_lo, e->msi.data); | ||
104 | |||
102 | irq.dest_id = (e->msi.address_lo & | 105 | irq.dest_id = (e->msi.address_lo & |
103 | MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; | 106 | MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT; |
104 | irq.vector = (e->msi.data & | 107 | irq.vector = (e->msi.data & |
@@ -113,7 +116,7 @@ static int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | |||
113 | return kvm_irq_delivery_to_apic(kvm, NULL, &irq); | 116 | return kvm_irq_delivery_to_apic(kvm, NULL, &irq); |
114 | } | 117 | } |
115 | 118 | ||
116 | /* This should be called with the kvm->lock mutex held | 119 | /* This should be called with the kvm->irq_lock mutex held |
117 | * Return value: | 120 | * Return value: |
118 | * < 0 Interrupt was ignored (masked or not delivered for other reasons) | 121 | * < 0 Interrupt was ignored (masked or not delivered for other reasons) |
119 | * = 0 Interrupt was coalesced (previous irq is still pending) | 122 | * = 0 Interrupt was coalesced (previous irq is still pending) |
@@ -125,6 +128,10 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) | |||
125 | unsigned long *irq_state, sig_level; | 128 | unsigned long *irq_state, sig_level; |
126 | int ret = -1; | 129 | int ret = -1; |
127 | 130 | ||
131 | trace_kvm_set_irq(irq, level, irq_source_id); | ||
132 | |||
133 | WARN_ON(!mutex_is_locked(&kvm->irq_lock)); | ||
134 | |||
128 | if (irq < KVM_IOAPIC_NUM_PINS) { | 135 | if (irq < KVM_IOAPIC_NUM_PINS) { |
129 | irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; | 136 | irq_state = (unsigned long *)&kvm->arch.irq_states[irq]; |
130 | 137 | ||
@@ -134,7 +141,9 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, int irq, int level) | |||
134 | else | 141 | else |
135 | clear_bit(irq_source_id, irq_state); | 142 | clear_bit(irq_source_id, irq_state); |
136 | sig_level = !!(*irq_state); | 143 | sig_level = !!(*irq_state); |
137 | } else /* Deal with MSI/MSI-X */ | 144 | } else if (!level) |
145 | return ret; | ||
146 | else /* Deal with MSI/MSI-X */ | ||
138 | sig_level = 1; | 147 | sig_level = 1; |
139 | 148 | ||
140 | /* Not possible to detect if the guest uses the PIC or the | 149 | /* Not possible to detect if the guest uses the PIC or the |
@@ -159,6 +168,8 @@ void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) | |||
159 | struct hlist_node *n; | 168 | struct hlist_node *n; |
160 | unsigned gsi = pin; | 169 | unsigned gsi = pin; |
161 | 170 | ||
171 | trace_kvm_ack_irq(irqchip, pin); | ||
172 | |||
162 | list_for_each_entry(e, &kvm->irq_routing, link) | 173 | list_for_each_entry(e, &kvm->irq_routing, link) |
163 | if (e->type == KVM_IRQ_ROUTING_IRQCHIP && | 174 | if (e->type == KVM_IRQ_ROUTING_IRQCHIP && |
164 | e->irqchip.irqchip == irqchip && | 175 | e->irqchip.irqchip == irqchip && |
@@ -175,19 +186,26 @@ void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) | |||
175 | void kvm_register_irq_ack_notifier(struct kvm *kvm, | 186 | void kvm_register_irq_ack_notifier(struct kvm *kvm, |
176 | struct kvm_irq_ack_notifier *kian) | 187 | struct kvm_irq_ack_notifier *kian) |
177 | { | 188 | { |
189 | mutex_lock(&kvm->irq_lock); | ||
178 | hlist_add_head(&kian->link, &kvm->arch.irq_ack_notifier_list); | 190 | hlist_add_head(&kian->link, &kvm->arch.irq_ack_notifier_list); |
191 | mutex_unlock(&kvm->irq_lock); | ||
179 | } | 192 | } |
180 | 193 | ||
181 | void kvm_unregister_irq_ack_notifier(struct kvm_irq_ack_notifier *kian) | 194 | void kvm_unregister_irq_ack_notifier(struct kvm *kvm, |
195 | struct kvm_irq_ack_notifier *kian) | ||
182 | { | 196 | { |
197 | mutex_lock(&kvm->irq_lock); | ||
183 | hlist_del_init(&kian->link); | 198 | hlist_del_init(&kian->link); |
199 | mutex_unlock(&kvm->irq_lock); | ||
184 | } | 200 | } |
185 | 201 | ||
186 | /* The caller must hold kvm->lock mutex */ | ||
187 | int kvm_request_irq_source_id(struct kvm *kvm) | 202 | int kvm_request_irq_source_id(struct kvm *kvm) |
188 | { | 203 | { |
189 | unsigned long *bitmap = &kvm->arch.irq_sources_bitmap; | 204 | unsigned long *bitmap = &kvm->arch.irq_sources_bitmap; |
190 | int irq_source_id = find_first_zero_bit(bitmap, | 205 | int irq_source_id; |
206 | |||
207 | mutex_lock(&kvm->irq_lock); | ||
208 | irq_source_id = find_first_zero_bit(bitmap, | ||
191 | sizeof(kvm->arch.irq_sources_bitmap)); | 209 | sizeof(kvm->arch.irq_sources_bitmap)); |
192 | 210 | ||
193 | if (irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) { | 211 | if (irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) { |
@@ -197,6 +215,7 @@ int kvm_request_irq_source_id(struct kvm *kvm) | |||
197 | 215 | ||
198 | ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); | 216 | ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); |
199 | set_bit(irq_source_id, bitmap); | 217 | set_bit(irq_source_id, bitmap); |
218 | mutex_unlock(&kvm->irq_lock); | ||
200 | 219 | ||
201 | return irq_source_id; | 220 | return irq_source_id; |
202 | } | 221 | } |
@@ -207,6 +226,7 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) | |||
207 | 226 | ||
208 | ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); | 227 | ASSERT(irq_source_id != KVM_USERSPACE_IRQ_SOURCE_ID); |
209 | 228 | ||
229 | mutex_lock(&kvm->irq_lock); | ||
210 | if (irq_source_id < 0 || | 230 | if (irq_source_id < 0 || |
211 | irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) { | 231 | irq_source_id >= sizeof(kvm->arch.irq_sources_bitmap)) { |
212 | printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); | 232 | printk(KERN_ERR "kvm: IRQ source ID out of range!\n"); |
@@ -215,19 +235,24 @@ void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id) | |||
215 | for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) | 235 | for (i = 0; i < KVM_IOAPIC_NUM_PINS; i++) |
216 | clear_bit(irq_source_id, &kvm->arch.irq_states[i]); | 236 | clear_bit(irq_source_id, &kvm->arch.irq_states[i]); |
217 | clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); | 237 | clear_bit(irq_source_id, &kvm->arch.irq_sources_bitmap); |
238 | mutex_unlock(&kvm->irq_lock); | ||
218 | } | 239 | } |
219 | 240 | ||
220 | void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, | 241 | void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, |
221 | struct kvm_irq_mask_notifier *kimn) | 242 | struct kvm_irq_mask_notifier *kimn) |
222 | { | 243 | { |
244 | mutex_lock(&kvm->irq_lock); | ||
223 | kimn->irq = irq; | 245 | kimn->irq = irq; |
224 | hlist_add_head(&kimn->link, &kvm->mask_notifier_list); | 246 | hlist_add_head(&kimn->link, &kvm->mask_notifier_list); |
247 | mutex_unlock(&kvm->irq_lock); | ||
225 | } | 248 | } |
226 | 249 | ||
227 | void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, | 250 | void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, |
228 | struct kvm_irq_mask_notifier *kimn) | 251 | struct kvm_irq_mask_notifier *kimn) |
229 | { | 252 | { |
253 | mutex_lock(&kvm->irq_lock); | ||
230 | hlist_del(&kimn->link); | 254 | hlist_del(&kimn->link); |
255 | mutex_unlock(&kvm->irq_lock); | ||
231 | } | 256 | } |
232 | 257 | ||
233 | void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask) | 258 | void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask) |
@@ -235,6 +260,8 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, bool mask) | |||
235 | struct kvm_irq_mask_notifier *kimn; | 260 | struct kvm_irq_mask_notifier *kimn; |
236 | struct hlist_node *n; | 261 | struct hlist_node *n; |
237 | 262 | ||
263 | WARN_ON(!mutex_is_locked(&kvm->irq_lock)); | ||
264 | |||
238 | hlist_for_each_entry(kimn, n, &kvm->mask_notifier_list, link) | 265 | hlist_for_each_entry(kimn, n, &kvm->mask_notifier_list, link) |
239 | if (kimn->irq == irq) | 266 | if (kimn->irq == irq) |
240 | kimn->func(kimn, mask); | 267 | kimn->func(kimn, mask); |
@@ -250,7 +277,9 @@ static void __kvm_free_irq_routing(struct list_head *irq_routing) | |||
250 | 277 | ||
251 | void kvm_free_irq_routing(struct kvm *kvm) | 278 | void kvm_free_irq_routing(struct kvm *kvm) |
252 | { | 279 | { |
280 | mutex_lock(&kvm->irq_lock); | ||
253 | __kvm_free_irq_routing(&kvm->irq_routing); | 281 | __kvm_free_irq_routing(&kvm->irq_routing); |
282 | mutex_unlock(&kvm->irq_lock); | ||
254 | } | 283 | } |
255 | 284 | ||
256 | static int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e, | 285 | static int setup_routing_entry(struct kvm_kernel_irq_routing_entry *e, |
@@ -325,13 +354,13 @@ int kvm_set_irq_routing(struct kvm *kvm, | |||
325 | e = NULL; | 354 | e = NULL; |
326 | } | 355 | } |
327 | 356 | ||
328 | mutex_lock(&kvm->lock); | 357 | mutex_lock(&kvm->irq_lock); |
329 | list_splice(&kvm->irq_routing, &tmp); | 358 | list_splice(&kvm->irq_routing, &tmp); |
330 | INIT_LIST_HEAD(&kvm->irq_routing); | 359 | INIT_LIST_HEAD(&kvm->irq_routing); |
331 | list_splice(&irq_list, &kvm->irq_routing); | 360 | list_splice(&irq_list, &kvm->irq_routing); |
332 | INIT_LIST_HEAD(&irq_list); | 361 | INIT_LIST_HEAD(&irq_list); |
333 | list_splice(&tmp, &irq_list); | 362 | list_splice(&tmp, &irq_list); |
334 | mutex_unlock(&kvm->lock); | 363 | mutex_unlock(&kvm->irq_lock); |
335 | 364 | ||
336 | r = 0; | 365 | r = 0; |
337 | 366 | ||