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@xxxxxxxxx> --- 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; + +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); -- 1.7.6 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html