qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 4/6] provide in-kernel i8259 chip


From: Glauber Costa
Subject: [Qemu-devel] [PATCH 4/6] provide in-kernel i8259 chip
Date: Mon, 28 Sep 2009 18:15:15 -0300

This patch provides kvm with an in-kernel i8259 chip. We are currently not 
enabling it.
The code is heavily based on what's in qemu-kvm.git.

Signed-off-by: Glauber Costa <address@hidden>
---
 hw/i8259.c |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pc.h    |    1 +
 kvm-all.c  |   24 ++++++++++++++
 kvm.h      |    2 +
 4 files changed, 130 insertions(+), 0 deletions(-)

diff --git a/hw/i8259.c b/hw/i8259.c
index 3de22e3..31524f5 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -26,6 +26,7 @@
 #include "isa.h"
 #include "monitor.h"
 #include "qemu-timer.h"
+#include "kvm.h"
 
 /* debug PIC */
 //#define DEBUG_PIC
@@ -446,9 +447,77 @@ static uint32_t elcr_ioport_read(void *opaque, uint32_t 
addr1)
     return s->elcr;
 }
 
+static int kvm_kernel_pic_load_from_user(void *opaque)
+{
+#if defined(TARGET_I386)
+    PicState *s = (void *)opaque;
+    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(&chip);
+#endif
+    return 0;
+}
+
+static void kvm_kernel_pic_save_to_user(const void *opaque)
+{
+#if defined(TARGET_I386)
+    PicState *s = (void *)opaque;
+    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(&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 const VMStateDescription vmstate_pic = {
     .name = "i8259",
     .version_id = 1,
+    .pre_save = kvm_kernel_pic_save_to_user,
+    .post_load = kvm_kernel_pic_load_from_user,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
     .fields      = (VMStateField []) {
@@ -535,3 +604,37 @@ qemu_irq *i8259_init(qemu_irq parent_irq)
     isa_pic = s;
     return qemu_allocate_irqs(i8259_set_irq, s, 16);
 }
+
+#if defined(KVM_CAP_IRQCHIP) && defined(TARGET_I386)
+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_init1(int io_addr, PicState *s)
+{
+    vmstate_register(io_addr, &vmstate_pic, s);
+    qemu_register_reset(pic_reset, 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, 24);
+}
+#endif
+
diff --git a/hw/pc.h b/hw/pc.h
index f7c1a88..ad97d22 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -26,6 +26,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);
 int pic_read_irq(PicState2 *s);
 void pic_update_irq(PicState2 *s);
 uint32_t pic_intack_read(PicState2 *s);
diff --git a/kvm-all.c b/kvm-all.c
index ff439a5..662017f 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -431,6 +431,30 @@ int kvm_get_irqchip(struct kvm_irqchip *chip)
 }
 #endif
 
+int kvm_set_irq(int irq, int level, int *status)
+{
+    struct kvm_irq_level event;
+    int r;
+
+    if (!kvm_state->irqchip_in_kernel) {
+        return 0;
+    }
+
+    event.level = level;
+    event.irq = irq;
+
+    r = kvm_vm_ioctl(kvm_state, KVM_IRQ_LINE_STATUS, &event);
+
+    if (r < 0)
+        return 0;
+
+    if (status) {
+        *status = event.status;
+    }
+
+    return 1;
+}
+
 int kvm_init(int smp_cpus)
 {
     static const char upgrade_note[] =
diff --git a/kvm.h b/kvm.h
index ae5223b..8536258 100644
--- a/kvm.h
+++ b/kvm.h
@@ -66,6 +66,8 @@ int kvm_irqchip_in_kernel(void);
 
 int kvm_set_irqchip(struct kvm_irqchip *chip);
 int kvm_get_irqchip(struct kvm_irqchip *chip);
+
+int kvm_set_irq(int irq, int level, int *status);
  
 /* internal API */
 
-- 
1.6.2.5





reply via email to

[Prev in Thread] Current Thread [Next in Thread]