diff options
-rw-r--r-- | arch/powerpc/kvm/mpic.c | 4 | ||||
-rw-r--r-- | arch/s390/kvm/interrupt.c | 3 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 8 | ||||
-rw-r--r-- | virt/kvm/eventfd.c | 10 | ||||
-rw-r--r-- | virt/kvm/irq_comm.c | 20 | ||||
-rw-r--r-- | virt/kvm/irqchip.c | 42 |
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 | ||
1829 | int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, | 1829 | int 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 | ||
1559 | int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, | 1559 | int 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, | |||
752 | void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, | 752 | void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, |
753 | bool mask); | 753 | bool mask); |
754 | 754 | ||
755 | int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries, | ||
756 | struct kvm_irq_routing_table *irq_rt, int gsi); | ||
757 | int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt, | ||
758 | unsigned irqchip, unsigned pin); | ||
759 | |||
755 | int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, | 760 | int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, |
756 | bool line_status); | 761 | bool line_status); |
757 | int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level); | 762 | int 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); |
945 | int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, | 950 | int 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); |
948 | void kvm_free_irq_routing(struct kvm *kvm); | 952 | void 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 | */ |
161 | int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level) | 161 | int 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 | ||
275 | int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, | 275 | int 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 | ||
34 | int 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 | |||
50 | int 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 | |||
34 | bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) | 56 | bool 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 | ||
55 | void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) | 79 | void 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) | |||
115 | int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, | 141 | int 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; |