All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 0/9] in-kernel irqchip
@ 2009-11-16 17:11 Glauber Costa
  2009-11-16 17:11 ` [Qemu-devel] [PATCH v2 1/9] introduce VMSTATE_U64 Glauber Costa
  0 siblings, 1 reply; 13+ messages in thread
From: Glauber Costa @ 2009-11-16 17:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

This is the second version of the in-kernel irqchip patchset.

It is pretty straightforward, and basically the same thing that was
already in staging. Just now kvm_put_mp_state() became i386-specific,
and had to go into a header.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v2 1/9] introduce VMSTATE_U64
  2009-11-16 17:11 [Qemu-devel] [PATCH v2 0/9] in-kernel irqchip Glauber Costa
@ 2009-11-16 17:11 ` Glauber Costa
  2009-11-16 17:12   ` [Qemu-devel] [PATCH v2 2/9] Provide ioapic-kvm Glauber Costa
  0 siblings, 1 reply; 13+ messages in thread
From: Glauber Costa @ 2009-11-16 17:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Slightly modified version of a patch already included in qemu-kvm:

This is a patch actually written by Juan, which, according to him,
he plans on posting to qemu.git. Problem is that linux defines
u64 in a way that is type-uncompatible with uint64_t.

I am including it here, because it is a dependency to my patch series
that follows.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 hw/hw.h  |   24 ++++++++++++++++++++++++
 savevm.c |   23 +++++++++++++++++++++++
 2 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/hw/hw.h b/hw/hw.h
index 1d4af2a..817b2c5 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -332,6 +332,11 @@ extern const VMStateInfo vmstate_info_uint16;
 extern const VMStateInfo vmstate_info_uint32;
 extern const VMStateInfo vmstate_info_uint64;
 
+#ifdef __linux__
+#include <linux/types.h>
+extern const VMStateInfo vmstate_info_u64;
+#endif
+
 extern const VMStateInfo vmstate_info_timer;
 extern const VMStateInfo vmstate_info_ptimer;
 extern const VMStateInfo vmstate_info_buffer;
@@ -388,6 +393,16 @@ extern const VMStateInfo vmstate_info_unused_buffer;
     .offset     = vmstate_offset_array(_state, _field, _type, _num), \
 }
 
+#define VMSTATE_ARRAY_UNSAFE(_field, _state, _num, _version, _info, _type) {\
+    .name       = (stringify(_field)),                               \
+    .version_id = (_version),                                        \
+    .num        = (_num),                                            \
+    .info       = &(_info),                                          \
+    .size       = sizeof(_type),                                     \
+    .flags      = VMS_ARRAY,                                         \
+    .offset     = offsetof(_state, _field)                           \
+}
+
 #define VMSTATE_ARRAY_TEST(_field, _state, _num, _test, _info, _type) {\
     .name         = (stringify(_field)),                              \
     .field_exists = (_test),                                          \
@@ -591,6 +606,15 @@ extern const VMStateDescription vmstate_i2c_slave;
 #define VMSTATE_UINT64(_f, _s)                                        \
     VMSTATE_UINT64_V(_f, _s, 0)
 
+/* This is needed because on linux __u64 is unsigned long long
+   and on glibc uint64_t is unsigned long on 64 bits */
+#ifdef __linux__
+#define VMSTATE_U64_V(_f, _s, _v)                                     \
+    VMSTATE_SINGLE(_f, _s, _v, vmstate_info_u64, __u64)
+#define VMSTATE_U64(_f, _s)                                           \
+    VMSTATE_U64_V(_f, _s, 0)
+#endif
+
 #define VMSTATE_UINT8_EQUAL(_f, _s)                                   \
     VMSTATE_SINGLE(_f, _s, 0, vmstate_info_uint8_equal, uint8_t)
 
diff --git a/savevm.c b/savevm.c
index 74f2c66..ac31eb7 100644
--- a/savevm.c
+++ b/savevm.c
@@ -856,6 +856,29 @@ const VMStateInfo vmstate_info_uint64 = {
     .put  = put_uint64,
 };
 
+/* 64 bit linux kernel unsigned int */
+
+#ifdef __linux__
+static int get_u64(QEMUFile *f, void *pv, size_t size)
+{
+    __u64 *v = pv;
+    qemu_get_be64s(f, (uint64_t *)v);
+    return 0;
+}
+
+static void put_u64(QEMUFile *f, void *pv, size_t size)
+{
+    __u64 *v = pv;
+    qemu_put_be64s(f, (uint64_t *)v);
+}
+
+const VMStateInfo vmstate_info_u64 = {
+    .name = "__u64",
+    .get  = get_u64,
+    .put  = put_u64,
+};
+#endif /* __linux__ */
+
 /* 8 bit int. See that the received value is the same than the one
    in the field */
 
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v2 2/9] Provide ioapic-kvm
  2009-11-16 17:11 ` [Qemu-devel] [PATCH v2 1/9] introduce VMSTATE_U64 Glauber Costa
@ 2009-11-16 17:12   ` Glauber Costa
  2009-11-16 17:12     ` [Qemu-devel] [PATCH v2 3/9] provide apic_set_irq_delivered Glauber Costa
  0 siblings, 1 reply; 13+ messages in thread
From: Glauber Costa @ 2009-11-16 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

This patch provides the file ioapic-kvm.c, which implements a schim over
the kvm in-kernel IO APIC.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 Makefile.target |    2 +
 hw/ioapic-kvm.c |   90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pc.c         |    7 ++++-
 hw/pc.h         |    2 +
 kvm-all.c       |   20 ++++++++++++
 kvm.h           |    4 ++
 6 files changed, 124 insertions(+), 1 deletions(-)
 create mode 100644 hw/ioapic-kvm.c

diff --git a/Makefile.target b/Makefile.target
index 7068dc5..6e97ba7 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -199,6 +199,8 @@ obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += ne2000-isa.o
 
+obj-i386-$(CONFIG_KVM) += ioapic-kvm.o
+
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
 obj-ppc-y += ide/cmd646.o
