1 #include <stdlib.h> 2 #include <sys/ioctl.h> 3 #include <linux/types.h> 4 #include <linux/kvm.h> 5 #include <errno.h> 6 7 #include "kvm/kvm.h" 8 #include "kvm/irq.h" 9 #include "kvm/kvm-arch.h" 10 11 static u8 next_line = KVM_IRQ_OFFSET; 12 static int allocated_gsis = 0; 13 14 int next_gsi; 15 16 struct kvm_irq_routing *irq_routing = NULL; 17 18 int irq__alloc_line(void) 19 { 20 return next_line++; 21 } 22 23 int irq__get_nr_allocated_lines(void) 24 { 25 return next_line - KVM_IRQ_OFFSET; 26 } 27 28 int irq__allocate_routing_entry(void) 29 { 30 size_t table_size = sizeof(struct kvm_irq_routing); 31 size_t old_size = table_size; 32 int nr_entries = 0; 33 34 if (irq_routing) 35 nr_entries = irq_routing->nr; 36 37 if (nr_entries < allocated_gsis) 38 return 0; 39 40 old_size += sizeof(struct kvm_irq_routing_entry) * allocated_gsis; 41 allocated_gsis = ALIGN(nr_entries + 1, 32); 42 table_size += sizeof(struct kvm_irq_routing_entry) * allocated_gsis; 43 irq_routing = realloc(irq_routing, table_size); 44 45 if (irq_routing == NULL) 46 return -ENOMEM; 47 memset((void *)irq_routing + old_size, 0, table_size - old_size); 48 49 irq_routing->nr = nr_entries; 50 irq_routing->flags = 0; 51 52 return 0; 53 } 54 55 static bool check_for_irq_routing(struct kvm *kvm) 56 { 57 static int has_irq_routing = 0; 58 59 if (has_irq_routing == 0) { 60 if (kvm__supports_extension(kvm, KVM_CAP_IRQ_ROUTING)) 61 has_irq_routing = 1; 62 else 63 has_irq_routing = -1; 64 } 65 66 return has_irq_routing > 0; 67 } 68 69 int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg) 70 { 71 int r; 72 73 if (!check_for_irq_routing(kvm)) 74 return -ENXIO; 75 76 r = irq__allocate_routing_entry(); 77 if (r) 78 return r; 79 80 irq_routing->entries[irq_routing->nr++] = 81 (struct kvm_irq_routing_entry) { 82 .gsi = next_gsi, 83 .type = KVM_IRQ_ROUTING_MSI, 84 .u.msi.address_hi = msg->address_hi, 85 .u.msi.address_lo = msg->address_lo, 86 .u.msi.data = msg->data, 87 }; 88 89 r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing); 90 if (r) 91 return r; 92 93 return next_gsi++; 94 } 95 96 int __attribute__((weak)) irq__exit(struct kvm *kvm) 97 { 98 free(irq_routing); 99 return 0; 100 } 101 dev_base_exit(irq__exit); 102