aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kvm/mpic.c4
-rw-r--r--arch/s390/kvm/interrupt.c3
-rw-r--r--include/linux/kvm_host.h8
-rw-r--r--virt/kvm/eventfd.c10
-rw-r--r--virt/kvm/irq_comm.c20
-rw-r--r--virt/kvm/irqchip.c42
6 files changed, 57 insertions, 30 deletions
diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c
index b68d0dc9479a..39b3a8f816f2 100644
--- a/arch/powerpc/kvm/mpic.c
+++ b/arch/powerpc/kvm/mpic.c
@@ -1826,8 +1826,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
1826 return 0; 1826 return 0;
1827} 1827}
1828 1828
1829int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, 1829int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
1830 struct kvm_kernel_irq_routing_entry *e,
1831 const struct kvm_irq_routing_entry *ue) 1830 const struct kvm_irq_routing_entry *ue)
1832{ 1831{
1833 int r = -EINVAL; 1832 int r = -EINVAL;
@@ -1839,7 +1838,6 @@ int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
1839 e->irqchip.pin = ue->u.irqchip.pin; 1838 e->irqchip.pin = ue->u.irqchip.pin;
1840 if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) 1839 if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS)
1841 goto out; 1840 goto out;
1842 rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi;
1843 break; 1841 break;
1844 case KVM_IRQ_ROUTING_MSI: 1842 case KVM_IRQ_ROUTING_MSI:
1845 e->set = kvm_set_msi; 1843 e->set = kvm_set_msi;
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 92528a0bdda6..f4c819bfc193 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -1556,8 +1556,7 @@ static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e,
1556 return ret; 1556 return ret;
1557} 1557}
1558 1558
1559int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, 1559int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
1560 struct kvm_kernel_irq_routing_entry *e,
1561 const struct kvm_irq_routing_entry *ue) 1560 const struct kvm_irq_routing_entry *ue)
1562{ 1561{
1563 int ret; 1562 int ret;
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 5065b953e6e8..4956149e962a 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -752,6 +752,11 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq,
752void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, 752void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
753 bool mask); 753 bool mask);
754 754
755int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries,
756 struct kvm_irq_routing_table *irq_rt, int gsi);
757int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt,
758 unsigned irqchip, unsigned pin);
759
755int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, 760int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
756 bool line_status); 761 bool line_status);
757int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level); 762int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level);
@@ -942,8 +947,7 @@ int kvm_set_irq_routing(struct kvm *kvm,
942 const struct kvm_irq_routing_entry *entries, 947 const struct kvm_irq_routing_entry *entries,
943 unsigned nr, 948 unsigned nr,
944 unsigned flags); 949 unsigned flags);
945int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, 950int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
946 struct kvm_kernel_irq_routing_entry *e,
947 const struct kvm_irq_routing_entry *ue); 951 const struct kvm_irq_routing_entry *ue);
948void kvm_free_irq_routing(struct kvm *kvm); 952void kvm_free_irq_routing(struct kvm *kvm);
949 953
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index bae593a545c5..15fa9488b2d0 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -282,20 +282,22 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd,
282 struct kvm_irq_routing_table *irq_rt) 282 struct kvm_irq_routing_table *irq_rt)
283{ 283{
284 struct kvm_kernel_irq_routing_entry *e; 284 struct kvm_kernel_irq_routing_entry *e;
285 struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS];
286 int i, n_entries;
287
288 n_entries = kvm_irq_map_gsi(entries, irq_rt, irqfd->gsi);
285 289
286 write_seqcount_begin(&irqfd->irq_entry_sc); 290 write_seqcount_begin(&irqfd->irq_entry_sc);
287 291
288 irqfd->irq_entry.type = 0; 292 irqfd->irq_entry.type = 0;
289 if (irqfd->gsi >= irq_rt->nr_rt_entries)
290 goto out;
291 293
292 hlist_for_each_entry(e, &irq_rt->map[irqfd->gsi], link) { 294 e = entries;
295 for (i = 0; i < n_entries; ++i, ++e) {
293 /* Only fast-path MSI. */ 296 /* Only fast-path MSI. */
294 if (e->type == KVM_IRQ_ROUTING_MSI) 297 if (e->type == KVM_IRQ_ROUTING_MSI)
295 irqfd->irq_entry = *e; 298 irqfd->irq_entry = *e;
296 } 299 }
297 300
298 out:
299 write_seqcount_end(&irqfd->irq_entry_sc); 301 write_seqcount_end(&irqfd->irq_entry_sc);
300} 302}
301 303
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c
index a228ee82bad2..175844593243 100644
--- a/virt/kvm/irq_comm.c
+++ b/virt/kvm/irq_comm.c
@@ -160,6 +160,7 @@ static int kvm_set_msi_inatomic(struct kvm_kernel_irq_routing_entry *e,
160 */ 160 */
161int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level) 161int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
162{ 162{
163 struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS];
163 struct kvm_kernel_irq_routing_entry *e; 164 struct kvm_kernel_irq_routing_entry *e;
164 int ret = -EINVAL; 165 int ret = -EINVAL;
165 struct kvm_irq_routing_table *irq_rt; 166 struct kvm_irq_routing_table *irq_rt;
@@ -177,14 +178,13 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level)
177 */ 178 */
178 idx = srcu_read_lock(&kvm->irq_srcu); 179 idx = srcu_read_lock(&kvm->irq_srcu);
179 irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); 180 irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
180 if (irq < irq_rt->nr_rt_entries) 181 if (kvm_irq_map_gsi(entries, irq_rt, irq) > 0) {
181 hlist_for_each_entry(e, &irq_rt->map[irq], link) { 182 e = &entries[0];
182 if (likely(e->type == KVM_IRQ_ROUTING_MSI)) 183 if (likely(e->type == KVM_IRQ_ROUTING_MSI))
183 ret = kvm_set_msi_inatomic(e, kvm); 184 ret = kvm_set_msi_inatomic(e, kvm);
184 else 185 else
185 ret = -EWOULDBLOCK; 186 ret = -EWOULDBLOCK;
186 break; 187 }
187 }
188 srcu_read_unlock(&kvm->irq_srcu, idx); 188 srcu_read_unlock(&kvm->irq_srcu, idx);
189 return ret; 189 return ret;
190} 190}
@@ -272,8 +272,7 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin,
272 srcu_read_unlock(&kvm->irq_srcu, idx); 272 srcu_read_unlock(&kvm->irq_srcu, idx);
273} 273}
274 274
275int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, 275int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e,
276 struct kvm_kernel_irq_routing_entry *e,
277 const struct kvm_irq_routing_entry *ue) 276 const struct kvm_irq_routing_entry *ue)
278{ 277{
279 int r = -EINVAL; 278 int r = -EINVAL;
@@ -304,7 +303,6 @@ int kvm_set_routing_entry(struct kvm_irq_routing_table *rt,
304 e->irqchip.pin = ue->u.irqchip.pin + delta; 303 e->irqchip.pin = ue->u.irqchip.pin + delta;
305 if (e->irqchip.pin >= max_pin) 304 if (e->irqchip.pin >= max_pin)
306 goto out; 305 goto out;
307 rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi;
308 break; 306 break;
309 case KVM_IRQ_ROUTING_MSI: 307 case KVM_IRQ_ROUTING_MSI:
310 e->set = kvm_set_msi; 308 e->set = kvm_set_msi;
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c
index b43c275775cd..f4648dd94888 100644
--- a/virt/kvm/irqchip.c
+++ b/virt/kvm/irqchip.c
@@ -31,13 +31,37 @@
31#include <trace/events/kvm.h> 31#include <trace/events/kvm.h>
32#include "irq.h" 32#include "irq.h"
33 33
34int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries,
35 struct kvm_irq_routing_table *irq_rt, int gsi)
36{
37 struct kvm_kernel_irq_routing_entry *e;
38 int n = 0;
39
40 if (gsi < irq_rt->nr_rt_entries) {
41 hlist_for_each_entry(e, &irq_rt->map[gsi], link) {
42 entries[n] = *e;
43 ++n;
44 }
45 }
46
47 return n;
48}
49
50int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt,
51 unsigned irqchip, unsigned pin)
52{
53 return irq_rt->chip[irqchip][pin];
54}
55
34bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) 56bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin)
35{ 57{
58 struct kvm_irq_routing_table *irq_rt;
36 struct kvm_irq_ack_notifier *kian; 59 struct kvm_irq_ack_notifier *kian;
37 int gsi, idx; 60 int gsi, idx;
38 61
39 idx = srcu_read_lock(&kvm->irq_srcu); 62 idx = srcu_read_lock(&kvm->irq_srcu);
40 gsi = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu)->chip[irqchip][pin]; 63 irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
64 gsi = kvm_irq_map_chip_pin(irq_rt, irqchip, pin);
41 if (gsi != -1) 65 if (gsi != -1)
42 hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, 66 hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
43 link) 67 link)
@@ -54,13 +78,15 @@ EXPORT_SYMBOL_GPL(kvm_irq_has_notifier);
54 78
55void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) 79void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin)
56{ 80{
81 struct kvm_irq_routing_table *irq_rt;
57 struct kvm_irq_ack_notifier *kian; 82 struct kvm_irq_ack_notifier *kian;
58 int gsi, idx; 83 int gsi, idx;
59 84
60 trace_kvm_ack_irq(irqchip, pin); 85 trace_kvm_ack_irq(irqchip, pin);
61 86
62 idx = srcu_read_lock(&kvm->irq_srcu); 87 idx = srcu_read_lock(&kvm->irq_srcu);
63 gsi = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu)->chip[irqchip][pin]; 88 irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
89 gsi = kvm_irq_map_chip_pin(irq_rt, irqchip, pin);
64 if (gsi != -1) 90 if (gsi != -1)
65 hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, 91 hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list,
66 link) 92 link)
@@ -115,8 +141,8 @@ int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi)
115int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, 141int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
116 bool line_status) 142 bool line_status)
117{ 143{
118 struct kvm_kernel_irq_routing_entry *e, irq_set[KVM_NR_IRQCHIPS]; 144 struct kvm_kernel_irq_routing_entry irq_set[KVM_NR_IRQCHIPS];
119 int ret = -1, i = 0, idx; 145 int ret = -1, i, idx;
120 struct kvm_irq_routing_table *irq_rt; 146 struct kvm_irq_routing_table *irq_rt;
121 147
122 trace_kvm_set_irq(irq, level, irq_source_id); 148 trace_kvm_set_irq(irq, level, irq_source_id);
@@ -127,9 +153,7 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
127 */ 153 */
128 idx = srcu_read_lock(&kvm->irq_srcu); 154 idx = srcu_read_lock(&kvm->irq_srcu);
129 irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); 155 irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu);
130 if (irq < irq_rt->nr_rt_entries) 156 i = kvm_irq_map_gsi(irq_set, irq_rt, irq);
131 hlist_for_each_entry(e, &irq_rt->map[irq], link)
132 irq_set[i++] = *e;
133 srcu_read_unlock(&kvm->irq_srcu, idx); 157 srcu_read_unlock(&kvm->irq_srcu, idx);
134 158
135 while(i--) { 159 while(i--) {
@@ -171,9 +195,11 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt,
171 195
172 e->gsi = ue->gsi; 196 e->gsi = ue->gsi;
173 e->type = ue->type; 197 e->type = ue->type;
174 r = kvm_set_routing_entry(rt, e, ue); 198 r = kvm_set_routing_entry(e, ue);
175 if (r) 199 if (r)
176 goto out; 200 goto out;
201 if (e->type == KVM_IRQ_ROUTING_IRQCHIP)
202 rt->chip[e->irqchip.irqchip][e->irqchip.pin] = e->gsi;
177 203
178 hlist_add_head(&e->link, &rt->map[e->gsi]); 204 hlist_add_head(&e->link, &rt->map[e->gsi]);
179 r = 0; 205 r = 0;