diff mbox series

[5/6] Add the aehd-i8259 device type.

Message ID 20230303022618.4098825-5-hshan@google.com
State New
Headers show
Series Adding the Android Emulator hypervisor driver accelerator | expand

Commit Message

Haitao Shan March 3, 2023, 2:26 a.m. UTC
The aehd-i8259 device type represents the AEHD in kernel PICs.
The irqchips should be always in kernel when AEHD is used.

Signed-off-by: Haitao Shan <hshan@google.com>
---
 hw/i386/aehd/i8259.c     | 165 +++++++++++++++++++++++++++++++++++++++
 hw/i386/aehd/meson.build |   1 +
 hw/i386/pc.c             |   2 +
 include/hw/intc/i8259.h  |   1 +
 4 files changed, 169 insertions(+)
 create mode 100644 hw/i386/aehd/i8259.c

Comments

Philippe Mathieu-Daudé March 3, 2023, 10:09 a.m. UTC | #1
On 3/3/23 03:26, Haitao Shan wrote:
> The aehd-i8259 device type represents the AEHD in kernel PICs.
> The irqchips should be always in kernel when AEHD is used.
> 
> Signed-off-by: Haitao Shan <hshan@google.com>
> ---
>   hw/i386/aehd/i8259.c     | 165 +++++++++++++++++++++++++++++++++++++++
>   hw/i386/aehd/meson.build |   1 +
>   hw/i386/pc.c             |   2 +
>   include/hw/intc/i8259.h  |   1 +
>   4 files changed, 169 insertions(+)
>   create mode 100644 hw/i386/aehd/i8259.c


> +static void aehd_pic_reset(DeviceState *dev)
> +{
> +    PICCommonState *s = PIC_COMMON(dev);
> +
> +    s->elcr = 0;
> +    pic_reset_common(s);
> +
> +    aehd_pic_put(s);
> +}
> +
> +static void aehd_pic_set_irq(void *opaque, int irq, int level)
> +{
> +    pic_stat_update_irq(irq, level);
> +    aehd_set_irq(aehd_state, irq, level);
> +}
> +
> +static void aehd_pic_realize(DeviceState *dev, Error **errp)
> +{
> +    PICCommonState *s = PIC_COMMON(dev);
> +    AEHDPICClass *kpc = AEHD_PIC_GET_CLASS(dev);
> +
> +    memory_region_init_io(&s->base_io, OBJECT(dev), NULL, NULL, "aehd-pic", 2);
> +    memory_region_init_io(&s->elcr_io, OBJECT(dev), NULL, NULL, "aehd-elcr", 1);
> +
> +
> +    kpc->parent_realize(dev, errp);
> +}

Again, this should be drastically simplified by adding a some fields &
handlers to the abstract TYPE_INKERNEL_IOAPIC class:

struct InKernelAPICCommonClass {
     APICCommonClass parent_class;

     void (*pic_put)(PICCommonState *s)
     ...
};

Eventually this could even belong to APICCommonClass, but I haven't
checked in detail.
Haitao Shan March 3, 2023, 6:56 p.m. UTC | #2
On Fri, Mar 3, 2023 at 2:09 AM Philippe Mathieu-Daudé <philmd@linaro.org> wrote:
>
> On 3/3/23 03:26, Haitao Shan wrote:
> > The aehd-i8259 device type represents the AEHD in kernel PICs.
> > The irqchips should be always in kernel when AEHD is used.
> >
> > Signed-off-by: Haitao Shan <hshan@google.com>
> > ---
> >   hw/i386/aehd/i8259.c     | 165 +++++++++++++++++++++++++++++++++++++++
> >   hw/i386/aehd/meson.build |   1 +
> >   hw/i386/pc.c             |   2 +
> >   include/hw/intc/i8259.h  |   1 +
> >   4 files changed, 169 insertions(+)
> >   create mode 100644 hw/i386/aehd/i8259.c
>
>
> > +static void aehd_pic_reset(DeviceState *dev)
> > +{
> > +    PICCommonState *s = PIC_COMMON(dev);
> > +
> > +    s->elcr = 0;
> > +    pic_reset_common(s);
> > +
> > +    aehd_pic_put(s);
> > +}
> > +
> > +static void aehd_pic_set_irq(void *opaque, int irq, int level)
> > +{
> > +    pic_stat_update_irq(irq, level);
> > +    aehd_set_irq(aehd_state, irq, level);
> > +}
> > +
> > +static void aehd_pic_realize(DeviceState *dev, Error **errp)
> > +{
> > +    PICCommonState *s = PIC_COMMON(dev);
> > +    AEHDPICClass *kpc = AEHD_PIC_GET_CLASS(dev);
> > +
> > +    memory_region_init_io(&s->base_io, OBJECT(dev), NULL, NULL, "aehd-pic", 2);
> > +    memory_region_init_io(&s->elcr_io, OBJECT(dev), NULL, NULL, "aehd-elcr", 1);
> > +
> > +
> > +    kpc->parent_realize(dev, errp);
> > +}
>
> Again, this should be drastically simplified by adding a some fields &
> handlers to the abstract TYPE_INKERNEL_IOAPIC class:
>
> struct InKernelAPICCommonClass {
>      APICCommonClass parent_class;
>
>      void (*pic_put)(PICCommonState *s)
>      ...
> };
>
> Eventually this could even belong to APICCommonClass, but I haven't
> checked in detail.
I got your idea now. I will address it in the next version. And this also
replies to the APIC and IOAPIC patch too.
diff mbox series

