aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2014-06-30 06:51:10 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2014-08-05 08:26:16 -0400
commit8ba918d488caded2c4368b0b922eb905fe3bb101 (patch)
tree6b14bc6c9b763e5dd7b641c902db3fd04b4d4b89
parent56f89f3629ffd1a21d38c3d0bea23deac0e284ce (diff)
KVM: irqchip: Provide and use accessors for irq routing table
This provides accessor functions for the KVM interrupt mappings, in order to reduce the amount of code that accesses the fields of the kvm_irq_routing_table struct, and restrict that code to one file, virt/kvm/irqchip.c. The new functions are kvm_irq_map_gsi(), which maps from a global interrupt number to a set of IRQ routing entries, and kvm_irq_map_chip_pin, which maps from IRQ chip and pin numbers to a global interrupt number. This also moves the update of kvm_irq_routing_table::chip[][] into irqchip.c, out of the various kvm_set_routing_entry implementations. That means that none of the kvm_set_routing_entry implementations need the kvm_irq_routing_table argument anymore, so this removes it. This does not change any locking or data lifetime rules. Signed-off-by: Paul Mackerras <paulus@samba.org> Tested-by: Eric Auger <eric.auger@linaro.org> Tested-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-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;