The discovered bit in PGCCSR register indicates if the device has been
[linux-2.6/next.git] / tools / kvm / irq.c
blobe35bf1863cce1264d0ffc791afd35495cfe04df5
1 #include "kvm/irq.h"
2 #include "kvm/kvm.h"
3 #include "kvm/util.h"
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>
11 #include <stddef.h>
12 #include <stdlib.h>
14 #define IRQ_MAX_GSI 64
15 #define IRQCHIP_MASTER 0
16 #define IRQCHIP_SLAVE 1
17 #define IRQCHIP_IOAPIC 2
19 static u8 next_line = 3;
20 static u8 next_dev = 1;
21 static struct rb_root pci_tree = RB_ROOT;
23 /* First 24 GSIs are routed between IRQCHIPs and IOAPICs */
24 static u32 gsi = 24;
26 struct kvm_irq_routing *irq_routing;
28 static int irq__add_routing(u32 gsi, u32 type, u32 irqchip, u32 pin)
30 if (gsi >= IRQ_MAX_GSI)
31 return -ENOSPC;
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,
41 return 0;
44 static struct pci_dev *search(struct rb_root *root, u32 id)
46 struct rb_node *node = root->rb_node;
48 while (node) {
49 struct pci_dev *data = container_of(node, struct pci_dev, node);
50 int result;
52 result = id - data->id;
54 if (result < 0)
55 node = node->rb_left;
56 else if (result > 0)
57 node = node->rb_right;
58 else
59 return data;
61 return NULL;
64 static int insert(struct rb_root *root, struct pci_dev *data)
66 struct rb_node **new = &(root->rb_node), *parent = NULL;
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;
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;
82 /* Add new node and rebalance tree. */
83 rb_link_node(&data->node, parent, new);
84 rb_insert_color(&data->node, root);
86 return 1;
89 int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
91 struct pci_dev *node;
93 node = search(&pci_tree, dev);
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;
101 *node = (struct pci_dev) {
102 .id = dev,
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.
109 .pin = 1,
112 INIT_LIST_HEAD(&node->lines);
114 if (insert(&pci_tree, node) != 1) {
115 free(node);
116 return -1;
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;
126 new->line = next_line++;
127 *line = new->line;
128 *pin = node->pin;
129 *num = next_dev++;
131 list_add(&new->node, &node->lines);
133 return 0;
136 return -1;
139 void irq__init(struct kvm *kvm)
141 int i, r;
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");
148 /* Hook first 8 GSIs to master IRQCHIP */
149 for (i = 0; i < 8; i++)
150 if (i != 2)
151 irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_MASTER, i);
153 /* Hook next 8 GSIs to slave IRQCHIP */
154 for (i = 8; i < 16; i++)
155 irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_SLAVE, i - 8);
157 /* Last but not least, IOAPIC */
158 for (i = 0; i < 24; i++) {
159 if (i == 0)
160 irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, 2);
161 else if (i != 2)
162 irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, i);
165 r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
166 if (r)
167 die("Failed setting GSI routes");
170 int irq__add_msix_route(struct kvm *kvm, u32 low, u32 high, u32 data)
172 int r;
174 irq_routing->entries[irq_routing->nr++] =
175 (struct kvm_irq_routing_entry) {
176 .gsi = gsi,
177 .type = KVM_IRQ_ROUTING_MSI,
178 .u.msi.address_lo = low,
179 .u.msi.address_hi = high,
180 .u.msi.data = data,
183 r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
184 if (r)
185 return r;
187 return gsi++;
190 struct rb_node *irq__get_pci_tree(void)
192 return rb_first(&pci_tree);