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

KVM: Maintain back mapping from irqchip/pin to gsi

Maintain back mapping from irqchip/pin to gsi to speedup
interrupt acknowledgment notifications.

[avi: build fix on non-x86/ia64]

Signed-off-by: Gleb Natapov <gleb@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>

authored by

Gleb Natapov and committed by
Avi Kivity
3e71f88b 46e624b9

+25 -17
+1
arch/ia64/include/asm/kvm.h
··· 60 60 #define KVM_IRQCHIP_PIC_MASTER 0 61 61 #define KVM_IRQCHIP_PIC_SLAVE 1 62 62 #define KVM_IRQCHIP_IOAPIC 2 63 + #define KVM_NR_IRQCHIPS 3 63 64 64 65 #define KVM_CONTEXT_SIZE 8*1024 65 66
+1
arch/x86/include/asm/kvm.h
··· 79 79 #define KVM_IRQCHIP_PIC_MASTER 0 80 80 #define KVM_IRQCHIP_PIC_SLAVE 1 81 81 #define KVM_IRQCHIP_IOAPIC 2 82 + #define KVM_NR_IRQCHIPS 3 82 83 83 84 /* for KVM_GET_REGS and KVM_SET_REGS */ 84 85 struct kvm_regs {
+9
include/linux/kvm_host.h
··· 131 131 struct hlist_node link; 132 132 }; 133 133 134 + #ifdef __KVM_HAVE_IOAPIC 135 + 134 136 struct kvm_irq_routing_table { 137 + int chip[KVM_NR_IRQCHIPS][KVM_IOAPIC_NUM_PINS]; 135 138 struct kvm_kernel_irq_routing_entry *rt_entries; 136 139 u32 nr_rt_entries; 137 140 /* ··· 143 140 */ 144 141 struct hlist_head map[0]; 145 142 }; 143 + 144 + #else 145 + 146 + struct kvm_irq_routing_table {}; 147 + 148 + #endif 146 149 147 150 struct kvm { 148 151 spinlock_t mmu_lock;
+14 -17
virt/kvm/irq_comm.c
··· 175 175 { 176 176 struct kvm_irq_ack_notifier *kian; 177 177 struct hlist_node *n; 178 - unsigned gsi = pin; 179 - int i; 178 + int gsi; 180 179 181 180 trace_kvm_ack_irq(irqchip, pin); 182 181 183 - for (i = 0; i < kvm->irq_routing->nr_rt_entries; i++) { 184 - struct kvm_kernel_irq_routing_entry *e; 185 - e = &kvm->irq_routing->rt_entries[i]; 186 - if (e->type == KVM_IRQ_ROUTING_IRQCHIP && 187 - e->irqchip.irqchip == irqchip && 188 - e->irqchip.pin == pin) { 189 - gsi = e->gsi; 190 - break; 191 - } 192 - } 193 - 194 - hlist_for_each_entry(kian, n, &kvm->arch.irq_ack_notifier_list, link) 195 - if (kian->gsi == gsi) 196 - kian->irq_acked(kian); 182 + gsi = kvm->irq_routing->chip[irqchip][pin]; 183 + if (gsi != -1) 184 + hlist_for_each_entry(kian, n, &kvm->arch.irq_ack_notifier_list, 185 + link) 186 + if (kian->gsi == gsi) 187 + kian->irq_acked(kian); 197 188 } 198 189 199 190 void kvm_register_irq_ack_notifier(struct kvm *kvm, ··· 323 332 } 324 333 e->irqchip.irqchip = ue->u.irqchip.irqchip; 325 334 e->irqchip.pin = ue->u.irqchip.pin + delta; 335 + if (e->irqchip.pin >= KVM_IOAPIC_NUM_PINS) 336 + goto out; 337 + rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi; 326 338 break; 327 339 case KVM_IRQ_ROUTING_MSI: 328 340 e->set = kvm_set_msi; ··· 350 356 unsigned flags) 351 357 { 352 358 struct kvm_irq_routing_table *new, *old; 353 - u32 i, nr_rt_entries = 0; 359 + u32 i, j, nr_rt_entries = 0; 354 360 int r; 355 361 356 362 for (i = 0; i < nr; ++i) { ··· 371 377 new->rt_entries = (void *)&new->map[nr_rt_entries]; 372 378 373 379 new->nr_rt_entries = nr_rt_entries; 380 + for (i = 0; i < 3; i++) 381 + for (j = 0; j < KVM_IOAPIC_NUM_PINS; j++) 382 + new->chip[i][j] = -1; 374 383 375 384 for (i = 0; i < nr; ++i) { 376 385 r = -EINVAL;