Patch

diff --git a/hw/i386/aehd/i8259.c b/hw/i386/aehd/i8259.c
new file mode 100644
index 0000000000..9a18e824dc
--- /dev/null
+++ b/hw/i386/aehd/i8259.c
@@ -0,0 +1,165 @@ 
+/*
+ * AEHD in-kernel PIC (i8259) support
+ *
+ * Copyright (c) 2011 Siemens AG
+ *
+ * Authors:
+ *  Jan Kiszka          <jan.kiszka@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "hw/isa/i8259_internal.h"
+#include "hw/i386/apic_internal.h"
+#include "sysemu/aehd.h"
+#include "sysemu/aehd-interface.h"
+
+#define TYPE_AEHD_I8259 "aehd-i8259"
+#define AEHD_PIC_CLASS(class) \
+    OBJECT_CLASS_CHECK(AEHDPICClass, (class), TYPE_AEHD_I8259)
+#define AEHD_PIC_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(AEHDPICClass, (obj), TYPE_AEHD_I8259)
+
+/**
+ * AEHDPICClass:
+ * @parent_realize: The parent's realizefn.
+ */
+typedef struct AEHDPICClass {
+    PICCommonClass parent_class;
+
+    DeviceRealize parent_realize;
+} AEHDPICClass;
+
+static void aehd_pic_get(PICCommonState *s)
+{
+    struct aehd_irqchip chip;
+    struct aehd_pic_state *aepic;
+    int ret;
+
+    chip.chip_id = s->master ? AEHD_IRQCHIP_PIC_MASTER : AEHD_IRQCHIP_PIC_SLAVE;
+    ret = aehd_vm_ioctl(aehd_state, AEHD_GET_IRQCHIP, &chip, sizeof(chip),
+                        &chip, sizeof(chip));
+    if (ret < 0) {
+        fprintf(stderr, "AEHD_GET_IRQCHIP failed: %s\n", strerror(ret));
+        abort();
+    }
+
+    aepic = &chip.chip.pic;
+
+    s->last_irr = aepic->last_irr;
+    s->irr = aepic->irr;
+    s->imr = aepic->imr;
+    s->isr = aepic->isr;
+    s->priority_add = aepic->priority_add;
+    s->irq_base = aepic->irq_base;
+    s->read_reg_select = aepic->read_reg_select;
+    s->poll = aepic->poll;
+    s->special_mask = aepic->special_mask;
+    s->init_state = aepic->init_state;
+    s->auto_eoi = aepic->auto_eoi;
+    s->rotate_on_auto_eoi = aepic->rotate_on_auto_eoi;
+    s->special_fully_nested_mode = aepic->special_fully_nested_mode;
+    s->init4 = aepic->init4;
+    s->elcr = aepic->elcr;
+    s->elcr_mask = aepic->elcr_mask;
+}
+
+static void aehd_pic_put(PICCommonState *s)
+{
+    struct aehd_irqchip chip;
+    struct aehd_pic_state *aepic;
+    int ret;
+
+    chip.chip_id = s->master ? AEHD_IRQCHIP_PIC_MASTER : AEHD_IRQCHIP_PIC_SLAVE;
+
+    aepic = &chip.chip.pic;
+
+    aepic->last_irr = s->last_irr;
+    aepic->irr = s->irr;
+    aepic->imr = s->imr;
+    aepic->isr = s->isr;
+    aepic->priority_add = s->priority_add;
+    aepic->irq_base = s->irq_base;
+    aepic->read_reg_select = s->read_reg_select;
+    aepic->poll = s->poll;
+    aepic->special_mask = s->special_mask;
+    aepic->init_state = s->init_state;
+    aepic->auto_eoi = s->auto_eoi;
+    aepic->rotate_on_auto_eoi = s->rotate_on_auto_eoi;
+    aepic->special_fully_nested_mode = s->special_fully_nested_mode;
+    aepic->init4 = s->init4;
+    aepic->elcr = s->elcr;
+    aepic->elcr_mask = s->elcr_mask;
+
+    ret = aehd_vm_ioctl(aehd_state, AEHD_SET_IRQCHIP,
+                        &chip, sizeof(chip), NULL, 0);
+    if (ret < 0) {
+        fprintf(stderr, "AEHD_GET_IRQCHIP failed: %s\n", strerror(ret));
+        abort();
+    }
+}
+
+static void aehd_pic_reset(DeviceState *dev)
+{
+    PICCommonState *s = PIC_COMMON(dev);
+
+    s->elcr = 0;
+    pic_reset_common(s);
+
+    aehd_pic_put(s);
+}
+
+static void aehd_pic_set_irq(void *opaque, int irq, int level)
+{
+    pic_stat_update_irq(irq, level);
+    aehd_set_irq(aehd_state, irq, level);
+}
+
+static void aehd_pic_realize(DeviceState *dev, Error **errp)
+{
+    PICCommonState *s = PIC_COMMON(dev);
+    AEHDPICClass *kpc = AEHD_PIC_GET_CLASS(dev);
+
+    memory_region_init_io(&s->base_io, OBJECT(dev), NULL, NULL, "aehd-pic", 2);
+    memory_region_init_io(&s->elcr_io, OBJECT(dev), NULL, NULL, "aehd-elcr", 1);
+
+
+    kpc->parent_realize(dev, errp);
+}
+
+qemu_irq *aehd_i8259_init(ISABus *bus)
+{
+    i8259_init_chip(TYPE_AEHD_I8259, bus, true);
+    i8259_init_chip(TYPE_AEHD_I8259, bus, false);
+
+    return qemu_allocate_irqs(aehd_pic_set_irq, NULL, ISA_NUM_IRQS);
+}
+
+static void aehd_i8259_class_init(ObjectClass *klass, void *data)
+{
+    AEHDPICClass *kpc = AEHD_PIC_CLASS(klass);
+    PICCommonClass *k = PIC_COMMON_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset     = aehd_pic_reset;
+    kpc->parent_realize = dc->realize;
+    dc->realize   = aehd_pic_realize;
+    k->pre_save   = aehd_pic_get;
+    k->post_load  = aehd_pic_put;
+}
+
+static const TypeInfo aehd_i8259_info = {
+    .name = TYPE_AEHD_I8259,
+    .parent = TYPE_PIC_COMMON,
+    .instance_size = sizeof(PICCommonState),
+    .class_init = aehd_i8259_class_init,
+    .class_size = sizeof(AEHDPICClass),
+};
+
+static void aehd_pic_register_types(void)
+{
+    type_register_static(&aehd_i8259_info);
+}
+
+type_init(aehd_pic_register_types)
diff --git a/hw/i386/aehd/meson.build b/hw/i386/aehd/meson.build
index 259c9f66f7..90c9a3e2b6 100644
--- a/hw/i386/aehd/meson.build
+++ b/hw/i386/aehd/meson.build
@@ -1,5 +1,6 @@ 
 i386_aehd_ss = ss.source_set()
 i386_aehd_ss.add(when: 'CONFIG_APIC', if_true: files('apic.c'))
