]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm tools: Use GSI routing
authorSasha Levin <levinsasha928@gmail.com>
Thu, 28 Jul 2011 17:56:18 +0000 (20:56 +0300)
committerPekka Enberg <penberg@kernel.org>
Thu, 28 Jul 2011 17:58:21 +0000 (20:58 +0300)
Map GSIs manually when starting the guest.
This will allow us mapping new GSIs for MSIX in the future.

Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/builtin-run.c
tools/kvm/include/kvm/irq.h
tools/kvm/irq.c

index 02c066bc43e314700563a5fdc70bac9ce2ea9b94..2e04265809822e0ebe66eec4fcec2b533045de08 100644 (file)
@@ -35,6 +35,7 @@
 #include <kvm/vnc.h>
 #include <kvm/sdl.h>
 #include <kvm/framebuffer.h>
+#include <kvm/irq.h>
 
 /* header files for gitish interface  */
 #include <kvm/builtin-run.h>
@@ -574,6 +575,8 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix)
 
        kvm = kvm__init(kvm_dev, ram_size, guest_name);
 
+       irq__init(kvm);
+
        kvm->single_step = single_step;
 
        ioeventfd__init();
index 7a75a0c537233a6e9081e6afec0c39004395188d..401bee90f11947e13f37a639cd2f65417d873001 100644 (file)
@@ -5,6 +5,8 @@
 #include <linux/rbtree.h>
 #include <linux/list.h>
 
+struct kvm;
+
 struct irq_line {
        u8                      line;
        struct list_head        node;
@@ -21,4 +23,7 @@ int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line);
 
 struct rb_node *irq__get_pci_tree(void);
 
+void irq__init(struct kvm *kvm);
+int irq__add_msix_route(struct kvm *kvm, u32 low, u32 high, u32 data);
+
 #endif
index 15f4702b850616ada24e85d055b2c25c2ad2eb91..85e2238a45e7f4f76a7612742f767aed2493bf06 100644 (file)
@@ -1,16 +1,46 @@
 #include "kvm/irq.h"
+#include "kvm/kvm.h"
+#include "kvm/util.h"
 
 #include <linux/types.h>
 #include <linux/rbtree.h>
 #include <linux/list.h>
+#include <linux/kvm.h>
+#include <sys/ioctl.h>
 
 #include <stddef.h>
 #include <stdlib.h>
 
+#define IRQ_MAX_GSI                    64
+#define IRQCHIP_MASTER                 0
+#define IRQCHIP_SLAVE                  1
+#define IRQCHIP_IOAPIC                 2
+
 static u8              next_line       = 3;
 static u8              next_dev        = 1;
 static struct rb_root  pci_tree        = RB_ROOT;
 
+/* First 24 GSIs are routed between IRQCHIPs and IOAPICs */
+static u32 gsi = 24;
+
+struct kvm_irq_routing *irq_routing;
+
+static int irq__add_routing(u32 gsi, u32 type, u32 irqchip, u32 pin)
+{
+       if (gsi >= IRQ_MAX_GSI)
+               return -ENOSPC;
+
+       irq_routing->entries[irq_routing->nr++] =
+               (struct kvm_irq_routing_entry) {
+                       .gsi = gsi,
+                       .type = type,
+                       .u.irqchip.irqchip = irqchip,
+                       .u.irqchip.pin = pin,
+               };
+
+       return 0;
+}
+
 static struct pci_dev *search(struct rb_root *root, u32 id)
 {
        struct rb_node *node = root->rb_node;
@@ -106,6 +136,56 @@ int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
        return -1;
 }
 
+void irq__init(struct kvm *kvm)
+{
+       int i, r;
+
+       irq_routing = malloc(sizeof(struct kvm_irq_routing) +
+                       IRQ_MAX_GSI * sizeof(struct kvm_irq_routing_entry));
+       if (irq_routing == NULL)
+               die("Failed allocating space for GSI table");
+
+       /* Hook first 8 GSIs to master IRQCHIP */
+       for (i = 0; i < 8; i++)
+               irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_MASTER, i);
+
+       /* Hook next 8 GSIs to slave IRQCHIP */
+       for (i = 8; i < 16; i++)
+               irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_SLAVE, 8-i);
+
+       /* Last but not least, IOAPIC */
+       for (i = 0; i < 24; i++) {
+               if (i == 0)
+                       irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, 2);
+               else
+                       irq__add_routing(i, KVM_IRQ_ROUTING_IRQCHIP, IRQCHIP_IOAPIC, i);
+       }
+
+       r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
+       if (r)
+               die("Failed setting GSI routes");
+}
+
+int irq__add_msix_route(struct kvm *kvm, u32 low, u32 high, u32 data)
+{
+       int r;
+
+       irq_routing->entries[irq_routing->nr++] =
+               (struct kvm_irq_routing_entry) {
+                       .gsi = gsi,
+                       .type = KVM_IRQ_ROUTING_MSI,
+                       .u.msi.address_lo = low,
+                       .u.msi.address_hi = high,
+                       .u.msi.data = data,
+               };
+
+       r = ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing);
+       if (r)
+               return r;
+
+       return gsi++;
+}
+
 struct rb_node *irq__get_pci_tree(void)
 {
        return rb_first(&pci_tree);