diff --git a/hw/ioapic-kvm.c b/hw/ioapic-kvm.c
new file mode 100644
index 0000000..9f3ff6a
--- /dev/null
+++ b/hw/ioapic-kvm.c
@@ -0,0 +1,90 @@
+#include "hw.h"
+#include "pc.h"
+#include "qemu-timer.h"
+#include "host-utils.h"
+#include "kvm.h"
+
+#define IOAPIC_NUM_PINS			0x18
+#define IOAPIC_DEFAULT_BASE_ADDRESS  0xfec00000
+
+static void ioapic_reset(void *opaque)
+{
+    struct kvm_ioapic_state *s = opaque;
+    struct kvm_irqchip *chip;
+    int i;
+
+    chip = container_of(s, struct kvm_irqchip, chip.ioapic);
+
+    chip->chip_id = KVM_IRQCHIP_IOAPIC;
+
+    memset(s, 0, sizeof(*s));
+    s->base_address = IOAPIC_DEFAULT_BASE_ADDRESS;
+    for(i = 0; i < IOAPIC_NUM_PINS; i++)
+        s->redirtbl[i].bits = 1 << 16; /* mask LVT */
+
+    kvm_set_irqchip(chip);
+}
+
+static void ioapic_pre_save(void *opaque)
+{
+    struct kvm_ioapic_state *s = opaque;
+    struct kvm_irqchip *chip;
+
+    chip = container_of(s, struct kvm_irqchip, chip.ioapic);
+
+    kvm_get_irqchip(chip);
+}
+
+static int ioapic_post_load(void *opaque, int version_id)
+{
+    struct kvm_ioapic_state *s = opaque;
+    struct kvm_irqchip *chip;
+
+    chip = container_of(s, struct kvm_irqchip, chip.ioapic);
+
+    return kvm_set_irqchip(chip);
+}
+
+static const VMStateDescription vmstate_kvm_ioapic = {
+    .name = "ioapic-kvm",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .post_load = ioapic_post_load,
+    .pre_save = ioapic_pre_save,
+    .fields      = (VMStateField []) {
+        /* Linux does not define __u64 the same as uint64_t */
+//        VMSTATE_SINGLE(base_address, struct kvm_ioapic_state, 1, vmstate_info_uint64, __u64),
+        VMSTATE_U64(base_address, struct kvm_ioapic_state),
+        VMSTATE_UINT32(id, struct kvm_ioapic_state),
+        VMSTATE_UINT32(ioregsel, struct kvm_ioapic_state),
+        VMSTATE_UINT32(irr, struct kvm_ioapic_state),
+        VMSTATE_ARRAY_UNSAFE(redirtbl, struct kvm_ioapic_state, IOAPIC_NUM_PINS, 0, vmstate_info_u64, __u64),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+
+static void kvm_ioapic_set_irq(void *opaque, int vector, int level)
+{
+/*
+    int pic_ret;
+
+    if (kvm_set_irq(vector, level, &pic_ret)) {
+        if (pic_ret != 0)
+            apic_set_irq_delivered();
+        return;
+    }
+*/
+}
+
+qemu_irq *kvm_ioapic_init(void)
+{
+    struct kvm_irqchip *s;
+
+    s = qemu_mallocz(sizeof(*s));
+
+    vmstate_register(0, &vmstate_kvm_ioapic, &s->chip.ioapic);
+    qemu_register_reset(ioapic_reset, &s->chip.ioapic);
+
+    return qemu_allocate_irqs(kvm_ioapic_set_irq, &s->chip.ioapic, IOAPIC_NUM_PINS);
+}
diff --git a/hw/pc.c b/hw/pc.c
index bf4718e..b7a1734 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -39,6 +39,7 @@
 #include "ide.h"
 #include "loader.h"
 #include "elf.h"
+#include "kvm.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -1200,7 +1201,11 @@ static void pc_init1(ram_addr_t ram_size,
     register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
 
     if (pci_enabled) {
-        isa_irq_state->ioapic = ioapic_init();
+        if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+            isa_irq_state->ioapic = kvm_ioapic_init();
+        } else {
+            isa_irq_state->ioapic = ioapic_init();
+        }
     }
     pit = pit_init(0x40, isa_reserve_irq(0));
     pcspk_init(pit);
diff --git a/hw/pc.h b/hw/pc.h
index 03ffc91..a3ad931 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -49,6 +49,8 @@ void ioapic_set_irq(void *opaque, int vector, int level);
 void apic_reset_irq_delivered(void);
 int apic_get_irq_delivered(void);
 
+qemu_irq *kvm_ioapic_init(void);
+
 /* i8254.c */
 
 #define PIT_FREQ 1193182
diff --git a/kvm-all.c b/kvm-all.c
index 1916ec6..fc542f3 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -391,6 +391,26 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
     return ret;
 }
 
+#ifdef KVM_CAP_IRQCHIP
+int kvm_set_irqchip(struct kvm_irqchip *chip)
+{
+    if (!kvm_state->irqchip_in_kernel) {
+        return 0;
+    }
+
+    return kvm_vm_ioctl(kvm_state, KVM_SET_IRQCHIP, chip);
+}
+
+int kvm_get_irqchip(struct kvm_irqchip *chip)
+{
+    if (!kvm_state->irqchip_in_kernel) {
+        return 0;
+    }
+
+    return kvm_vm_ioctl(kvm_state, KVM_GET_IRQCHIP, chip);
+}
+#endif
+
 int kvm_init(int smp_cpus)
 {
     static const char upgrade_note[] =
diff --git a/kvm.h b/kvm.h
index ecac828..fa5dbb6 100644
--- a/kvm.h
+++ b/kvm.h
@@ -16,6 +16,7 @@
 
 #include "config.h"
 #include "qemu-queue.h"
+#include <linux/kvm.h>
 
 #ifdef CONFIG_KVM
 extern int kvm_allowed;
@@ -63,6 +64,9 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap);
 int kvm_pit_in_kernel(void);
 int kvm_irqchip_in_kernel(void);
 
+int kvm_set_irqchip(struct kvm_irqchip *chip);
+int kvm_get_irqchip(struct kvm_irqchip *chip);
+
 /* internal API */
 
 struct KVMState;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v2 3/9] provide apic_set_irq_delivered
  2009-11-16 17:12   ` [Qemu-devel] [PATCH v2 2/9] Provide ioapic-kvm Glauber Costa
@ 2009-11-16 17:12     ` Glauber Costa
  2009-11-16 17:12       ` [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm Glauber Costa
  0 siblings, 1 reply; 13+ messages in thread
From: Glauber Costa @ 2009-11-16 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

i8259 chip will use it, so provide it, and export it through pc.h

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 hw/apic.c |    5 +++++
 hw/pc.h   |    1 +
 2 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/hw/apic.c b/hw/apic.c
index 87e7dc0..482bb1e 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -388,6 +388,11 @@ void apic_reset_irq_delivered(void)
     apic_irq_delivered = 0;
 }
 
+void apic_set_irq_delivered(void)
+{
+    apic_irq_delivered = 1;
+}
+
 int apic_get_irq_delivered(void)
 {
     return apic_irq_delivered;
diff --git a/hw/pc.h b/hw/pc.h
index a3ad931..4c9b4c3 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -47,6 +47,7 @@ int apic_get_interrupt(CPUState *env);
 qemu_irq *ioapic_init(void);
 void ioapic_set_irq(void *opaque, int vector, int level);
 void apic_reset_irq_delivered(void);
+void apic_set_irq_delivered(void);
 int apic_get_irq_delivered(void);
 
 qemu_irq *kvm_ioapic_init(void);
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm
  2009-11-16 17:12     ` [Qemu-devel] [PATCH v2 3/9] provide apic_set_irq_delivered Glauber Costa
@ 2009-11-16 17:12       ` Glauber Costa
  2009-11-16 17:12         ` [Qemu-devel] [PATCH v2 5/9] Don't call apic functions directly from kvm code Glauber Costa
  2009-12-01 16:49         ` [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm Alexander Graf
  0 siblings, 2 replies; 13+ messages in thread
From: Glauber Costa @ 2009-11-16 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

This patch provides the file i8259-kvm.c, which implements a schim over
the kvm in-kernel PIC.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 Makefile.target |    2 +-
 hw/i8259-kvm.c  |  112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pc.c         |    8 +++-
 hw/pc.h         |    1 +
 kvm-all.c       |   26 ++++++++++++-
 kvm.h           |    2 +
 6 files changed, 147 insertions(+), 4 deletions(-)
 create mode 100644 hw/i8259-kvm.c

diff --git a/Makefile.target b/Makefile.target
index 6e97ba7..86cf0a5 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -199,7 +199,7 @@ obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += ne2000-isa.o
 
-obj-i386-$(CONFIG_KVM) += ioapic-kvm.o
+obj-i386-$(CONFIG_KVM) += ioapic-kvm.o i8259-kvm.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
diff --git a/hw/i8259-kvm.c b/hw/i8259-kvm.c
new file mode 100644
index 0000000..bd6387b
--- /dev/null
+++ b/hw/i8259-kvm.c
@@ -0,0 +1,112 @@
+#include "hw.h"
+#include "pc.h"
+#include "isa.h"
+#include "monitor.h"
+#include "qemu-timer.h"
+#include "kvm.h"
+
+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)
+            /* In theory, we should not be using any apic state, but we need
+             * to warn devices such as the rtc about state of delivery. Since this
+             * one is just a marker, it is no big deal */
+            apic_set_irq_delivered();
+        return;
+    }
+}
+
+static void kvm_pic_reset(void *opaque)
+{
+    struct kvm_pic_state *s = opaque;
+    struct kvm_irqchip *chip;
+
+    s->last_irr = 0;
+    s->irr = 0;
+    s->imr = 0;
+    s->isr = 0;
+    s->priority_add = 0;
+    s->irq_base = 0;
+    s->read_reg_select = 0;
+    s->poll = 0;
+    s->special_mask = 0;
+    s->init_state = 0;
+    s->auto_eoi = 0;
+    s->rotate_on_auto_eoi = 0;
+    s->special_fully_nested_mode = 0;
+    s->init4 = 0;
+
+    chip = container_of(s, struct kvm_irqchip, chip.pic);
+    kvm_set_irqchip(chip);
+}
+
+static void pic_pre_save(void *opaque)
+{
+    struct kvm_pic_state *s = opaque;
+    struct kvm_irqchip *chip;
+
+    chip = container_of(s, struct kvm_irqchip, chip.pic);
+
+    kvm_get_irqchip(chip);
+}
+
+static int pic_post_load(void *opaque, int version_id)
+{
+    struct kvm_pic_state *s = opaque;
+    struct kvm_irqchip *chip;
+
+    chip = container_of(s, struct kvm_irqchip, chip.pic);
+
+    return kvm_set_irqchip(chip);
+}
+
+static const VMStateDescription vmstate_kvm_pic = {
+    .name = "i8259-kvm",
+    .version_id = 1,
+    .pre_save = pic_pre_save,
+    .post_load = pic_post_load,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_UINT8(last_irr, struct kvm_pic_state),
+        VMSTATE_UINT8(irr, struct kvm_pic_state),
+        VMSTATE_UINT8(imr, struct kvm_pic_state),
+        VMSTATE_UINT8(isr, struct kvm_pic_state),
+        VMSTATE_UINT8(priority_add, struct kvm_pic_state),
+        VMSTATE_UINT8(irq_base, struct kvm_pic_state),
+        VMSTATE_UINT8(read_reg_select, struct kvm_pic_state),
+        VMSTATE_UINT8(poll, struct kvm_pic_state),
+        VMSTATE_UINT8(special_mask, struct kvm_pic_state),
+        VMSTATE_UINT8(init_state, struct kvm_pic_state),
+        VMSTATE_UINT8(auto_eoi, struct kvm_pic_state),
+        VMSTATE_UINT8(rotate_on_auto_eoi, struct kvm_pic_state),
+        VMSTATE_UINT8(special_fully_nested_mode, struct kvm_pic_state),
+        VMSTATE_UINT8(init4, struct kvm_pic_state),
+        VMSTATE_UINT8(elcr, struct kvm_pic_state),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void kvm_pic_init1(int io_addr, struct kvm_pic_state *s)
+{
+    vmstate_register(io_addr, &vmstate_kvm_pic, s);
+    qemu_register_reset(kvm_pic_reset, s);
+}
+
+qemu_irq *kvm_i8259_init(qemu_irq parent_irq)
+{
+    struct kvm_irqchip *master, *slave;
+
+    master = qemu_mallocz(sizeof(*master));
+    slave = qemu_mallocz(sizeof(*slave));
+
+    master->chip_id = KVM_IRQCHIP_PIC_MASTER;
+    slave->chip_id = KVM_IRQCHIP_PIC_SLAVE;
+
+    kvm_pic_init1(0x20, &master->chip.pic);
+    kvm_pic_init1(0xa0, &slave->chip.pic);
+
+    return qemu_allocate_irqs(kvm_i8259_set_irq, master, 16);
+}
diff --git a/hw/pc.c b/hw/pc.c
index b7a1734..003ae11 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1154,8 +1154,14 @@ static void pc_init1(ram_addr_t ram_size,
     }
 
     cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
-    i8259 = i8259_init(cpu_irq[0]);
     isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
+
+    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+        i8259 = kvm_i8259_init(cpu_irq[0]);
+    } else {
+        i8259 = i8259_init(cpu_irq[0]);
+    }
+
     isa_irq_state->i8259 = i8259;
     isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
 
diff --git a/hw/pc.h b/hw/pc.h
index 4c9b4c3..3d79b9d 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -34,6 +34,7 @@ uint32_t pic_intack_read(PicState2 *s);
 void pic_info(Monitor *mon);
 void irq_info(Monitor *mon);
 
+qemu_irq *kvm_i8259_init(qemu_irq parent_irq);
 /* APIC */
 typedef struct IOAPICState IOAPICState;
 void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
diff --git a/kvm-all.c b/kvm-all.c
index fc542f3..c46a411 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -391,7 +391,6 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
     return ret;
 }
 
-#ifdef KVM_CAP_IRQCHIP
 int kvm_set_irqchip(struct kvm_irqchip *chip)
 {
     if (!kvm_state->irqchip_in_kernel) {
@@ -409,7 +408,30 @@ int kvm_get_irqchip(struct kvm_irqchip *chip)
 
     return kvm_vm_ioctl(kvm_state, KVM_GET_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)
 {
diff --git a/kvm.h b/kvm.h
index fa5dbb6..5f62e96 100644
--- a/kvm.h
+++ b/kvm.h
@@ -67,6 +67,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 */
 
 struct KVMState;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v2 5/9] Don't call apic functions directly from kvm code
  2009-11-16 17:12       ` [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm Glauber Costa
@ 2009-11-16 17:12         ` Glauber Costa
  2009-11-16 17:12           ` [Qemu-devel] [PATCH v2 6/9] export kvm_put_mp_state Glauber Costa
  2009-12-01 16:49         ` [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm Alexander Graf
  1 sibling, 1 reply; 13+ messages in thread
From: Glauber Costa @ 2009-11-16 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

It is actually not necessary to call a tpr function to save and load cr8,
as cr8 is part of the processor state, and thus, it is much easier
to just add it to CPUState.

As for apic base, wrap kvm usages, so we can call either the qemu device,
or the in kernel version.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 target-i386/cpu.h |    1 +
 target-i386/kvm.c |   25 +++++++++++++++++++------
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 5929d28..e5470f7 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -606,6 +606,7 @@ typedef struct CPUX86State {
     SegmentCache idt; /* only base and limit are used */
 
     target_ulong cr[5]; /* NOTE: cr1 is unused */
+    target_ulong cr8;
     int32_t a20_mask;
 
     /* FPU state */
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 6613a3f..103defd 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -338,6 +338,19 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)
 	| (rhs->avl * DESC_AVL_MASK);
 }
 
+static void kvm_set_apic_base(CPUState *env, uint64_t val)
+{
+    if (!kvm_irqchip_in_kernel())
+        cpu_set_apic_base(env, val);
+}
+
+static uint64_t kvm_get_apic_base(CPUState *env)
+{
+    if (!kvm_irqchip_in_kernel())
+        return cpu_get_apic_base(env);
+    return 0;
+}
+
 static void kvm_getput_reg(__u64 *kvm_reg, target_ulong *qemu_reg, int set)
 {
     if (set)
@@ -447,8 +460,8 @@ static int kvm_put_sregs(CPUState *env)
     sregs.cr3 = env->cr[3];
     sregs.cr4 = env->cr[4];
 
-    sregs.cr8 = cpu_get_apic_tpr(env);
-    sregs.apic_base = cpu_get_apic_base(env);
+    sregs.cr8 = env->cr8;
+    sregs.apic_base = kvm_get_apic_base(env);
 
     sregs.efer = env->efer;
 
@@ -546,7 +559,7 @@ static int kvm_get_sregs(CPUState *env)
     env->cr[3] = sregs.cr3;
     env->cr[4] = sregs.cr4;
 
-    cpu_set_apic_base(env, sregs.apic_base);
+    kvm_set_apic_base(env, sregs.apic_base);
 
     env->efer = sregs.efer;
     //cpu_set_apic_tpr(env, sregs.cr8);
@@ -762,7 +775,7 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
         run->request_interrupt_window = 0;
 
     dprintf("setting tpr\n");
-    run->cr8 = cpu_get_apic_tpr(env);
+    run->cr8 = env->cr8;
 
     return 0;
 }
@@ -774,8 +787,8 @@ int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
     else
         env->eflags &= ~IF_MASK;
     
-    cpu_set_apic_tpr(env, run->cr8);
-    cpu_set_apic_base(env, run->apic_base);
+    env->cr8 = run->cr8;
+    kvm_set_apic_base(env, run->apic_base);
 
     return 0;
 }
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v2 6/9] export kvm_put_mp_state
  2009-11-16 17:12         ` [Qemu-devel] [PATCH v2 5/9] Don't call apic functions directly from kvm code Glauber Costa
@ 2009-11-16 17:12           ` Glauber Costa
  2009-11-16 17:12             ` [Qemu-devel] [PATCH v2 7/9] provide apic-kvm Glauber Costa
  0 siblings, 1 reply; 13+ messages in thread
From: Glauber Costa @ 2009-11-16 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

We'll use it from inside the in-kernel apic chip, so get it into a header
file.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 target-i386/cpu.h |    4 ++++
 target-i386/kvm.c |    2 +-
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index e5470f7..c671894 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -922,4 +922,8 @@ void apic_init_reset(CPUState *env);
 void apic_sipi(CPUState *env);
 void do_cpu_init(CPUState *env);
 void do_cpu_sipi(CPUState *env);
+
+/* KVM hooks */
+int kvm_put_mp_state(CPUState *env);
+
 #endif /* CPU_I386_H */
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 103defd..6ba0b7e 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -672,7 +672,7 @@ static int kvm_get_msrs(CPUState *env)
     return 0;
 }
 
-static int kvm_put_mp_state(CPUState *env)
+int kvm_put_mp_state(CPUState *env)
 {
     struct kvm_mp_state mp_state = { .mp_state = env->mp_state };
 
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v2 7/9] provide apic-kvm
  2009-11-16 17:12           ` [Qemu-devel] [PATCH v2 6/9] export kvm_put_mp_state Glauber Costa
@ 2009-11-16 17:12             ` Glauber Costa
  2009-11-16 17:12               ` [Qemu-devel] [PATCH v2 8/9] Initialize in-kernel irqchip Glauber Costa
  2009-12-01 16:44               ` [Qemu-devel] [PATCH v2 7/9] provide apic-kvm Alexander Graf
  0 siblings, 2 replies; 13+ messages in thread
From: Glauber Costa @ 2009-11-16 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

This patch provides the file apic-kvm.c, which implements a schim over
the kvm in-kernel APIC.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 Makefile.target   |    2 +-
 hw/apic-kvm.c     |  157 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/pc.c           |    6 ++-
 hw/pc.h           |    2 +
 kvm.h             |    3 +
 target-i386/cpu.h |    4 ++
 target-i386/kvm.c |   23 ++++++++-
 7 files changed, 194 insertions(+), 3 deletions(-)
 create mode 100644 hw/apic-kvm.c

diff --git a/Makefile.target b/Makefile.target
index 86cf0a5..761e905 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -199,7 +199,7 @@ obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
 obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += ne2000-isa.o
 
-obj-i386-$(CONFIG_KVM) += ioapic-kvm.o i8259-kvm.o
+obj-i386-$(CONFIG_KVM) += ioapic-kvm.o i8259-kvm.o apic-kvm.o
 
 # shared objects
 obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
diff --git a/hw/apic-kvm.c b/hw/apic-kvm.c
new file mode 100644
index 0000000..089fa45
--- /dev/null
+++ b/hw/apic-kvm.c
@@ -0,0 +1,157 @@
+#include "hw.h"
+#include "pc.h"
+#include "pci.h"
+#include "msix.h"
+#include "qemu-timer.h"
+#include "host-utils.h"
+#include "kvm.h"
+
+#define APIC_LVT_NB      6
+#define APIC_LVT_LINT0   3
+
+struct qemu_lapic_state {
+    uint32_t apicbase;
+    uint8_t id;
+    uint8_t arb_id;
+    uint8_t tpr;
+    uint32_t spurious_vec;
+    uint8_t log_dest;
+    uint8_t dest_mode;
+    uint32_t isr[8];  /* in service register */
+    uint32_t tmr[8];  /* trigger mode register */
+    uint32_t irr[8]; /* interrupt request register */
+    uint32_t lvt[APIC_LVT_NB];
+    uint32_t esr; /* error register */
+    uint32_t icr[2];
+
+    uint32_t divide_conf;
+    int count_shift;
+    uint32_t initial_count;
+    int64_t initial_count_load_time, next_time;
+    uint32_t idx;
+    int sipi_vector;
+    int wait_for_sipi;
+};
+
+typedef struct APICState {
+    CPUState *cpu_env;
+
+/* KVM lapic structure is just a big array of regs. But it is what kvm
+ * functions expect. So have both the fields separated, for easy access,
+ * and the kvm stucture, for ioctls communications */
+    union {
+        struct qemu_lapic_state dev;
+        struct kvm_lapic_state kvm_lapic_state;
+    };
+} APICState;
+
+void kvm_apic_set_base(CPUState *env, uint64_t val)
+{
+    APICState *s = env->apic_state;
+
+    if (!s)
+        return;
+
+    s->dev.apicbase = val;
+}
+
+uint64_t kvm_apic_get_base(CPUState *env)
+{
+    APICState *s = env->apic_state;
+
+    return s ? s->dev.apicbase : 0;
+}
+
+static void apic_pre_save(void *opaque)
+{
+    APICState *s = opaque;
+
+    kvm_get_lapic(s->cpu_env, &s->kvm_lapic_state);
+}
+
+static int apic_post_load(void *opaque, int version_id)
+{
+    APICState *s = opaque;
+
+    return kvm_set_lapic(s->cpu_env, &s->kvm_lapic_state);
+}
+
+static const VMStateDescription vmstate_apic = {
+    .name = "apic-kvm",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields      = (VMStateField []) {
+        VMSTATE_BUFFER_UNSAFE(kvm_lapic_state.regs, APICState, 1, KVM_APIC_REG_SIZE),
+        VMSTATE_END_OF_LIST()
+    },
+    .pre_save = apic_pre_save,
+    .post_load = apic_post_load,
+};
+
+static void kvm_apic_reset(void *opaque)
+{
+    APICState *s = opaque;
+    int bsp;
+    int i;
+
+    cpu_synchronize_state(s->cpu_env);
+
+    bsp = cpu_is_bsp(s->cpu_env);
+
+    s->dev.apicbase = 0xfee00000 |
+        (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE;
+
+    cpu_reset(s->cpu_env);
+
+    s->dev.tpr = 0;
+    s->dev.spurious_vec = 0xff;
+    s->dev.log_dest = 0;
+    s->dev.dest_mode = 0xf;
+    memset(s->dev.isr, 0, sizeof(s->dev.isr));
+    memset(s->dev.tmr, 0, sizeof(s->dev.tmr));
+    memset(s->dev.irr, 0, sizeof(s->dev.irr));
+    for(i = 0; i < APIC_LVT_NB; i++)
+        s->dev.lvt[i] = 1 << 16; /* mask LVT */
+    s->dev.esr = 0;
+    memset(s->dev.icr, 0, sizeof(s->dev.icr));
+    s->dev.divide_conf = 0;
+    s->dev.count_shift = 0;
+    s->dev.initial_count = 0;
+    s->dev.initial_count_load_time = 0;
+    s->dev.next_time = 0;
+    s->dev.wait_for_sipi = 1;
+
+    s->cpu_env->halted = !(s->dev.apicbase & MSR_IA32_APICBASE_BSP);
+
+    s->cpu_env->mp_state
+            = s->cpu_env->halted ? KVM_MP_STATE_UNINITIALIZED : KVM_MP_STATE_RUNNABLE;
+
+    kvm_put_mp_state(s->cpu_env);
+
+    if (bsp) {
+        /*
+         * LINT0 delivery mode on CPU #0 is set to ExtInt at initialization
+         * time typically by BIOS, so PIC interrupt can be delivered to the
+         * processor when local APIC is enabled.
+         */
+        s->dev.lvt[APIC_LVT_LINT0] = 0x700;
+    }
+    kvm_set_lapic(s->cpu_env, &s->kvm_lapic_state);
+}
+
+int kvm_apic_init(CPUState *env)
+{
+    APICState *s;
+
+    s = qemu_mallocz(sizeof(*s));
+    env->apic_state = s;
+    s->cpu_env = env;
+
+    msix_supported = 1;
+
+    vmstate_register(s->dev.id, &vmstate_apic, s);
+    qemu_register_reset(kvm_apic_reset, s);
+
+    return 0;
+}
diff --git a/hw/pc.c b/hw/pc.c
index 003ae11..ddc8d32 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1018,7 +1018,11 @@ static CPUState *pc_new_cpu(const char *cpu_model)
     if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
         env->cpuid_apic_id = env->cpu_index;
         /* APIC reset callback resets cpu */
-        apic_init(env);
+        if (kvm_enabled() && kvm_irqchip_in_kernel()) {
+            kvm_apic_init(env);
+        } else {
+            apic_init(env);
+        }
     } else {
         qemu_register_reset((QEMUResetHandler*)cpu_reset, env);
     }
diff --git a/hw/pc.h b/hw/pc.h
index 3d79b9d..6b3817a 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -42,6 +42,8 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
                              uint8_t vector_num, uint8_t polarity,
                              uint8_t trigger_mode);
 int apic_init(CPUState *env);
+int kvm_apic_init(CPUState *env);
+
 int apic_accept_pic_intr(CPUState *env);
 void apic_deliver_pic_intr(CPUState *env, int level);
 int apic_get_interrupt(CPUState *env);
diff --git a/kvm.h b/kvm.h
index 5f62e96..c5a0915 100644
--- a/kvm.h
+++ b/kvm.h
@@ -96,6 +96,9 @@ int kvm_arch_init(KVMState *s, int smp_cpus);
 
 int kvm_arch_init_vcpu(CPUState *env);
 
+int kvm_set_lapic(CPUState *env, struct kvm_lapic_state *s);
+int kvm_get_lapic(CPUState *env, struct kvm_lapic_state *s);
+
 struct kvm_guest_debug;
 struct kvm_debug_exit_arch;
 
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index c671894..6eb0f21 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -855,6 +855,10 @@ void cpu_set_apic_tpr(CPUX86State *env, uint8_t val);
 uint8_t cpu_get_apic_tpr(CPUX86State *env);
 #endif
 
+/* hw/apic-kvm.c */
+void kvm_apic_set_base(CPUX86State *env, uint64_t val);
+uint64_t kvm_apic_get_base(CPUX86State *env);
+
 /* hw/pc.c */
 void cpu_smm_update(CPUX86State *env);
 uint64_t cpu_get_tsc(CPUX86State *env);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 6ba0b7e..0224818 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -342,13 +342,16 @@ static void kvm_set_apic_base(CPUState *env, uint64_t val)
 {
     if (!kvm_irqchip_in_kernel())
         cpu_set_apic_base(env, val);
+    else
+        kvm_apic_set_base(env, val);
 }
 
 static uint64_t kvm_get_apic_base(CPUState *env)
 {
     if (!kvm_irqchip_in_kernel())
         return cpu_get_apic_base(env);
-    return 0;
+    else
+        return kvm_apic_get_base(env);
 }
 
 static void kvm_getput_reg(__u64 *kvm_reg, target_ulong *qemu_reg, int set)
@@ -990,3 +993,21 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
     }
 }
 #endif /* KVM_CAP_SET_GUEST_DEBUG */
+
+#ifdef KVM_CAP_IRQCHIP
+int kvm_set_lapic(CPUState *env, struct kvm_lapic_state *s)
+{
+    if (!kvm_irqchip_in_kernel())
+        return 0;
+
+    return kvm_vcpu_ioctl(env, KVM_SET_LAPIC, s);
+}
+
+int kvm_get_lapic(CPUState *env, struct kvm_lapic_state *s)
+{
+    if (!kvm_irqchip_in_kernel())
+        return 0;
+
+    return kvm_vcpu_ioctl(env, KVM_GET_LAPIC, s);
+}
+#endif
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v2 8/9] Initialize in-kernel irqchip
  2009-11-16 17:12             ` [Qemu-devel] [PATCH v2 7/9] provide apic-kvm Glauber Costa
@ 2009-11-16 17:12               ` Glauber Costa
  2009-11-16 17:12                 ` [Qemu-devel] [PATCH v2 9/9] Do GSI routing Glauber Costa
  2009-12-01 16:44               ` [Qemu-devel] [PATCH v2 7/9] provide apic-kvm Alexander Graf
  1 sibling, 1 reply; 13+ messages in thread
From: Glauber Costa @ 2009-11-16 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Now that we have all devices set up, this patch initializes the irqchip.
This is dependant on the io-thread, since we need someone to pull ourselves
out of the halted state.

I believe this should be the default when we are running over the io-thread.
Later on, I plan to post a patch that makes it optional.

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 kvm-all.c |   20 ++++++++++++++++++++
 1 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index c46a411..7a3671f 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -433,6 +433,22 @@ int kvm_set_irq(int irq, int level, int *status)
     return 1;
 }
 
+static int kvm_create_irqchip(KVMState *s)
+{
+    int ret = 0;
+#if defined(CONFIG_IOTHREAD)
+    if (!kvm_check_extension(s, KVM_CAP_IRQCHIP))
+        return -1;
+
+    ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP);
+    if (ret < 0)
+        return ret;
+
+    s->irqchip_in_kernel = 1;
+#endif
+    return ret;
+}
+
 int kvm_init(int smp_cpus)
 {
     static const char upgrade_note[] =
@@ -519,6 +535,10 @@ int kvm_init(int smp_cpus)
     }
 #endif
 
+    ret = kvm_create_irqchip(s);
+    if (ret < 0)
+        goto err;
+
     ret = kvm_arch_init(s, smp_cpus);
     if (ret < 0)
         goto err;
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Qemu-devel] [PATCH v2 9/9] Do GSI routing
  2009-11-16 17:12               ` [Qemu-devel] [PATCH v2 8/9] Initialize in-kernel irqchip Glauber Costa
@ 2009-11-16 17:12                 ` Glauber Costa
  0 siblings, 0 replies; 13+ messages in thread
From: Glauber Costa @ 2009-11-16 17:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

To follow correctly what our bios ACPI tables say, we have to be able to program
our irqchips with GSI routing mappings. This support is already in qemu-kvm

Signed-off-by: Glauber Costa <glommer@redhat.com>
---
 kvm-all.c         |    6 ++-
 kvm.h             |    3 +
 target-i386/kvm.c |  118 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 125 insertions(+), 2 deletions(-)

diff --git a/kvm-all.c b/kvm-all.c
index 7a3671f..cf10abe 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -66,6 +66,8 @@ struct KVMState
 #endif
     int irqchip_in_kernel;
     int pit_in_kernel;
+
+    KVMArchState *arch_state;
 };
 
 static KVMState *kvm_state;
@@ -539,12 +541,12 @@ int kvm_init(int smp_cpus)
     if (ret < 0)
         goto err;
 
+    kvm_state = s;
+
     ret = kvm_arch_init(s, smp_cpus);
     if (ret < 0)
         goto err;
 
-    kvm_state = s;
-
     return 0;
 
 err:
diff --git a/kvm.h b/kvm.h
index c5a0915..15df381 100644
--- a/kvm.h
+++ b/kvm.h
@@ -72,7 +72,10 @@ int kvm_set_irq(int irq, int level, int *status);
 /* internal API */
 
 struct KVMState;
+struct KVMArchState;
+
 typedef struct KVMState KVMState;
+typedef struct KVMArchState KVMArchState;
 
 int kvm_ioctl(KVMState *s, int type, ...);
 
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0224818..8439f2f 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -36,6 +36,16 @@
 
 #ifdef KVM_CAP_EXT_CPUID
 
+struct KVMArchState
+{
+    struct kvm_irq_routing *irq_routes;
+    int nr_allocated_irq_routes;
+    void *used_gsi_bitmap;
+    int max_gsi;
+};
+
+static KVMArchState *kvm_arch_state;
+
 static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
 {
     struct kvm_cpuid2 *cpuid;
@@ -266,10 +276,118 @@ static int kvm_has_msr_star(CPUState *env)
     return 0;
 }
 
