diff mbox

[1/4] kvm tools: Use GSI routing

Message ID 1311843715-5464-1-git-send-email-levinsasha928@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Sasha Levin July 28, 2011, 9:01 a.m. UTC
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>
---
 tools/kvm/builtin-run.c     |    3 ++
 tools/kvm/include/kvm/irq.h |    3 ++
 tools/kvm/irq.c             |   75 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 81 insertions(+), 0 deletions(-)

Comments

Pekka Enberg July 28, 2011, 9:27 a.m. UTC | #1
Hi Sasha,

On Thu, Jul 28, 2011 at 12:01 PM, Sasha Levin <levinsasha928@gmail.com> wrote:
> 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>
> ---
>  tools/kvm/builtin-run.c     |    3 ++
>  tools/kvm/include/kvm/irq.h |    3 ++
>  tools/kvm/irq.c             |   75 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 81 insertions(+), 0 deletions(-)
>
> diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
> index 941129c..f9c3e7e 100644
> --- a/tools/kvm/builtin-run.c
> +++ b/tools/kvm/builtin-run.c
> @@ -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>
> @@ -573,6 +574,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->single_step = single_step;
>
>        ioeventfd__init();
> diff --git a/tools/kvm/include/kvm/irq.h b/tools/kvm/include/kvm/irq.h
> index 7a75a0c..2f00b18 100644
> --- a/tools/kvm/include/kvm/irq.h
> +++ b/tools/kvm/include/kvm/irq.h
> @@ -21,4 +21,7 @@ int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line);
>
>  struct rb_node *irq__get_pci_tree(void);
>
> +void irq__init(void);
> +u32 irq__add_msix_route(u32 low, u32 high, u32 data);
> +
>  #endif
> diff --git a/tools/kvm/irq.c b/tools/kvm/irq.c
> index 15f4702..fc5d800 100644
> --- a/tools/kvm/irq.c
> +++ b/tools/kvm/irq.c
> @@ -1,16 +1,47 @@
>  #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;
> +
> +extern struct kvm *kvm;

I'd prefer you actually pass this as an argument to irq__init() and
irq__add_msix_route().

> +
> +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;

EINVAL is more appropriate, I think.

> +
> +       irq_routing->entries[irq_routing->nr++] = (struct kvm_irq_routing_entry) {
> +               .gsi = gsi,
> +               .type = type,
> +               .u.irqchip.irqchip = irqchip,
> +               .u.irqchip.pin = pin,

Please indent the assignments.

> +       };
> +
> +       return 0;
> +}
> +
>  static struct pci_dev *search(struct rb_root *root, u32 id)
>  {
>        struct rb_node *node = root->rb_node;
> @@ -106,6 +137,50 @@ int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
>        return -1;
>  }
>
> +void irq__init(void)
> +{
> +       int i, r;
> +
> +       irq_routing = malloc(sizeof(struct kvm_irq_routing) +
> +                       IRQ_MAX_GSI * sizeof(struct kvm_irq_routing_entry));

We usually die() on out-of-memory. Maybe it doesn't make sense here. Dunno.

> +
> +       /* 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");
> +}
> +
> +u32 irq__add_msix_route(u32 low, u32 high, u32 data)
> +{
> +       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,

Please indent the assignments.

> +       };
> +
> +       if (ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing))
> +               return -1;

How will that work when we have 'u32' as the return value type?

> +
> +       return gsi++;
> +}
> +
>  struct rb_node *irq__get_pci_tree(void)
>  {
>        return rb_first(&pci_tree);
> --
> 1.7.6
>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Cyrill Gorcunov July 28, 2011, 9:43 a.m. UTC | #2
On Thu, Jul 28, 2011 at 12:01:52PM +0300, Sasha Levin wrote:
> 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>
> ---

Other than a few nits the series looks good to me, thanks Sasha!
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/tools/kvm/builtin-run.c b/tools/kvm/builtin-run.c
index 941129c..f9c3e7e 100644
--- a/tools/kvm/builtin-run.c
+++ b/tools/kvm/builtin-run.c
@@ -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>
@@ -573,6 +574,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->single_step = single_step;
 
 	ioeventfd__init();
diff --git a/tools/kvm/include/kvm/irq.h b/tools/kvm/include/kvm/irq.h
index 7a75a0c..2f00b18 100644
--- a/tools/kvm/include/kvm/irq.h
+++ b/tools/kvm/include/kvm/irq.h
@@ -21,4 +21,7 @@  int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line);
 
 struct rb_node *irq__get_pci_tree(void);
 
+void irq__init(void);
+u32 irq__add_msix_route(u32 low, u32 high, u32 data);
+
 #endif
diff --git a/tools/kvm/irq.c b/tools/kvm/irq.c
index 15f4702..fc5d800 100644
--- a/tools/kvm/irq.c
+++ b/tools/kvm/irq.c
@@ -1,16 +1,47 @@ 
 #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;
+
+extern struct kvm *kvm;
+
+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 +137,50 @@  int irq__register_device(u32 dev, u8 *num, u8 *pin, u8 *line)
 	return -1;
 }
 
+void irq__init(void)
+{
+	int i, r;
+
+	irq_routing = malloc(sizeof(struct kvm_irq_routing) +
+			IRQ_MAX_GSI * sizeof(struct kvm_irq_routing_entry));
+
+	/* 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");
+}
+
+u32 irq__add_msix_route(u32 low, u32 high, u32 data)
+{
+	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,
+	};
+
+	if (ioctl(kvm->vm_fd, KVM_SET_GSI_ROUTING, irq_routing))
+		return -1;
+
+	return gsi++;
+}
+
 struct rb_node *irq__get_pci_tree(void)
 {
 	return rb_first(&pci_tree);