Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: Extract generic irqchip logic into irqchip.c

The current irq_comm.c file contains pieces of code that are generic
across different irqchip implementations, as well as code that is
fully IOAPIC specific.

Split the generic bits out into irqchip.c.

Signed-off-by: Alexander Graf <agraf@suse.de>
Acked-by: Michael S. Tsirkin <mst@redhat.com>

+163 -121
+1 -1
arch/x86/kvm/Makefile
··· 7 7 8 8 kvm-y += $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \ 9 9 coalesced_mmio.o irq_comm.o eventfd.o \ 10 - assigned-dev.o) 10 + assigned-dev.o irqchip.o) 11 11 kvm-$(CONFIG_IOMMU_API) += $(addprefix ../../../virt/kvm/, iommu.o) 12 12 kvm-$(CONFIG_KVM_ASYNC_PF) += $(addprefix ../../../virt/kvm/, async_pf.o) 13 13
+10 -2
include/trace/events/kvm.h
··· 37 37 __entry->errno < 0 ? -__entry->errno : __entry->reason) 38 38 ); 39 39 40 - #if defined(__KVM_HAVE_IRQ_LINE) 40 + #if defined(CONFIG_HAVE_KVM_IRQCHIP) 41 41 TRACE_EVENT(kvm_set_irq, 42 42 TP_PROTO(unsigned int gsi, int level, int irq_source_id), 43 43 TP_ARGS(gsi, level, irq_source_id), ··· 122 122 {KVM_IRQCHIP_PIC_SLAVE, "PIC slave"}, \ 123 123 {KVM_IRQCHIP_IOAPIC, "IOAPIC"} 124 124 125 + #endif /* defined(__KVM_HAVE_IOAPIC) */ 126 + 127 + #if defined(CONFIG_HAVE_KVM_IRQCHIP) 128 + 125 129 TRACE_EVENT(kvm_ack_irq, 126 130 TP_PROTO(unsigned int irqchip, unsigned int pin), 127 131 TP_ARGS(irqchip, pin), ··· 140 136 __entry->pin = pin; 141 137 ), 142 138 139 + #ifdef kvm_irqchips 143 140 TP_printk("irqchip %s pin %u", 144 141 __print_symbolic(__entry->irqchip, kvm_irqchips), 145 142 __entry->pin) 143 + #else 144 + TP_printk("irqchip %d pin %u", __entry->irqchip, __entry->pin) 145 + #endif 146 146 ); 147 147 148 + #endif /* defined(CONFIG_HAVE_KVM_IRQCHIP) */ 148 149 149 150 150 - #endif /* defined(__KVM_HAVE_IOAPIC) */ 151 151 152 152 #define KVM_TRACE_MMIO_READ_UNSATISFIED 0 153 153 #define KVM_TRACE_MMIO_READ 1
-118
virt/kvm/irq_comm.c
··· 151 151 return -EWOULDBLOCK; 152 152 } 153 153 154 - int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi) 155 - { 156 - struct kvm_kernel_irq_routing_entry route; 157 - 158 - if (!irqchip_in_kernel(kvm) || msi->flags != 0) 159 - return -EINVAL; 160 - 161 - route.msi.address_lo = msi->address_lo; 162 - route.msi.address_hi = msi->address_hi; 163 - route.msi.data = msi->data; 164 - 165 - return kvm_set_msi(&route, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1, false); 166 - } 167 - 168 - /* 169 - * Return value: 170 - * < 0 Interrupt was ignored (masked or not delivered for other reasons) 171 - * = 0 Interrupt was coalesced (previous irq is still pending) 172 - * > 0 Number of CPUs interrupt was delivered to 173 - */ 174 - int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, 175 - bool line_status) 176 - { 177 - struct kvm_kernel_irq_routing_entry *e, irq_set[KVM_NR_IRQCHIPS]; 178 - int ret = -1, i = 0; 179 - struct kvm_irq_routing_table *irq_rt; 180 - 181 - trace_kvm_set_irq(irq, level, irq_source_id); 182 - 183 - /* Not possible to detect if the guest uses the PIC or the 184 - * IOAPIC. So set the bit in both. The guest will ignore 185 - * writes to the unused one. 186 - */ 187 - rcu_read_lock(); 188 - irq_rt = rcu_dereference(kvm->irq_routing); 189 - if (irq < irq_rt->nr_rt_entries) 190 - hlist_for_each_entry(e, &irq_rt->map[irq], link) 191 - irq_set[i++] = *e; 192 - rcu_read_unlock(); 193 - 194 - while(i--) { 195 - int r; 196 - r = irq_set[i].set(&irq_set[i], kvm, irq_source_id, level, 197 - line_status); 198 - if (r < 0) 199 - continue; 200 - 201 - ret = r + ((ret < 0) ? 0 : ret); 202 - } 203 - 204 - return ret; 205 - } 206 - 207 154 /* 208 155 * Deliver an IRQ in an atomic context if we can, or return a failure, 209 156 * user can retry in a process context. ··· 186 239 } 187 240 rcu_read_unlock(); 188 241 return ret; 189 - } 190 - 191 - bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) 192 - { 193 - struct kvm_irq_ack_notifier *kian; 194 - int gsi; 195 - 196 - rcu_read_lock(); 197 - gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin]; 198 - if (gsi != -1) 199 - hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, 200 - link) 201 - if (kian->gsi == gsi) { 202 - rcu_read_unlock(); 203 - return true; 204 - } 205 - 206 - rcu_read_unlock(); 207 - 208 - return false; 209 - } 210 - EXPORT_SYMBOL_GPL(kvm_irq_has_notifier); 211 - 212 - void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) 213 - { 214 - struct kvm_irq_ack_notifier *kian; 215 - int gsi; 216 - 217 - trace_kvm_ack_irq(irqchip, pin); 218 - 219 - rcu_read_lock(); 220 - gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin]; 221 - if (gsi != -1) 222 - hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, 223 - link) 224 - if (kian->gsi == gsi) 225 - kian->irq_acked(kian); 226 - rcu_read_unlock(); 227 - } 228 - 229 - void kvm_register_irq_ack_notifier(struct kvm *kvm, 230 - struct kvm_irq_ack_notifier *kian) 231 - { 232 - mutex_lock(&kvm->irq_lock); 233 - hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list); 234 - mutex_unlock(&kvm->irq_lock); 235 - kvm_vcpu_request_scan_ioapic(kvm); 236 - } 237 - 238 - void kvm_unregister_irq_ack_notifier(struct kvm *kvm, 239 - struct kvm_irq_ack_notifier *kian) 240 - { 241 - mutex_lock(&kvm->irq_lock); 242 - hlist_del_init_rcu(&kian->link); 243 - mutex_unlock(&kvm->irq_lock); 244 - synchronize_rcu(); 245 - kvm_vcpu_request_scan_ioapic(kvm); 246 242 } 247 243 248 244 int kvm_request_irq_source_id(struct kvm *kvm) ··· 271 381 rcu_read_unlock(); 272 382 } 273 383 274 - void kvm_free_irq_routing(struct kvm *kvm) 275 - { 276 - /* Called only during vm destruction. Nobody can use the pointer 277 - at this stage */ 278 - kfree(kvm->irq_routing); 279 - } 280 - 281 384 static int setup_routing_entry(struct kvm_irq_routing_table *rt, 282 385 struct kvm_kernel_irq_routing_entry *e, 283 386 const struct kvm_irq_routing_entry *ue) ··· 333 450 out: 334 451 return r; 335 452 } 336 - 337 453 338 454 int kvm_set_irq_routing(struct kvm *kvm, 339 455 const struct kvm_irq_routing_entry *ue,
+152
virt/kvm/irqchip.c
··· 1 + /* 2 + * irqchip.c: Common API for in kernel interrupt controllers 3 + * Copyright (c) 2007, Intel Corporation. 4 + * Copyright 2010 Red Hat, Inc. and/or its affiliates. 5 + * Copyright (c) 2013, Alexander Graf <agraf@suse.de> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms and conditions of the GNU General Public License, 9 + * version 2, as published by the Free Software Foundation. 10 + * 11 + * This program is distributed in the hope it will be useful, but WITHOUT 12 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 + * more details. 15 + * 16 + * You should have received a copy of the GNU General Public License along with 17 + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple 18 + * Place - Suite 330, Boston, MA 02111-1307 USA. 19 + * 20 + * This file is derived from virt/kvm/irq_comm.c. 21 + * 22 + * Authors: 23 + * Yaozu (Eddie) Dong <Eddie.dong@intel.com> 24 + * Alexander Graf <agraf@suse.de> 25 + */ 26 + 27 + #include <linux/kvm_host.h> 28 + #include <linux/slab.h> 29 + #include <linux/export.h> 30 + #include <trace/events/kvm.h> 31 + #include "irq.h" 32 + 33 + bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) 34 + { 35 + struct kvm_irq_ack_notifier *kian; 36 + int gsi; 37 + 38 + rcu_read_lock(); 39 + gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin]; 40 + if (gsi != -1) 41 + hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, 42 + link) 43 + if (kian->gsi == gsi) { 44 + rcu_read_unlock(); 45 + return true; 46 + } 47 + 48 + rcu_read_unlock(); 49 + 50 + return false; 51 + } 52 + EXPORT_SYMBOL_GPL(kvm_irq_has_notifier); 53 + 54 + void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) 55 + { 56 + struct kvm_irq_ack_notifier *kian; 57 + int gsi; 58 + 59 + trace_kvm_ack_irq(irqchip, pin); 60 + 61 + rcu_read_lock(); 62 + gsi = rcu_dereference(kvm->irq_routing)->chip[irqchip][pin]; 63 + if (gsi != -1) 64 + hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, 65 + link) 66 + if (kian->gsi == gsi) 67 + kian->irq_acked(kian); 68 + rcu_read_unlock(); 69 + } 70 + 71 + void kvm_register_irq_ack_notifier(struct kvm *kvm, 72 + struct kvm_irq_ack_notifier *kian) 73 + { 74 + mutex_lock(&kvm->irq_lock); 75 + hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list); 76 + mutex_unlock(&kvm->irq_lock); 77 + #ifdef __KVM_HAVE_IOAPIC 78 + kvm_vcpu_request_scan_ioapic(kvm); 79 + #endif 80 + } 81 + 82 + void kvm_unregister_irq_ack_notifier(struct kvm *kvm, 83 + struct kvm_irq_ack_notifier *kian) 84 + { 85 + mutex_lock(&kvm->irq_lock); 86 + hlist_del_init_rcu(&kian->link); 87 + mutex_unlock(&kvm->irq_lock); 88 + synchronize_rcu(); 89 + #ifdef __KVM_HAVE_IOAPIC 90 + kvm_vcpu_request_scan_ioapic(kvm); 91 + #endif 92 + } 93 + 94 + int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi) 95 + { 96 + struct kvm_kernel_irq_routing_entry route; 97 + 98 + if (!irqchip_in_kernel(kvm) || msi->flags != 0) 99 + return -EINVAL; 100 + 101 + route.msi.address_lo = msi->address_lo; 102 + route.msi.address_hi = msi->address_hi; 103 + route.msi.data = msi->data; 104 + 105 + return kvm_set_msi(&route, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1, false); 106 + } 107 + 108 + /* 109 + * Return value: 110 + * < 0 Interrupt was ignored (masked or not delivered for other reasons) 111 + * = 0 Interrupt was coalesced (previous irq is still pending) 112 + * > 0 Number of CPUs interrupt was delivered to 113 + */ 114 + int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, 115 + bool line_status) 116 + { 117 + struct kvm_kernel_irq_routing_entry *e, irq_set[KVM_NR_IRQCHIPS]; 118 + int ret = -1, i = 0; 119 + struct kvm_irq_routing_table *irq_rt; 120 + 121 + trace_kvm_set_irq(irq, level, irq_source_id); 122 + 123 + /* Not possible to detect if the guest uses the PIC or the 124 + * IOAPIC. So set the bit in both. The guest will ignore 125 + * writes to the unused one. 126 + */ 127 + rcu_read_lock(); 128 + irq_rt = rcu_dereference(kvm->irq_routing); 129 + if (irq < irq_rt->nr_rt_entries) 130 + hlist_for_each_entry(e, &irq_rt->map[irq], link) 131 + irq_set[i++] = *e; 132 + rcu_read_unlock(); 133 + 134 + while(i--) { 135 + int r; 136 + r = irq_set[i].set(&irq_set[i], kvm, irq_source_id, level, 137 + line_status); 138 + if (r < 0) 139 + continue; 140 + 141 + ret = r + ((ret < 0) ? 0 : ret); 142 + } 143 + 144 + return ret; 145 + } 146 + 147 + void kvm_free_irq_routing(struct kvm *kvm) 148 + { 149 + /* Called only during vm destruction. Nobody can use the pointer 150 + at this stage */ 151 + kfree(kvm->irq_routing); 152 + }