+i386_aehd_ss.add(when: 'CONFIG_I8259', if_true: files('i8259.c'))
 i386_aehd_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic.c'))
 
 i386_ss.add_all(when: 'CONFIG_AEHD', if_true: i386_aehd_ss)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 59513a5c38..3b45f75fbd 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1356,6 +1356,8 @@  void pc_i8259_create(ISABus *isa_bus, qemu_irq *i8259_irqs)
 
     if (kvm_pic_in_kernel()) {
         i8259 = kvm_i8259_init(isa_bus);
+    } else if (aehd_enabled()) {
+        i8259 = aehd_i8259_init(isa_bus);
     } else if (xen_enabled()) {
         i8259 = xen_interrupt_controller_init();
     } else {
diff --git a/include/hw/intc/i8259.h b/include/hw/intc/i8259.h
index c412575775..5ce85ed590 100644
--- a/include/hw/intc/i8259.h
+++ b/include/hw/intc/i8259.h
@@ -14,6 +14,7 @@  extern PICCommonState *isa_pic;
  */
 qemu_irq *i8259_init(ISABus *bus, qemu_irq parent_irq_in);
 qemu_irq *kvm_i8259_init(ISABus *bus);
+qemu_irq *aehd_i8259_init(ISABus *bus);
 int pic_get_output(PICCommonState *s);
 int pic_read_irq(PICCommonState *s);