[PATCH] provide a kvm-free pic implementation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch separates all i8259 specific kvm implementation
in separate functions. This way, qemu can have an i8259 device
free from any kvm interference. kvm can have a simpler code path
(we may even be able to compile out qemu's pic in the future if
we want to), and everybody gets happy.

Signed-off-by: Glauber Costa <glommer@xxxxxxxxxx>
---
 hw/i8259.c |  210 ++++++++++++++++++++++++++++++++++++------------------------
 hw/pc.c    |    7 ++-
 hw/pc.h    |    1 +
 3 files changed, 134 insertions(+), 84 deletions(-)

diff --git a/hw/i8259.c b/hw/i8259.c
index bfc7fd9..132f294 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -185,16 +185,6 @@ int64_t irq_time[16];
 static void i8259_set_irq(void *opaque, int irq, int level)
 {
     PicState2 *s = opaque;
-#ifdef KVM_CAP_IRQCHIP
-    if (kvm_enabled()) {
-        int pic_ret;
-        if (kvm_set_irq(irq, level, &pic_ret)) {
-            if (pic_ret != 0)
-                apic_set_irq_delivered();
-            return;
-        }
-    }
-#endif
 #if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
     if (level != irq_level[irq]) {
 #if defined(DEBUG_PIC)
@@ -478,77 +468,10 @@ static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
     return s->elcr;
 }
 
-static void kvm_kernel_pic_save_to_user(PicState *s)
-{
-#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386)
-    struct kvm_irqchip chip;
-    struct kvm_pic_state *kpic;
-
-    chip.chip_id = (&s->pics_state->pics[0] == s) ?
-                   KVM_IRQCHIP_PIC_MASTER :
-                   KVM_IRQCHIP_PIC_SLAVE;
-    kvm_get_irqchip(kvm_context, &chip);
-    kpic = &chip.chip.pic;
-
-    s->last_irr = kpic->last_irr;
-    s->irr = kpic->irr;
-    s->imr = kpic->imr;
-    s->isr = kpic->isr;
-    s->priority_add = kpic->priority_add;
-    s->irq_base = kpic->irq_base;
-    s->read_reg_select = kpic->read_reg_select;
-    s->poll = kpic->poll;
-    s->special_mask = kpic->special_mask;
-    s->init_state = kpic->init_state;
-    s->auto_eoi = kpic->auto_eoi;
-    s->rotate_on_auto_eoi = kpic->rotate_on_auto_eoi;
-    s->special_fully_nested_mode = kpic->special_fully_nested_mode;
-    s->init4 = kpic->init4;
-    s->elcr = kpic->elcr;
-    s->elcr_mask = kpic->elcr_mask;
-#endif
-}
-
-static void kvm_kernel_pic_load_from_user(PicState *s)
-{
-#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386)
-    struct kvm_irqchip chip;
-    struct kvm_pic_state *kpic;
-
-    chip.chip_id = (&s->pics_state->pics[0] == s) ?
-                   KVM_IRQCHIP_PIC_MASTER :
-                   KVM_IRQCHIP_PIC_SLAVE;
-    kpic = &chip.chip.pic;
-
-    kpic->last_irr = s->last_irr;
-    kpic->irr = s->irr;
-    kpic->imr = s->imr;
-    kpic->isr = s->isr;
-    kpic->priority_add = s->priority_add;
-    kpic->irq_base = s->irq_base;
-    kpic->read_reg_select = s->read_reg_select;
-    kpic->poll = s->poll;
-    kpic->special_mask = s->special_mask;
-    kpic->init_state = s->init_state;
-    kpic->auto_eoi = s->auto_eoi;
-    kpic->rotate_on_auto_eoi = s->rotate_on_auto_eoi;
-    kpic->special_fully_nested_mode = s->special_fully_nested_mode;
-    kpic->init4 = s->init4;
-    kpic->elcr = s->elcr;
-    kpic->elcr_mask = s->elcr_mask;
-
-    kvm_set_irqchip(kvm_context, &chip);
-#endif
-}
-
-static void pic_save(QEMUFile *f, void *opaque)
+static void pic_save_common(QEMUFile *f, void *opaque)
 {
     PicState *s = opaque;
 
-    if (kvm_enabled() && qemu_kvm_irqchip_in_kernel()) {
-        kvm_kernel_pic_save_to_user(s);
-    }
-
     qemu_put_8s(f, &s->last_irr);
     qemu_put_8s(f, &s->irr);
     qemu_put_8s(f, &s->imr);
@@ -567,7 +490,12 @@ static void pic_save(QEMUFile *f, void *opaque)
     qemu_put_8s(f, &s->elcr);
 }
 
-static int pic_load(QEMUFile *f, void *opaque, int version_id)
+static void pic_save(QEMUFile *f, void *opaque)
+{
+    pic_save_common(f, opaque);
+}
+
+static int pic_load_common(QEMUFile *f, void *opaque, int version_id)
 {
     PicState *s = opaque;
 
@@ -591,13 +519,14 @@ static int pic_load(QEMUFile *f, void *opaque, int version_id)
     qemu_get_8s(f, &s->single_mode);
     qemu_get_8s(f, &s->elcr);
 
-    if (kvm_enabled() && qemu_kvm_irqchip_in_kernel()) {
-        kvm_kernel_pic_load_from_user(s);
-    }
-
     return 0;
 }
 
+static int pic_load(QEMUFile *f, void *opaque, int version_id)
+{
+    return pic_load_common(f, opaque, version_id);
+}
+
 /* XXX: add generic master/slave system */
 static void pic_init1(int io_addr, int elcr_addr, PicState *s)
 {
@@ -668,3 +597,118 @@ void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func,
     s->alt_irq_func = alt_irq_func;
     s->alt_irq_opaque = alt_irq_opaque;
 }
+
+#ifdef KVM_CAP_IRQCHIP
+static void kvm_kernel_pic_save_to_user(PicState *s)
+{
+#if defined(TARGET_I386)
+    struct kvm_irqchip chip;
+    struct kvm_pic_state *kpic;
+
+    chip.chip_id = (&s->pics_state->pics[0] == s) ?
+                   KVM_IRQCHIP_PIC_MASTER :
+                   KVM_IRQCHIP_PIC_SLAVE;
+    kvm_get_irqchip(kvm_context, &chip);
+    kpic = &chip.chip.pic;
+
+    s->last_irr = kpic->last_irr;
+    s->irr = kpic->irr;
+    s->imr = kpic->imr;
+    s->isr = kpic->isr;
+    s->priority_add = kpic->priority_add;
+    s->irq_base = kpic->irq_base;
+    s->read_reg_select = kpic->read_reg_select;
+    s->poll = kpic->poll;
+    s->special_mask = kpic->special_mask;
+    s->init_state = kpic->init_state;
+    s->auto_eoi = kpic->auto_eoi;
+    s->rotate_on_auto_eoi = kpic->rotate_on_auto_eoi;
+    s->special_fully_nested_mode = kpic->special_fully_nested_mode;
+    s->init4 = kpic->init4;
+    s->elcr = kpic->elcr;
+    s->elcr_mask = kpic->elcr_mask;
+#endif
+}
+
+static void kvm_kernel_pic_load_from_user(PicState *s)
+{
+#if defined(TARGET_I386)
+    struct kvm_irqchip chip;
+    struct kvm_pic_state *kpic;
+
+    chip.chip_id = (&s->pics_state->pics[0] == s) ?
+                   KVM_IRQCHIP_PIC_MASTER :
+                   KVM_IRQCHIP_PIC_SLAVE;
+    kpic = &chip.chip.pic;
+
+    kpic->last_irr = s->last_irr;
+    kpic->irr = s->irr;
+    kpic->imr = s->imr;
+    kpic->isr = s->isr;
+    kpic->priority_add = s->priority_add;
+    kpic->irq_base = s->irq_base;
+    kpic->read_reg_select = s->read_reg_select;
+    kpic->poll = s->poll;
+    kpic->special_mask = s->special_mask;
+    kpic->init_state = s->init_state;
+    kpic->auto_eoi = s->auto_eoi;
+    kpic->rotate_on_auto_eoi = s->rotate_on_auto_eoi;
+    kpic->special_fully_nested_mode = s->special_fully_nested_mode;
+    kpic->init4 = s->init4;
+    kpic->elcr = s->elcr;
+    kpic->elcr_mask = s->elcr_mask;
+
+    kvm_set_irqchip(kvm_context, &chip);
+#endif
+}
+
+static void kvm_i8259_set_irq(void *opaque, int irq, int level)
+{
+    int pic_ret;
+    if (kvm_set_irq(irq, level, &pic_ret)) {
+        if (pic_ret != 0)
+            apic_set_irq_delivered();
+        return;
+    }
+}
+
+static void kvm_pic_save(QEMUFile *f, void *opaque)
+{
+    PicState *s = opaque;
+
+    kvm_kernel_pic_save_to_user(s);
+    pic_save_common(f, opaque);
+}
+
+static int kvm_pic_load(QEMUFile *f, void *opaque, int version_id)
+{
+    PicState *s = opaque;
+    int r = pic_load_common(f, s, version_id);
+    if (r == 0)
+        kvm_kernel_pic_load_from_user(s);
+    return r;
+}
+
+static void kvm_pic_init1(int io_addr, PicState *s)
+{
+    register_savevm("i8259", io_addr, 1, kvm_pic_save, kvm_pic_load, s);
+    qemu_register_reset(pic_reset, 0, s);
+}
+
+qemu_irq *kvm_i8259_init(qemu_irq parent_irq)
+{
+    PicState2 *s;
+
+    s = qemu_mallocz(sizeof(PicState2));
+
+    kvm_pic_init1(0x20, &s->pics[0]);
+    kvm_pic_init1(0xa0, &s->pics[1]);
+    s->parent_irq = parent_irq;
+    s->pics[0].pics_state = s;
+    s->pics[1].pics_state = s;
+    isa_pic = s;
+    return qemu_allocate_irqs(kvm_i8259_set_irq, s, 16);
+}
+#endif
+
+
diff --git a/hw/pc.c b/hw/pc.c
index 077187b..66f4635 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -990,7 +990,12 @@ static void pc_init1(ram_addr_t ram_size,
     bochs_bios_init();
 
     cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
-    i8259 = i8259_init(cpu_irq[0]);
+#ifdef KVM_CAP_IRQCHIP
+    if (kvm_enabled() && qemu_kvm_irqchip_in_kernel()) {
+        i8259 = kvm_i8259_init(cpu_irq[0]);
+    } else
+#endif
+        i8259 = i8259_init(cpu_irq[0]);
     ferr_irq = i8259[13];
 
     if (pci_enabled) {
diff --git a/hw/pc.h b/hw/pc.h
index 5be2d84..3af22f2 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -32,6 +32,7 @@ extern PicState2 *isa_pic;
 void pic_set_irq(int irq, int level);
 void pic_set_irq_new(void *opaque, int irq, int level);
 qemu_irq *i8259_init(qemu_irq parent_irq);
+qemu_irq *kvm_i8259_init(qemu_irq parent_irq);
 void pic_set_alt_irq_func(PicState2 *s, SetIRQFunc *alt_irq_func,
                           void *alt_irq_opaque);
 int pic_read_irq(PicState2 *s);
-- 
1.5.6.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

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux