[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 06/16] i8259: Introduce backend/frontend infrastr
From: |
Jan Kiszka |
Subject: |
[Qemu-devel] [PATCH v3 06/16] i8259: Introduce backend/frontend infrastructure for KVM reuse |
Date: |
Tue, 6 Dec 2011 13:58:06 +0100 |
Analogously to the APIC, we will reuse some parts of the user space
i8259 model for KVM. Again, we create a PIC backend infrastructure and
provide hooks for init, reset, and vmload/save. This also introduces a
common helper to instantiate a single i8259 chip from the cascade-
creating i8259_init function.
Signed-off-by: Jan Kiszka <address@hidden>
---
Makefile.objs | 2 +-
hw/i8259.c | 127 +++++---------------------------------
hw/i8259_common.c | 173 +++++++++++++++++++++++++++++++++++++++++++++++++++
hw/i8259_internal.h | 82 ++++++++++++++++++++++++
4 files changed, 271 insertions(+), 113 deletions(-)
create mode 100644 hw/i8259_common.c
create mode 100644 hw/i8259_internal.h
diff --git a/Makefile.objs b/Makefile.objs
index 01587c8..5372eec 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -220,7 +220,7 @@ hw-obj-$(CONFIG_APPLESMC) += applesmc.o
hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o
-hw-obj-$(CONFIG_I8259) += i8259.o
+hw-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
# PPC devices
hw-obj-$(CONFIG_PREP_PCI) += prep_pci.o
diff --git a/hw/i8259.c b/hw/i8259.c
index ab519de..413802c 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -26,6 +26,7 @@
#include "isa.h"
#include "monitor.h"
#include "qemu-timer.h"
+#include "i8259_internal.h"
/* debug PIC */
//#define DEBUG_PIC
@@ -40,33 +41,6 @@
//#define DEBUG_IRQ_LATENCY
//#define DEBUG_IRQ_COUNT
-struct PicState {
- ISADevice dev;
- uint8_t last_irr; /* edge detection */
- uint8_t irr; /* interrupt request register */
- uint8_t imr; /* interrupt mask register */
- uint8_t isr; /* interrupt service register */
- uint8_t priority_add; /* highest irq priority */
- uint8_t irq_base;
- uint8_t read_reg_select;
- uint8_t poll;
- uint8_t special_mask;
- uint8_t init_state;
- uint8_t auto_eoi;
- uint8_t rotate_on_auto_eoi;
- uint8_t special_fully_nested_mode;
- uint8_t init4; /* true if 4 byte init */
- uint8_t single_mode; /* true if slave pic is not initialized */
- uint8_t elcr; /* PIIX edge/trigger selection*/
- uint8_t elcr_mask;
- qemu_irq int_out[1];
- uint32_t master; /* reflects /SP input pin */
- uint32_t iobase;
- uint32_t elcr_addr;
- MemoryRegion base_io;
- MemoryRegion elcr_io;
-};
-
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
static int irq_level[16];
#endif
@@ -248,29 +222,12 @@ int pic_read_irq(PicState *s)
static void pic_init_reset(PicState *s)
{
- 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;
- s->single_mode = 0;
- /* Note: ELCR is not reset */
+ pic_reset_internal(s);
pic_update_irq(s);
}
-static void pic_reset(DeviceState *dev)
+static void pic_reset(PicState *s)
{
- PicState *s = container_of(dev, PicState, dev.qdev);
-
pic_init_reset(s);
s->elcr = 0;
}
@@ -418,32 +375,6 @@ static uint64_t elcr_ioport_read(void *opaque,
target_phys_addr_t addr,
return s->elcr;
}
-static const VMStateDescription vmstate_pic = {
- .name = "i8259",
- .version_id = 1,
- .minimum_version_id = 1,
- .minimum_version_id_old = 1,
- .fields = (VMStateField[]) {
- VMSTATE_UINT8(last_irr, PicState),
- VMSTATE_UINT8(irr, PicState),
- VMSTATE_UINT8(imr, PicState),
- VMSTATE_UINT8(isr, PicState),
- VMSTATE_UINT8(priority_add, PicState),
- VMSTATE_UINT8(irq_base, PicState),
- VMSTATE_UINT8(read_reg_select, PicState),
- VMSTATE_UINT8(poll, PicState),
- VMSTATE_UINT8(special_mask, PicState),
- VMSTATE_UINT8(init_state, PicState),
- VMSTATE_UINT8(auto_eoi, PicState),
- VMSTATE_UINT8(rotate_on_auto_eoi, PicState),
- VMSTATE_UINT8(special_fully_nested_mode, PicState),
- VMSTATE_UINT8(init4, PicState),
- VMSTATE_UINT8(single_mode, PicState),
- VMSTATE_UINT8(elcr, PicState),
- VMSTATE_END_OF_LIST()
- }
-};
-
static const MemoryRegionOps pic_base_ioport_ops = {
.read = pic_ioport_read,
.write = pic_ioport_write,
@@ -462,24 +393,13 @@ static const MemoryRegionOps pic_elcr_ioport_ops = {
},
};
-static int pic_initfn(ISADevice *dev)
+static void pic_backend_init(PicState *s)
{
- PicState *s = DO_UPCAST(PicState, dev, dev);
-
memory_region_init_io(&s->base_io, &pic_base_ioport_ops, s, "pic", 2);
memory_region_init_io(&s->elcr_io, &pic_elcr_ioport_ops, s, "elcr", 1);
- isa_register_ioport(NULL, &s->base_io, s->iobase);
- if (s->elcr_addr != -1) {
- isa_register_ioport(NULL, &s->elcr_io, s->elcr_addr);
- }
-
- qdev_init_gpio_out(&dev->qdev, s->int_out, ARRAY_SIZE(s->int_out));
- qdev_init_gpio_in(&dev->qdev, pic_set_irq, 8);
-
- qdev_set_legacy_instance_id(&dev->qdev, s->iobase, 1);
-
- return 0;
+ qdev_init_gpio_out(&s->dev.qdev, s->int_out, ARRAY_SIZE(s->int_out));
+ qdev_init_gpio_in(&s->dev.qdev, pic_set_irq, 8);
}
void pic_info(Monitor *mon)
@@ -526,12 +446,7 @@ qemu_irq *i8259_init(qemu_irq parent_irq)
irq_set = g_malloc(ISA_NUM_IRQS * sizeof(qemu_irq));
- dev = isa_create("isa-i8259");
- qdev_prop_set_uint32(&dev->qdev, "iobase", 0x20);
- qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d0);
- qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xf8);
- qdev_prop_set_bit(&dev->qdev, "master", true);
- qdev_init_nofail(&dev->qdev);
+ dev = i8259_init_chip(true, "QEMU");
qdev_connect_gpio_out(&dev->qdev, 0, parent_irq);
for (i = 0 ; i < 8; i++) {
@@ -540,11 +455,7 @@ qemu_irq *i8259_init(qemu_irq parent_irq)
isa_pic = DO_UPCAST(PicState, dev, dev);
- dev = isa_create("isa-i8259");
- qdev_prop_set_uint32(&dev->qdev, "iobase", 0xa0);
- qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d1);
- qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xde);
- qdev_init_nofail(&dev->qdev);
+ dev = i8259_init_chip(false, "QEMU");
qdev_connect_gpio_out(&dev->qdev, 0, irq_set[2]);
for (i = 0 ; i < 8; i++) {
@@ -556,24 +467,16 @@ qemu_irq *i8259_init(qemu_irq parent_irq)
return irq_set;
}
-static ISADeviceInfo i8259_info = {
- .qdev.name = "isa-i8259",
- .qdev.size = sizeof(PicState),
- .qdev.vmsd = &vmstate_pic,
- .qdev.reset = pic_reset,
- .qdev.no_user = 1,
- .init = pic_initfn,
- .qdev.props = (Property[]) {
- DEFINE_PROP_HEX32("iobase", PicState, iobase, -1),
- DEFINE_PROP_HEX32("elcr_addr", PicState, elcr_addr, -1),
- DEFINE_PROP_HEX8("elcr_mask", PicState, elcr_mask, -1),
- DEFINE_PROP_BIT("master", PicState, master, 0, false),
- DEFINE_PROP_END_OF_LIST(),
- },
+static PICBackend pic_backend = {
+ .name = "QEMU",
+ .init = pic_backend_init,
+ .reset = pic_reset,
};
static void pic_register(void)
{
- isa_qdev_register(&i8259_info);
+ pic_register_device();
+ pic_register_backend(&pic_backend);
}
+
device_init(pic_register)
diff --git a/hw/i8259_common.c b/hw/i8259_common.c
new file mode 100644
index 0000000..4abda09
--- /dev/null
+++ b/hw/i8259_common.c
@@ -0,0 +1,173 @@
+/*
+ * QEMU 8259 - common bits of emulated and KVM kernel model
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "pc.h"
+#include "i8259_internal.h"
+
+static QSIMPLEQ_HEAD(, PICBackend) backends =
+ QSIMPLEQ_HEAD_INITIALIZER(backends);
+
+void pic_reset_internal(PicState *s)
+{
+ 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;
+ s->single_mode = 0;
+ /* Note: ELCR is not reset */
+}
+
+static void pic_dispatch_pre_save(void *opaque)
+{
+ PicState *s = opaque;
+
+ if (s->backend->pre_save) {
+ s->backend->pre_save(s);
+ }
+}
+
+static int pic_dispatch_post_load(void *opaque, int version_id)
+{
+ PicState *s = opaque;
+
+ if (s->backend->post_load) {
+ s->backend->post_load(s);
+ }
+ return 0;
+}
+
+static const VMStateDescription vmstate_pic = {
+ .name = "i8259",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .pre_save = pic_dispatch_pre_save,
+ .post_load = pic_dispatch_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(last_irr, PicState),
+ VMSTATE_UINT8(irr, PicState),
+ VMSTATE_UINT8(imr, PicState),
+ VMSTATE_UINT8(isr, PicState),
+ VMSTATE_UINT8(priority_add, PicState),
+ VMSTATE_UINT8(irq_base, PicState),
+ VMSTATE_UINT8(read_reg_select, PicState),
+ VMSTATE_UINT8(poll, PicState),
+ VMSTATE_UINT8(special_mask, PicState),
+ VMSTATE_UINT8(init_state, PicState),
+ VMSTATE_UINT8(auto_eoi, PicState),
+ VMSTATE_UINT8(rotate_on_auto_eoi, PicState),
+ VMSTATE_UINT8(special_fully_nested_mode, PicState),
+ VMSTATE_UINT8(init4, PicState),
+ VMSTATE_UINT8(single_mode, PicState),
+ VMSTATE_UINT8(elcr, PicState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static int pic_initfn(ISADevice *dev)
+{
+ PicState *s = DO_UPCAST(PicState, dev, dev);
+ PICBackend *b;
+
+ QSIMPLEQ_FOREACH(b, &backends, entry) {
+ if (strcmp(b->name, s->backend_name) == 0) {
+ s->backend = b;
+ break;
+ }
+ }
+ if (!s->backend) {
+ hw_error("PIC backend '%s' not found!", s->backend_name);
+ exit(1);
+ }
+
+ b->init(s);
+
+ isa_register_ioport(NULL, &s->base_io, s->iobase);
+ if (s->elcr_addr != -1) {
+ isa_register_ioport(NULL, &s->elcr_io, s->elcr_addr);
+ }
+
+ qdev_set_legacy_instance_id(&s->dev.qdev, s->iobase, 1);
+
+ return 0;
+}
+
+static void pic_reset(DeviceState *dev)
+{
+ PicState *s = container_of(dev, PicState, dev.qdev);
+
+ s->backend->reset(s);
+}
+
+static ISADeviceInfo i8259_info = {
+ .qdev.name = "isa-i8259",
+ .qdev.size = sizeof(PicState),
+ .qdev.vmsd = &vmstate_pic,
+ .qdev.reset = pic_reset,
+ .qdev.no_user = 1,
+ .init = pic_initfn,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_HEX32("iobase", PicState, iobase, -1),
+ DEFINE_PROP_HEX32("elcr_addr", PicState, elcr_addr, -1),
+ DEFINE_PROP_HEX8("elcr_mask", PicState, elcr_mask, -1),
+ DEFINE_PROP_BIT("master", PicState, master, 0, false),
+ DEFINE_PROP_STRING("backend", PicState, backend_name),
+ DEFINE_PROP_END_OF_LIST(),
+ },
+};
+
+void pic_register_backend(PICBackend *backend)
+{
+ QSIMPLEQ_INSERT_TAIL(&backends, backend, entry);
+}
+
+void pic_register_device(void)
+{
+ isa_qdev_register(&i8259_info);
+}
+
+ISADevice *i8259_init_chip(bool master, const char *backend)
+{
+ ISADevice *dev;
+
+ dev = isa_create("isa-i8259");
+ qdev_prop_set_uint32(&dev->qdev, "iobase", 0x20);
+ qdev_prop_set_uint32(&dev->qdev, "elcr_addr", 0x4d0);
+ qdev_prop_set_uint8(&dev->qdev, "elcr_mask", 0xf8);
+ qdev_prop_set_bit(&dev->qdev, "master", master);
+ qdev_prop_set_string(&dev->qdev, "backend", g_strdup(backend));
+ qdev_init_nofail(&dev->qdev);
+
+ return dev;
+}
diff --git a/hw/i8259_internal.h b/hw/i8259_internal.h
new file mode 100644
index 0000000..e11c312
--- /dev/null
+++ b/hw/i8259_internal.h
@@ -0,0 +1,82 @@
+/*
+ * QEMU 8259 - internal interfaces
+ *
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_I8259_INTERNAL_H
+#define QEMU_I8259_INTERNAL_H
+
+#include "hw.h"
+#include "pc.h"
+#include "isa.h"
+#include "qemu-queue.h"
+
+typedef struct PICBackend PICBackend;
+
+struct PICBackend {
+ const char *name;
+ void (*init)(PicState *s);
+ void (*reset)(PicState *s);
+ void (*pre_save)(PicState *s);
+ void (*post_load)(PicState *s);
+
+ QSIMPLEQ_ENTRY(PICBackend) entry;
+};
+
+struct PicState {
+ ISADevice dev;
+ uint8_t last_irr; /* edge detection */
+ uint8_t irr; /* interrupt request register */
+ uint8_t imr; /* interrupt mask register */
+ uint8_t isr; /* interrupt service register */
+ uint8_t priority_add; /* highest irq priority */
+ uint8_t irq_base;
+ uint8_t read_reg_select;
+ uint8_t poll;
+ uint8_t special_mask;
+ uint8_t init_state;
+ uint8_t auto_eoi;
+ uint8_t rotate_on_auto_eoi;
+ uint8_t special_fully_nested_mode;
+ uint8_t init4; /* true if 4 byte init */
+ uint8_t single_mode; /* true if slave pic is not initialized */
+ uint8_t elcr; /* PIIX edge/trigger selection*/
+ uint8_t elcr_mask;
+ qemu_irq int_out[1];
+ uint32_t master; /* reflects /SP input pin */
+ uint32_t iobase;
+ uint32_t elcr_addr;
+ MemoryRegion base_io;
+ MemoryRegion elcr_io;
+
+ char *backend_name;
+ PICBackend *backend;
+};
+
+void pic_register_device(void);
+void pic_register_backend(PICBackend *backend);
+
+void pic_reset_internal(PicState *s);
+
+ISADevice *i8259_init_chip(bool master, const char *backend);
+
+#endif /* !QEMU_I8259_INTERNAL_H */
--
1.7.3.4
- [Qemu-devel] [PATCH v3 01/16] msi: Generalize msix_supported to msi_supported, (continued)
- [Qemu-devel] [PATCH v3 01/16] msi: Generalize msix_supported to msi_supported, Jan Kiszka, 2011/12/06
- [Qemu-devel] [PATCH v3 10/16] memory: Introduce memory_region_init_reservation, Jan Kiszka, 2011/12/06
- [Qemu-devel] [PATCH v3 07/16] ioapic: Convert to memory API, Jan Kiszka, 2011/12/06
- [Qemu-devel] [PATCH v3 11/16] kvm: Introduce core services for in-kernel irqchip support, Jan Kiszka, 2011/12/06
- [Qemu-devel] [PATCH v3 13/16] kvm: x86: Add user space part for in-kernel APIC, Jan Kiszka, 2011/12/06
- [Qemu-devel] [PATCH v3 15/16] kvm: x86: Add user space part for in-kernel IOAPIC, Jan Kiszka, 2011/12/06
- [Qemu-devel] [PATCH v3 08/16] ioapic: Reject non-dword accesses to IOWIN register, Jan Kiszka, 2011/12/06
- [Qemu-devel] [PATCH v3 14/16] kvm: x86: Add user space part for in-kernel i8259, Jan Kiszka, 2011/12/06
- [Qemu-devel] [PATCH v3 16/16] kvm: Arm in-kernel irqchip support, Jan Kiszka, 2011/12/06
- [Qemu-devel] [PATCH v3 03/16] apic: Stop timer on reset, Jan Kiszka, 2011/12/06
- [Qemu-devel] [PATCH v3 06/16] i8259: Introduce backend/frontend infrastructure for KVM reuse,
Jan Kiszka <=
- Re: [Qemu-devel] [PATCH v3 00/16] uq/master: Introduce basic irqchip support, Avi Kivity, 2011/12/06