+/*
+ * Setup x86 specific IRQ routing
+ */
+static inline void set_gsi(KVMArchState *s, unsigned int gsi)
+{
+    uint32_t *bitmap = s->used_gsi_bitmap;
+
+    if (gsi < s->max_gsi)
+        bitmap[gsi / 32] |= 1U << (gsi % 32);
+    else
+        fprintf(stderr, "Invalid GSI %d\n", gsi);
+}
+
+static int kvm_add_routing_entry(KVMArchState *s, struct kvm_irq_routing_entry *entry)
+{
+    struct kvm_irq_routing *z;
+    struct kvm_irq_routing_entry *new;
+    int n, size;
+
+    if (s->irq_routes->nr == s->nr_allocated_irq_routes) {
+        n = s->nr_allocated_irq_routes * 2;
+        if (n < 64)
+            n = 64;
+        size = sizeof(struct kvm_irq_routing);
+        size += n * sizeof(*new);
+        z = realloc(s->irq_routes, size);
+        if (!z)
+            return -ENOMEM;
+        s->nr_allocated_irq_routes = n;
+        s->irq_routes = z;
+    }
+    n = s->irq_routes->nr++;
+    new = &s->irq_routes->entries[n];
+    memset(new, 0, sizeof(*new));
+    new->gsi = entry->gsi;
+    new->type = entry->type;
+    new->flags = entry->flags;
+    new->u = entry->u;
+
+    set_gsi(s, entry->gsi);
+
+    return 0;
+}
+
+static int kvm_add_irq_route(KVMArchState *s, int gsi, int irqchip, int pin)
+{
+    struct kvm_irq_routing_entry e;
+
+    e.gsi = gsi;
+    e.type = KVM_IRQ_ROUTING_IRQCHIP;
+    e.flags = 0;
+    e.u.irqchip.irqchip = irqchip;
+    e.u.irqchip.pin = pin;
+    return kvm_add_routing_entry(s, &e);
+}
+
+static int kvm_init_irq_routing(KVMState *s)
+{
+    int i, r;
+    int gsi_count, gsi_bits;
+
+    gsi_count = kvm_check_extension(s, KVM_CAP_IRQ_ROUTING);
+    if (!kvm_irqchip_in_kernel() && (gsi_count > 0)) {
+        return 0;
+    }
+
+        /* Round up so we can search ints using ffs */
+    gsi_bits = ((gsi_count - 31) & ~31);
+    kvm_arch_state->used_gsi_bitmap = qemu_mallocz(gsi_bits / 8);
+    kvm_arch_state->max_gsi = gsi_bits;
+
+    /* Mark any over-allocated bits as already in use */
+    for (i = gsi_count; i < gsi_bits; i++) {
+        set_gsi(kvm_arch_state, i);
+    }
+
+    kvm_arch_state->irq_routes->nr = 0;
+
+    for (i = 0; i < 8; ++i) {
+        if (i == 2)
+            continue;
+        r = kvm_add_irq_route(kvm_arch_state, i, KVM_IRQCHIP_PIC_MASTER, i);
+        if (r < 0)
+            return r;
+    }
+    for (i = 8; i < 16; ++i) {
+        r = kvm_add_irq_route(kvm_arch_state, i, KVM_IRQCHIP_PIC_SLAVE, i - 8);
+        if (r < 0)
+            return r;
+    }
+    for (i = 0; i < 24; ++i) {
+        if (i == 0) {
+            r = kvm_add_irq_route(kvm_arch_state, i, KVM_IRQCHIP_IOAPIC, 2);
+        } else if (i != 2) {
+            r = kvm_add_irq_route(kvm_arch_state, i, KVM_IRQCHIP_IOAPIC, i);
+        }
+        if (r < 0)
+            return r;
+    }
+
+    kvm_arch_state->irq_routes->flags = 0;
+    return kvm_vm_ioctl(s, KVM_SET_GSI_ROUTING, kvm_arch_state->irq_routes);
+}
 int kvm_arch_init(KVMState *s, int smp_cpus)
 {
     int ret;
 
+    kvm_arch_state = qemu_mallocz(sizeof(*kvm_arch_state));
+    kvm_arch_state->irq_routes = qemu_mallocz(sizeof(*kvm_arch_state->irq_routes));
+
+    kvm_init_irq_routing(s);
+
     /* create vm86 tss.  KVM uses vm86 mode to emulate 16-bit code
      * directly.  In order to use vm86 mode, a TSS is needed.  Since this
      * must be part of guest physical memory, we need to allocate it.  Older
-- 
1.6.2.5

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2 7/9] provide apic-kvm
  2009-11-16 17:12             ` [Qemu-devel] [PATCH v2 7/9] provide apic-kvm Glauber Costa
  2009-11-16 17:12               ` [Qemu-devel] [PATCH v2 8/9] Initialize in-kernel irqchip Glauber Costa
@ 2009-12-01 16:44               ` Alexander Graf
  1 sibling, 0 replies; 13+ messages in thread
From: Alexander Graf @ 2009-12-01 16:44 UTC (permalink / raw)
  To: Glauber Costa; +Cc: aliguori, qemu-devel

Glauber Costa wrote:
> This patch provides the file apic-kvm.c, which implements a schim over
> the kvm in-kernel APIC.
>
> Signed-off-by: Glauber Costa <glommer@redhat.com>
> ---
>  Makefile.target   |    2 +-
>  hw/apic-kvm.c     |  157 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/pc.c           |    6 ++-
>  hw/pc.h           |    2 +
>  kvm.h             |    3 +
>  target-i386/cpu.h |    4 ++
>  target-i386/kvm.c |   23 ++++++++-
>  7 files changed, 194 insertions(+), 3 deletions(-)
>  create mode 100644 hw/apic-kvm.c
>
> diff --git a/Makefile.target b/Makefile.target
> index 86cf0a5..761e905 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -199,7 +199,7 @@ obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
>  obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
>  obj-i386-y += ne2000-isa.o
>  
> -obj-i386-$(CONFIG_KVM) += ioapic-kvm.o i8259-kvm.o
> +obj-i386-$(CONFIG_KVM) += ioapic-kvm.o i8259-kvm.o apic-kvm.o
>  
>  # shared objects
>  obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
> diff --git a/hw/apic-kvm.c b/hw/apic-kvm.c
> new file mode 100644
> index 0000000..089fa45
> --- /dev/null
> +++ b/hw/apic-kvm.c
> @@ -0,0 +1,157 @@
> +#include "hw.h"
> +#include "pc.h"
> +#include "pci.h"
> +#include "msix.h"
> +#include "qemu-timer.h"
> +#include "host-utils.h"
> +#include "kvm.h"
> +
> +#define APIC_LVT_NB      6
> +#define APIC_LVT_LINT0   3
> +
> +struct qemu_lapic_state {
> +    uint32_t apicbase;
> +    uint8_t id;
> +    uint8_t arb_id;
> +    uint8_t tpr;
> +    uint32_t spurious_vec;
> +    uint8_t log_dest;
> +    uint8_t dest_mode;
> +    uint32_t isr[8];  /* in service register */
> +    uint32_t tmr[8];  /* trigger mode register */
> +    uint32_t irr[8]; /* interrupt request register */
> +    uint32_t lvt[APIC_LVT_NB];
> +    uint32_t esr; /* error register */
> +    uint32_t icr[2];
> +
> +    uint32_t divide_conf;
> +    int count_shift;
> +    uint32_t initial_count;
> +    int64_t initial_count_load_time, next_time;
> +    uint32_t idx;
> +    int sipi_vector;
> +    int wait_for_sipi;
> +};
> +
> +typedef struct APICState {
> +    CPUState *cpu_env;
> +
> +/* KVM lapic structure is just a big array of regs. But it is what kvm
> + * functions expect. So have both the fields separated, for easy access,
> + * and the kvm stucture, for ioctls communications */
> +    union {
> +        struct qemu_lapic_state dev;
> +        struct kvm_lapic_state kvm_lapic_state
>   

On S390X:

cc1: warnings being treated as errors
In file included from /suse/agraf/work/kvm-s390/qemu.works/vl.c:156:
/suse/agraf/work/kvm-s390/qemu.works/kvm.h:104: error: ‘struct
kvm_lapic_state’ declared inside parameter list
/suse/agraf/work/kvm-s390/qemu.works/kvm.h:104: error: its scope is only
this definition or declaration, which is probably not what you want
/suse/agraf/work/kvm-s390/qemu.works/kvm.h:105: error: ‘struct
kvm_lapic_state’ declared inside parameter list


Alex

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm
  2009-11-16 17:12       ` [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm Glauber Costa
  2009-11-16 17:12         ` [Qemu-devel] [PATCH v2 5/9] Don't call apic functions directly from kvm code Glauber Costa
@ 2009-12-01 16:49         ` Alexander Graf
  2009-12-01 17:15           ` Glauber Costa
  1 sibling, 1 reply; 13+ messages in thread
From: Alexander Graf @ 2009-12-01 16:49 UTC (permalink / raw)
  To: Glauber Costa; +Cc: aliguori, qemu-devel

Glauber Costa wrote:
> This patch provides the file i8259-kvm.c, which implements a schim over
> the kvm in-kernel PIC.
>
> Signed-off-by: Glauber Costa <glommer@redhat.com>
> ---
>  Makefile.target |    2 +-
>  hw/i8259-kvm.c  |  112 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  hw/pc.c         |    8 +++-
>  hw/pc.h         |    1 +
>  kvm-all.c       |   26 ++++++++++++-
>  kvm.h           |    2 +
>  6 files changed, 147 insertions(+), 4 deletions(-)
>  create mode 100644 hw/i8259-kvm.c
>
> diff --git a/Makefile.target b/Makefile.target
> index 6e97ba7..86cf0a5 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -199,7 +199,7 @@ obj-i386-y += usb-uhci.o vmmouse.o vmport.o vmware_vga.o hpet.o
>  obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
>  obj-i386-y += ne2000-isa.o
>  
> -obj-i386-$(CONFIG_KVM) += ioapic-kvm.o
> +obj-i386-$(CONFIG_KVM) += ioapic-kvm.o i8259-kvm.o
>  
>  # shared objects
>  obj-ppc-y = ppc.o ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/macio.o
> diff --git a/hw/i8259-kvm.c b/hw/i8259-kvm.c
> new file mode 100644
> index 0000000..bd6387b
> --- /dev/null
> +++ b/hw/i8259-kvm.c
> @@ -0,0 +1,112 @@
> +#include "hw.h"
> +#include "pc.h"
> +#include "isa.h"
> +#include "monitor.h"
> +#include "qemu-timer.h"
> +#include "kvm.h"
> +
> +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)
> +            /* In theory, we should not be using any apic state, but we need
> +             * to warn devices such as the rtc about state of delivery. Since this
> +             * one is just a marker, it is no big deal */
> +            apic_set_irq_delivered();
> +        return;
> +    }
> +}
> +
> +static void kvm_pic_reset(void *opaque)
> +{
> +    struct kvm_pic_state *s = opaque;
> +    struct kvm_irqchip *chip;
> +
> +    s->last_irr = 0;
> +    s->irr = 0;
> +    s->imr = 0;
> +    s->isr = 0;
> +    s->priority_add = 0;
> +    s->irq_base = 0;
> +    s->read_reg_select = 0;
> +    s->poll = 0;
> +    s->special_mask = 0;
> +    s->init_state = 0;
> +    s->auto_eoi = 0;
> +    s->rotate_on_auto_eoi = 0;
> +    s->special_fully_nested_mode = 0;
> +    s->init4 = 0;
> +
> +    chip = container_of(s, struct kvm_irqchip, chip.pic);
> +    kvm_set_irqchip(chip);
> +}
> +
> +static void pic_pre_save(void *opaque)
> +{
> +    struct kvm_pic_state *s = opaque;
> +    struct kvm_irqchip *chip;
> +
> +    chip = container_of(s, struct kvm_irqchip, chip.pic);
> +
> +    kvm_get_irqchip(chip);
> +}
> +
> +static int pic_post_load(void *opaque, int version_id)
> +{
> +    struct kvm_pic_state *s = opaque;
> +    struct kvm_irqchip *chip;
> +
> +    chip = container_of(s, struct kvm_irqchip, chip.pic);
> +
> +    return kvm_set_irqchip(chip);
> +}
> +
> +static const VMStateDescription vmstate_kvm_pic = {
> +    .name = "i8259-kvm",
> +    .version_id = 1,
> +    .pre_save = pic_pre_save,
> +    .post_load = pic_post_load,
> +    .minimum_version_id = 1,
> +    .fields      = (VMStateField []) {
> +        VMSTATE_UINT8(last_irr, struct kvm_pic_state),
> +        VMSTATE_UINT8(irr, struct kvm_pic_state),
> +        VMSTATE_UINT8(imr, struct kvm_pic_state),
> +        VMSTATE_UINT8(isr, struct kvm_pic_state),
> +        VMSTATE_UINT8(priority_add, struct kvm_pic_state),
> +        VMSTATE_UINT8(irq_base, struct kvm_pic_state),
> +        VMSTATE_UINT8(read_reg_select, struct kvm_pic_state),
> +        VMSTATE_UINT8(poll, struct kvm_pic_state),
> +        VMSTATE_UINT8(special_mask, struct kvm_pic_state),
> +        VMSTATE_UINT8(init_state, struct kvm_pic_state),
> +        VMSTATE_UINT8(auto_eoi, struct kvm_pic_state),
> +        VMSTATE_UINT8(rotate_on_auto_eoi, struct kvm_pic_state),
> +        VMSTATE_UINT8(special_fully_nested_mode, struct kvm_pic_state),
> +        VMSTATE_UINT8(init4, struct kvm_pic_state),
> +        VMSTATE_UINT8(elcr, struct kvm_pic_state),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void kvm_pic_init1(int io_addr, struct kvm_pic_state *s)
> +{
> +    vmstate_register(io_addr, &vmstate_kvm_pic, s);
> +    qemu_register_reset(kvm_pic_reset, s);
> +}
> +
> +qemu_irq *kvm_i8259_init(qemu_irq parent_irq)
> +{
> +    struct kvm_irqchip *master, *slave;
> +
> +    master = qemu_mallocz(sizeof(*master));
> +    slave = qemu_mallocz(sizeof(*slave));
> +
> +    master->chip_id = KVM_IRQCHIP_PIC_MASTER;
> +    slave->chip_id = KVM_IRQCHIP_PIC_SLAVE;
> +
> +    kvm_pic_init1(0x20, &master->chip.pic);
> +    kvm_pic_init1(0xa0, &slave->chip.pic);
> +
> +    return qemu_allocate_irqs(kvm_i8259_set_irq, master, 16);
> +}
> diff --git a/hw/pc.c b/hw/pc.c
> index b7a1734..003ae11 100644
> --- a/hw/pc.c
> +++ b/hw/pc.c
> @@ -1154,8 +1154,14 @@ static void pc_init1(ram_addr_t ram_size,
>      }
>  
>      cpu_irq = qemu_allocate_irqs(pic_irq_request, NULL, 1);
> -    i8259 = i8259_init(cpu_irq[0]);
>      isa_irq_state = qemu_mallocz(sizeof(*isa_irq_state));
> +
> +    if (kvm_enabled() && kvm_irqchip_in_kernel()) {
> +        i8259 = kvm_i8259_init(cpu_irq[0]);
> +    } else {
> +        i8259 = i8259_init(cpu_irq[0]);
> +    }
> +
>      isa_irq_state->i8259 = i8259;
>      isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24);
>  
> diff --git a/hw/pc.h b/hw/pc.h
> index 4c9b4c3..3d79b9d 100644
> --- a/hw/pc.h
> +++ b/hw/pc.h
> @@ -34,6 +34,7 @@ uint32_t pic_intack_read(PicState2 *s);
>  void pic_info(Monitor *mon);
>  void irq_info(Monitor *mon);
>  
> +qemu_irq *kvm_i8259_init(qemu_irq parent_irq);
>  /* APIC */
>  typedef struct IOAPICState IOAPICState;
>  void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
> diff --git a/kvm-all.c b/kvm-all.c
> index fc542f3..c46a411 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -391,7 +391,6 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
>      return ret;
>  }
>  
> -#ifdef KVM_CAP_IRQCHIP
>  int kvm_set_irqchip(struct kvm_irqchip *chip)
>  {
>      if (!kvm_state->irqchip_in_kernel) {
> @@ -409,7 +408,30 @@ int kvm_get_irqchip(struct kvm_irqchip *chip)
>  
>      return kvm_vm_ioctl(kvm_state, KVM_GET_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);
>   

On S390X:

/suse/agraf/work/kvm-s390/qemu.works/kvm-all.c: In function ‘kvm_set_irq’:
/suse/agraf/work/kvm-s390/qemu.works/kvm-all.c:425: error:
‘KVM_IRQ_LINE_STATUS’ undeclared (first use in this function)
/suse/agraf/work/kvm-s390/qemu.works/kvm-all.c:425: error: (Each
undeclared identifier is reported only once
/suse/agraf/work/kvm-s390/qemu.works/kvm-all.c:425: error: for each
function it appears in.)
/suse/agraf/work/kvm-s390/qemu.works/kvm-all.c:431: error: ‘struct
kvm_irq_level’ has no member named ‘status’


Alex

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm
  2009-12-01 16:49         ` [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm Alexander Graf
@ 2009-12-01 17:15           ` Glauber Costa
  0 siblings, 0 replies; 13+ messages in thread
From: Glauber Costa @ 2009-12-01 17:15 UTC (permalink / raw)
  To: Alexander Graf; +Cc: aliguori, qemu-devel

> 
> On S390X:
> 
> /suse/agraf/work/kvm-s390/qemu.works/kvm-all.c: In function ‘kvm_set_irq’:
> /suse/agraf/work/kvm-s390/qemu.works/kvm-all.c:425: error:
> ‘KVM_IRQ_LINE_STATUS’ undeclared (first use in this function)
> /suse/agraf/work/kvm-s390/qemu.works/kvm-all.c:425: error: (Each
> undeclared identifier is reported only once
> /suse/agraf/work/kvm-s390/qemu.works/kvm-all.c:425: error: for each
> function it appears in.)
> /suse/agraf/work/kvm-s390/qemu.works/kvm-all.c:431: error: ‘struct
> kvm_irq_level’ has no member named ‘status’

Yeah.

As we talked, I tested all targets, but only in x86 hosts, which is what I
have handy. I will re-send another version

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2009-12-01 17:15 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-16 17:11 [Qemu-devel] [PATCH v2 0/9] in-kernel irqchip Glauber Costa
2009-11-16 17:11 ` [Qemu-devel] [PATCH v2 1/9] introduce VMSTATE_U64 Glauber Costa
2009-11-16 17:12   ` [Qemu-devel] [PATCH v2 2/9] Provide ioapic-kvm Glauber Costa
2009-11-16 17:12     ` [Qemu-devel] [PATCH v2 3/9] provide apic_set_irq_delivered Glauber Costa
2009-11-16 17:12       ` [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm Glauber Costa
2009-11-16 17:12         ` [Qemu-devel] [PATCH v2 5/9] Don't call apic functions directly from kvm code Glauber Costa
2009-11-16 17:12           ` [Qemu-devel] [PATCH v2 6/9] export kvm_put_mp_state Glauber Costa
2009-11-16 17:12             ` [Qemu-devel] [PATCH v2 7/9] provide apic-kvm Glauber Costa
2009-11-16 17:12               ` [Qemu-devel] [PATCH v2 8/9] Initialize in-kernel irqchip Glauber Costa
2009-11-16 17:12                 ` [Qemu-devel] [PATCH v2 9/9] Do GSI routing Glauber Costa
2009-12-01 16:44               ` [Qemu-devel] [PATCH v2 7/9] provide apic-kvm Alexander Graf
2009-12-01 16:49         ` [Qemu-devel] [PATCH v2 4/9] provide i8259-kvm Alexander Graf
2009-12-01 17:15           ` Glauber Costa

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.