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 static bool update_data(u32 *ptr, u32 newdata) 97 { 98 if (*ptr == newdata) 99 return false; 100 101 *ptr = newdata; 102 return true; 103 } 104 105 void irq__update_msix_route(struct kvm *kvm, u32 gsi, struct msi_msg *msg) 106 { 107 struct kvm_irq_routing_msi *entry; 108 unsigned int i; 109 bool changed; 110 111 for (i = 0; i < irq_routing->nr; i++) 112 if (gsi == irq_routing->entries[i].gsi) 113 break; 114 if (i == irq_routing->nr) 115 return; 116 117 entry = &irq_routing->entries[i].u.msi; 118 119 changed = update_data(&entry->address_hi, msg->address_hi); 120 changed |= update_data(&entry->address_lo, msg->address_lo); 121 changed |= update_data(&entry->data, msg->data); 122 123 if (!changed) 124 return; 125 126 if (ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing) == -1) 127 die_perror("KVM_SET_GSI_ROUTING"); 128 } 129 130 int __attribute__((weak)) irq__exit(struct kvm *kvm) 131 { 132 free(irq_routing); 133 return 0; 134 } 135 dev_base_exit(irq__exit); 136