1 #include "kvm/irq.h" 2 #include "kvm/kvm.h" 3 #include "kvm/util.h" 4 5 #include <linux/types.h> 6 #include <linux/rbtree.h> 7 #include <linux/list.h> 8 #include <linux/kvm.h> 9 #include <sys/ioctl.h> 10 11 #include <stddef.h> 12 #include <stdlib.h> 13 14 #define IRQ_MAX_GSI 64 15 #define IRQCHIP_MASTER 0 16 #define IRQCHIP_SLAVE 1 17 #define IRQCHIP_IOAPIC 2 18 19 static u8 next_line = 3; 20 static u8 next_dev = 1; 21 static struct rb_root pci_tree = RB_ROOT; 22 23 /* First 24 GSIs are routed between IRQCHIPs and IOAPICs */ 24 static u32 gsi = 24; 25 26 struct kvm_irq_routing *irq_routing; 27 28 static int irq__add_routing(u32 gsi, u32 type, u32 irqchip, u32 pin) 29 { 30 if (gsi >= IRQ_MAX_GSI) 31 return -ENOSPC; 32 33 irq_routing->entries[irq_routing->nr++] = 34 (struct kvm_irq_routing_entry) { 35 .gsi = gsi, 36 .type = type, 37 .u.irqchip.irqchip = irqchip, 38 .u.irqchip.pin = pin, 39 }; 40 41 return 0; 42 } 43 44 static struct pci_dev *search(struct rb_root *root, u32 id) 45 { 46 struct rb_node *node = root->rb_node; 47 48 while (node) { 49 struct pci_dev *data = container_of(node, struct pci_dev, node); 50 int result; 51 52 result = id - data->id; 53 54 if (result < 0) 55 node = node->rb_left; 56 else if (result > 0) 57 node = node->rb_right; 58 else 59 return data; 60 } 61 return NULL; 62 } 63 64 static int insert(struct rb_root *root, struct pci_dev *data) 65 { 66 struct rb_node **new = &(root->rb_node), *parent = NULL; 67 68 /* Figure out where to put new node */ 69 while (*new) { 70 struct pci_dev *this = container_of(*new, struct pci_dev, node); 71 int result = data->id - this->id; 72 73 parent = *new; 74 if (result < 0) 75 new = &((*new)->rb_left); 76 else if (result > 0) 77 new = &((*new)->rb_right); 78 else 79 return 0; 80 } 81 82 /* Add new node and rebalance tree. */ 83 rb_link_node(&data->node, parent, new); 84 rb_insert_color(&data->node, root); 85 86 return 1; 87 } 88 89 int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line) 90 { 91 struct pci_dev *node; 92 93 node = search(&pci_tree, dev); 94 95 if (!node) { 96 /* We haven't found a node - First device of it's kind */ 97 node = malloc(sizeof(*node)); 98 if (node == NULL) 99 return -1; 100 101 *node = (struct pci_dev) { 102 .id = dev, 103 /* 104 * PCI supports only INTA#,B#,C#,D# per device. 105 * A#,B#,C#,D# are allowed for multifunctional 106 * devices so stick with A# for our single 107 * function devices. 108 */ 109 .pin = 1, 110 }; 111 112 INIT_LIST_HEAD(&node->lines); 113 114 if (insert(&pci_tree, node) != 1) { 115 free(node); 116 return -1; 117 } 118 } 119 120 if (node) { 121 /* This device already has a pin assigned, give out a new line and device id */ 122 struct irq_line *new = malloc(sizeof(*new)); 123 if (new == NULL) 124 return -1; 125 126 new->line = next_line++; 127 *line = new->line; 128 *pin = node->pin; 129 *num = next_dev++; 130 131 list_add(&new->node, &node->lines); 132 133 return 0; 134 } 135 136 return -1; 137 } 138 139 void irq__init(struct kvm *kvm) 140 { 141 int i, r; 142 143 irq_routing = malloc(sizeof(struct kvm_irq_routing) + 144 IRQ_MAX_GSI * sizeof(struct kvm_irq_routing_entry)); 145 if (irq_routing == NULL) 146 die("Failed allocating space for GSI table"); 147 148 /* Hook first 8 GSIs to master IRQCHIP */ 149 for (i = 0; i < 8; i++) 150 irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_MASTER, i); 151 152 /* Hook next 8 GSIs to slave IRQCHIP */ 153 for (i = 8; i < 16; i++) 154 irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_SLAVE, 8-i); 155 156 /* Last but not least, IOAPIC */ 157 for (i = 0; i < 24; i++) { 158 if (i == 0) 159 irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, 2); 160 else 161 irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, i); 162 } 163 164 r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing); 165 if (r) 166 die("Failed setting GSI routes"); 167 } 168 169 int irq__add_msix_route(struct kvm *kvm, u32 low, u32 high, u32 data) 170 { 171 int r; 172 173 irq_routing->entries[irq_routing->nr++] = 174 (struct kvm_irq_routing_entry) { 175 .gsi = gsi, 176 .type = KVM_IRQ_ROUTING_MSI, 177 .u.msi.address_lo = low, 178 .u.msi.address_hi = high, 179 .u.msi.data = data, 180 }; 181 182 r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing); 183 if (r) 184 return r; 185 186 return gsi++; 187 } 188 189 struct rb_node *irq__get_pci_tree(void) 190 { 191 return rb_first(&pci_tree); 192 } 193