@@ -10,22 +10,8 @@
struct kvm;
-struct irq_line {
- u8 line;
- struct list_head node;
-};
-
-struct pci_dev {
- struct rb_node node;
- u32 id;
- u8 pin;
- struct list_head lines;
-};
-
int irq__register_device(u32 dev, u8 *line);
-struct rb_node *irq__get_pci_tree(void);
-
int irq__init(struct kvm *kvm);
int irq__exit(struct kvm *kvm);
int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg);
@@ -17,7 +17,6 @@
#define IRQCHIP_IOAPIC 2
static u8 next_line = 5;
-static struct rb_root pci_tree = RB_ROOT;
/* First 24 GSIs are routed between IRQCHIPs and IOAPICs */
static u32 gsi = 24;
@@ -40,92 +39,10 @@ static int irq__add_routing(u32 gsi, u32 type, u32 irqchip, u32 pin)
return 0;
}
-static struct pci_dev *search(struct rb_root *root, u32 id)
-{
- struct rb_node *node = root->rb_node;
-
- while (node) {
- struct pci_dev *data = rb_entry(node, struct pci_dev, node);
- int result;
-
- result = id - data->id;
-
- if (result < 0)
- node = node->rb_left;
- else if (result > 0)
- node = node->rb_right;
- else
- return data;
- }
- return NULL;
-}
-
-static int insert(struct rb_root *root, struct pci_dev *data)
-{
- struct rb_node **new = &(root->rb_node), *parent = NULL;
-
- /* Figure out where to put new node */
- while (*new) {
- struct pci_dev *this = container_of(*new, struct pci_dev, node);
- int result = data->id - this->id;
-
- parent = *new;
- if (result < 0)
- new = &((*new)->rb_left);
- else if (result > 0)
- new = &((*new)->rb_right);
- else
- return -EEXIST;
- }
-
- /* Add new node and rebalance tree. */
- rb_link_node(&data->node, parent, new);
- rb_insert_color(&data->node, root);
-
- return 0;
-}
-
int irq__register_device(u32 dev, u8 *line)
{
- struct pci_dev *node;
- int r;
-
- node = search(&pci_tree, dev);
-
- if (!node) {
- /* We haven't found a node - First device of it's kind */
- node = malloc(sizeof(*node));
- if (node == NULL)
- return -ENOMEM;
-
- *node = (struct pci_dev) {
- .id = dev,
- };
-
- INIT_LIST_HEAD(&node->lines);
-
- r = insert(&pci_tree, node);
- if (r) {
- free(node);
- return r;
- }
- }
-
- if (node) {
- /* This device already has a pin assigned, give out a new line and device id */
- struct irq_line *new = malloc(sizeof(*new));
- if (new == NULL)
- return -ENOMEM;
-
- new->line = next_line++;
- *line = new->line;
-
- list_add(&new->node, &node->lines);
-
- return 0;
- }
-
- return -EFAULT;
+ *line = next_line++;
+ return 0;
}
int irq__init(struct kvm *kvm)
@@ -166,24 +83,7 @@ dev_base_init(irq__init);
int irq__exit(struct kvm *kvm)
{
- struct rb_node *ent;
-
free(irq_routing);
-
- while ((ent = rb_first(&pci_tree))) {
- struct pci_dev *dev;
- struct irq_line *line;
-
- dev = rb_entry(ent, struct pci_dev, node);
- while (!list_empty(&dev->lines)) {
- line = list_first_entry(&dev->lines, struct irq_line, node);
- list_del(&line->node);
- free(line);
- }
- rb_erase(&dev->node, &pci_tree);
- free(dev);
- }
-
return 0;
}
dev_base_exit(irq__exit);
@@ -207,8 +107,3 @@ int irq__add_msix_route(struct kvm *kvm, struct msi_msg *msg)
return gsi++;
}
-
-struct rb_node *irq__get_pci_tree(void)
-{
- return rb_first(&pci_tree);
-}
@@ -3,7 +3,8 @@
#include "kvm/apic.h"
#include "kvm/mptable.h"
#include "kvm/util.h"
-#include "kvm/irq.h"
+#include "kvm/devices.h"
+#include "kvm/pci.h"
#include <linux/kernel.h>
#include <string.h>
@@ -80,7 +81,7 @@ int mptable__init(struct kvm *kvm)
struct mpc_bus *mpc_bus;
struct mpc_ioapic *mpc_ioapic;
struct mpc_intsrc *mpc_intsrc;
- struct rb_node *pci_tree;
+ struct device_header *dev_hdr;
const int pcibusid = 0;
const int isabusid = 1;
@@ -171,31 +172,21 @@ int mptable__init(struct kvm *kvm)
/*
* IRQ sources.
- *
- * FIXME: Same issue as with buses. We definitely
- * need kind of collector routine which enumerate
- * resources used first and pass them here.
- * At moment we know we have only virtio block device
- * and virtio console but this is g00berfish.
- *
* Also note we use PCI irqs here, no for ISA bus yet.
*/
- for (pci_tree = irq__get_pci_tree(); pci_tree; pci_tree = rb_next(pci_tree)) {
- struct pci_dev *dev = rb_entry(pci_tree, struct pci_dev, node);
- struct irq_line *irq_line;
+ dev_hdr = device__first_dev(DEVICE_BUS_PCI);
+ while (dev_hdr) {
+ unsigned char srcbusirq;
+ struct pci_device_header *pci_hdr = dev_hdr->data;
- list_for_each_entry(irq_line, &dev->lines, node) {
- unsigned char srcbusirq;
+ srcbusirq = (pci_hdr->subsys_id << 2) | (pci_hdr->irq_pin - 1);
+ mpc_intsrc = last_addr;
+ mptable_add_irq_src(mpc_intsrc, pcibusid, srcbusirq, ioapicid, pci_hdr->irq_line);
- srcbusirq = (dev->id << 2) | (dev->pin - 1);
-
- mpc_intsrc = last_addr;
-
- mptable_add_irq_src(mpc_intsrc, pcibusid, srcbusirq, ioapicid, irq_line->line);
- last_addr = (void *)&mpc_intsrc[1];
- nentries++;
- }
+ last_addr = (void *)&mpc_intsrc[dev_hdr->dev_num];
+ nentries++;
+ dev_hdr = device__next_dev(dev_hdr);
}
/*
The x86 code keeps its own rbtree of PCI devices in order to allocate interrupts. However, this functionality can be moved into the generic PCI device tree and be reused by other architectures. This patch removes the x86 tree and reworks the ACPI mptable generation to use the PCI device tree for enumerating the bus. Signed-off-by: Will Deacon <will.deacon@arm.com> --- tools/kvm/include/kvm/irq.h | 14 ------ tools/kvm/x86/irq.c | 109 +------------------------------------------- tools/kvm/x86/mptable.c | 35 ++++++-------- 3 files changed, 15 insertions(+), 143 deletions(-)