Implement the routing of PC's interrupt gpio to intc, and
retrieve the gsi.

Signed-off-by: Liu Ping Fan <pingf...@linux.vnet.ibm.com>
---
 hw/core/qdev.c         |  8 ++++++++
 hw/i386/kvm/i8259.c    |  8 +++++++-
 hw/i386/kvm/ioapic.c   | 21 ++++++++++++++++++++-
 hw/i386/pc_q35.c       |  4 ++--
 include/hw/qdev-core.h |  2 ++
 include/sysemu/kvm.h   |  1 +
 6 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 758de9f..63605d1 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -312,6 +312,14 @@ void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler 
handler, int n)
     dev->num_gpio_in += n;
 }
 
+void qdev_init_gpio_in_2(DeviceState *dev, qemu_irq_handler handler,
+        qemu_irq_route route, int n)
+{
+    dev->gpio_in = qemu_extend_irqs_2(dev->gpio_in, dev->num_gpio_in, handler,
+                                        route, dev, n);
+    dev->num_gpio_in += n;
+}
+
 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n)
 {
     assert(dev->num_gpio_out == 0);
diff --git a/hw/i386/kvm/i8259.c b/hw/i386/kvm/i8259.c
index 53e3ca8..1193b54 100644
--- a/hw/i386/kvm/i8259.c
+++ b/hw/i386/kvm/i8259.c
@@ -106,6 +106,11 @@ static void kvm_pic_reset(DeviceState *dev)
     kvm_pic_put(s);
 }
 
+static int kvm_pic_route_gsi(void *opaque, int irq)
+{
+    return irq;
+}
+
 static void kvm_pic_set_irq(void *opaque, int irq, int level)
 {
     int delivered;
@@ -130,7 +135,8 @@ qemu_irq *kvm_i8259_init(ISABus *bus)
     i8259_init_chip(TYPE_KVM_I8259, bus, true);
     i8259_init_chip(TYPE_KVM_I8259, bus, false);
 
-    return qemu_allocate_irqs(kvm_pic_set_irq, NULL, ISA_NUM_IRQS);
+    return qemu_extend_irqs_2(NULL, 0, kvm_pic_set_irq, kvm_pic_route_gsi,
+                NULL, ISA_NUM_IRQS);
 }
 
 static void kvm_i8259_class_init(ObjectClass *klass, void *data)
diff --git a/hw/i386/kvm/ioapic.c b/hw/i386/kvm/ioapic.c
index f11a540..1e6ff0b 100644
--- a/hw/i386/kvm/ioapic.c
+++ b/hw/i386/kvm/ioapic.c
@@ -44,6 +44,19 @@ void kvm_pc_setup_irq_routing(bool pci_enabled)
     }
 }
 
+int kvm_pc_route_gsi(void *opaque, int n)
+{
+    GSIState *s = opaque;
+    int gsi;
+
+    if (n < ISA_NUM_IRQS) {
+        gsi = qemu_irq_route_gsi(s->i8259_irq[n]);
+    } else {
+        gsi = qemu_irq_route_gsi(s->ioapic_irq[n]);
+    }
+    return gsi;
+}
+
 void kvm_pc_gsi_handler(void *opaque, int n, int level)
 {
     GSIState *s = opaque;
@@ -127,11 +140,17 @@ static void kvm_ioapic_set_irq(void *opaque, int irq, int 
level)
     apic_report_irq_delivered(delivered);
 }
 
+static int kvm_ioapic_route_irq(void *opaque, int irq)
+{
+    return irq;
+}
+
 static void kvm_ioapic_init(IOAPICCommonState *s, int instance_no)
 {
     memory_region_init_reservation(&s->io_memory, NULL, "kvm-ioapic", 0x1000);
 
-    qdev_init_gpio_in(DEVICE(s), kvm_ioapic_set_irq, IOAPIC_NUM_PINS);
+    qdev_init_gpio_in_2(DEVICE(s), kvm_ioapic_set_irq, kvm_ioapic_route_irq,
+        IOAPIC_NUM_PINS);
 }
 
 static Property kvm_ioapic_properties[] = {
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 198c785..df1deb3 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -120,8 +120,8 @@ static void pc_q35_init(QEMUMachineInitArgs *args)
     gsi_state = g_malloc0(sizeof(*gsi_state));
     if (kvm_irqchip_in_kernel()) {
         kvm_pc_setup_irq_routing(pci_enabled);
-        gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state,
-                                 GSI_NUM_PINS);
+        gsi = qemu_extend_irqs_2(NULL, 0, kvm_pc_gsi_handler,
+                                kvm_pc_route_gsi, gsi_state, GSI_NUM_PINS);
     } else {
         gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS);
     }
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 46972f4..4b8eb35 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -252,6 +252,8 @@ BusState *qdev_get_child_bus(DeviceState *dev, const char 
*name);
 /* Register device properties.  */
 /* GPIO inputs also double as IRQ sinks.  */
 void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
+void qdev_init_gpio_in_2(DeviceState *dev, qemu_irq_handler handler,
+        qemu_irq_route route, int n);
 void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
 
 BusState *qdev_get_parent_bus(DeviceState *dev);
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 8e76685..47cc012 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -312,6 +312,7 @@ void kvm_irqchip_release_virq(KVMState *s, int virq);
 int kvm_irqchip_add_irqfd_notifier(KVMState *s, EventNotifier *n,
                                    EventNotifier *rn, int virq);
 int kvm_irqchip_remove_irqfd_notifier(KVMState *s, EventNotifier *n, int virq);
+int kvm_pc_route_gsi(void *opaque, int n);
 void kvm_pc_gsi_handler(void *opaque, int n, int level);
 void kvm_pc_setup_irq_routing(bool pci_enabled);
 void kvm_init_irq_routing(KVMState *s);
-- 
1.8.1.4


Reply via email to