diff mbox series

[4/6] Add the aehd-ioapic device type.

Message ID 20230303022618.4098825-4-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-ioapic device type represents the AEHD in kernel IO-APIC.
The irqchips should be always in kernel when AEHD is used.

Signed-off-by: Haitao Shan <hshan@google.com>
---
 hw/i386/aehd/ioapic.c       | 164 ++++++++++++++++++++++++++++++++++++
 hw/i386/aehd/meson.build    |   1 +
 hw/i386/pc.c                |   3 +
 hw/i386/x86.c               |   3 +
 include/hw/intc/ioapic.h    |   1 +
 include/sysemu/aehd.h       |   4 +
 target/i386/aehd/aehd-all.c |  14 +++
 7 files changed, 190 insertions(+)
 create mode 100644 hw/i386/aehd/ioapic.c

Comments

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


> +static const TypeInfo aehd_ioapic_info = {
> +    .name  = TYPE_AEHD_IOAPIC,
> +    .parent = TYPE_IOAPIC_COMMON,

Instead of duplicating TYPE_KVM_IOAPIC, as a first step we should
extract the common code in an abstract TYPE_INKERNEL_IOAPIC object,
then TYPE_AEHD_IOAPIC inherits it.

> +    .instance_size = sizeof(AEHDIOAPICState),
> +    .class_init = aehd_ioapic_class_init,
> +};
diff mbox series

Patch

diff --git a/hw/i386/aehd/ioapic.c b/hw/i386/aehd/ioapic.c
new file mode 100644
index 0000000000..62ffb0172f
--- /dev/null
+++ b/hw/i386/aehd/ioapic.c
@@ -0,0 +1,164 @@ 
+/*
+ * AEHD in-kernel IOPIC 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 "monitor/monitor.h"
+#include "hw/i386/pc.h"
+#include "hw/qdev-properties.h"
+#include "hw/intc/ioapic_internal.h"
+#include "sysemu/aehd.h"
+#include "sysemu/aehd-interface.h"
+
+/* PC Utility function */
+void aehd_pc_setup_irq_routing(bool pci_enabled)
+{
+    AEHDState *s = aehd_state;
+    int i;
+
+    for (i = 0; i < 8; ++i) {
+        if (i == 2) {
+            continue;
+        }
+        aehd_irqchip_add_irq_route(s, i, AEHD_IRQCHIP_PIC_MASTER, i);
+    }
+    for (i = 8; i < 16; ++i) {
+        aehd_irqchip_add_irq_route(s, i, AEHD_IRQCHIP_PIC_SLAVE, i - 8);
+    }
+    if (pci_enabled) {
+        for (i = 0; i < 24; ++i) {
+            if (i == 0) {
+                aehd_irqchip_add_irq_route(s, i, AEHD_IRQCHIP_IOAPIC, 2);
+            } else if (i != 2) {
+                aehd_irqchip_add_irq_route(s, i, AEHD_IRQCHIP_IOAPIC, i);
+            }
+        }
+    }
+    aehd_irqchip_commit_routes(s);
+}
+
+typedef struct AEHDIOAPICState AEHDIOAPICState;
+
+struct AEHDIOAPICState {
+    IOAPICCommonState ioapic;
+    uint32_t aehd_gsi_base;
+};
+
+static void aehd_ioapic_get(IOAPICCommonState *s)
+{
+    struct aehd_irqchip chip;
+    struct aehd_ioapic_state *aioapic;
+    int ret, i;
+
+    chip.chip_id = AEHD_IRQCHIP_IOAPIC;
+    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();
+    }
+
+    aioapic = &chip.chip.ioapic;
+
+    s->id = aioapic->id;
+    s->ioregsel = aioapic->ioregsel;
+    s->irr = aioapic->irr;
+    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+        s->ioredtbl[i] = aioapic->redirtbl[i].bits;
+    }
+}
+
+static void aehd_ioapic_put(IOAPICCommonState *s)
+{
+    struct aehd_irqchip chip;
+    struct aehd_ioapic_state *aioapic;
+    int ret, i;
+
+    chip.chip_id = AEHD_IRQCHIP_IOAPIC;
+    aioapic = &chip.chip.ioapic;
+
+    aioapic->id = s->id;
+    aioapic->ioregsel = s->ioregsel;
+    aioapic->base_address = s->busdev.mmio[0].addr;
+    aioapic->irr = s->irr;
+    for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+        aioapic->redirtbl[i].bits = s->ioredtbl[i];
+    }
+
+    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_ioapic_reset(DeviceState *dev)
+{
+    IOAPICCommonState *s = IOAPIC_COMMON(dev);
+
+    ioapic_reset_common(dev);
+    aehd_ioapic_put(s);
+}
+
+static void aehd_ioapic_set_irq(void *opaque, int irq, int level)
+{
+    AEHDIOAPICState *s = opaque;
+
+    aehd_set_irq(aehd_state, s->aehd_gsi_base + irq, level);
+}
+
+static void aehd_ioapic_realize(DeviceState *dev, Error **errp)
+{
+    IOAPICCommonState *s = IOAPIC_COMMON(dev);
+
+    memory_region_init_io(&s->io_memory, OBJECT(dev), NULL, NULL,
+                          "aehd-ioapic", 0x1000);
+
+    /*
+     * AEHD ioapic only supports 0x11 now. This will only be used when
+     * we want to dump ioapic version.
+     */
+    s->version = 0x11;
+
+    qdev_init_gpio_in(dev, aehd_ioapic_set_irq, IOAPIC_NUM_PINS);
+}
+
+static Property aehd_ioapic_properties[] = {
+    DEFINE_PROP_UINT32("gsi_base", AEHDIOAPICState, aehd_gsi_base, 0),
+    DEFINE_PROP_END_OF_LIST()
+};
+
+static void aehd_ioapic_class_init(ObjectClass *klass, void *data)
+{
+    IOAPICCommonClass *k = IOAPIC_COMMON_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    k->realize   = aehd_ioapic_realize;
+    k->pre_save  = aehd_ioapic_get;
+    k->post_load = aehd_ioapic_put;
+    dc->reset    = aehd_ioapic_reset;
+    device_class_set_props(dc, aehd_ioapic_properties);
+}
+
+static const TypeInfo aehd_ioapic_info = {
+    .name  = TYPE_AEHD_IOAPIC,
+    .parent = TYPE_IOAPIC_COMMON,
+    .instance_size = sizeof(AEHDIOAPICState),
+    .class_init = aehd_ioapic_class_init,
+};
+
+static void aehd_ioapic_register_types(void)
+{
+    type_register_static(&aehd_ioapic_info);
+}
+
+type_init(aehd_ioapic_register_types)
diff --git a/hw/i386/aehd/meson.build b/hw/i386/aehd/meson.build
index 1749860954..259c9f66f7 100644
--- a/hw/i386/aehd/meson.build
+++ b/hw/i386/aehd/meson.build
@@ -1,4 +1,5 @@ 
 i386_aehd_ss = ss.source_set()
 i386_aehd_ss.add(when: 'CONFIG_APIC', if_true: files('apic.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 992951c107..59513a5c38 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -58,6 +58,7 @@ 
 #include "sysemu/tcg.h"
 #include "sysemu/numa.h"
 #include "sysemu/kvm.h"
+#include "sysemu/aehd.h"
 #include "sysemu/xen.h"
 #include "sysemu/reset.h"
 #include "sysemu/runstate.h"
@@ -405,6 +406,8 @@  GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled)
     s = g_new0(GSIState, 1);
     if (kvm_ioapic_in_kernel()) {
         kvm_pc_setup_irq_routing(pci_enabled);
+    } else if (aehd_enabled()) {
+        aehd_pc_setup_irq_routing(pci_enabled);
     }
     *irqs = qemu_allocate_irqs(gsi_handler, s, IOAPIC_NUM_PINS);
 
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index c44846f47b..ffc6f97ce0 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -34,6 +34,7 @@ 
 #include "qapi/visitor.h"
 #include "sysemu/qtest.h"
 #include "sysemu/whpx.h"
+#include "sysemu/aehd.h"
 #include "sysemu/numa.h"
 #include "sysemu/replay.h"
 #include "sysemu/reset.h"
@@ -628,6 +629,8 @@  void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name)
     assert(parent_name);
     if (kvm_ioapic_in_kernel()) {
         dev = qdev_new(TYPE_KVM_IOAPIC);
+    } else if (aehd_enabled()) {
+        dev = qdev_new(TYPE_AEHD_IOAPIC);
     } else {
         dev = qdev_new(TYPE_IOAPIC);
     }
diff --git a/include/hw/intc/ioapic.h b/include/hw/intc/ioapic.h
index aa122e25e3..6f46543e24 100644
--- a/include/hw/intc/ioapic.h
+++ b/include/hw/intc/ioapic.h
@@ -26,6 +26,7 @@ 
 #define IO_APIC_SECONDARY_IRQBASE 24 /* primary 0 -> 23, secondary 24 -> 47 */
 
 #define TYPE_KVM_IOAPIC "kvm-ioapic"
+#define TYPE_AEHD_IOAPIC "aehd-ioapic"
 #define TYPE_IOAPIC "ioapic"
 
 void ioapic_eoi_broadcast(int vector);
diff --git a/include/sysemu/aehd.h b/include/sysemu/aehd.h
index 87fa2f8362..534dd95e3c 100644
--- a/include/sysemu/aehd.h
+++ b/include/sysemu/aehd.h
@@ -66,6 +66,8 @@  int aehd_arch_release_virq_post(int virq);
 int aehd_set_irq(AEHDState *s, int irq, int level);
 int aehd_irqchip_send_msi(AEHDState *s, MSIMessage msg);
 
+void aehd_irqchip_add_irq_route(AEHDState *s, int gsi, int irqchip, int pin);
+
 void aehd_put_apic_state(DeviceState *d, struct aehd_lapic_state *kapic);
 void aehd_get_apic_state(DeviceState *d, struct aehd_lapic_state *kapic);
 
@@ -74,4 +76,6 @@  void aehd_get_apic_state(DeviceState *d, struct aehd_lapic_state *kapic);
 void aehd_irqchip_commit_routes(AEHDState *s);
 void aehd_irqchip_release_virq(AEHDState *s, int virq);
 
+void aehd_pc_setup_irq_routing(bool pci_enabled);
+
 #endif
diff --git a/target/i386/aehd/aehd-all.c b/target/i386/aehd/aehd-all.c
index f2eb80ecde..4c6a670cb7 100644
--- a/target/i386/aehd/aehd-all.c
+++ b/target/i386/aehd/aehd-all.c
@@ -124,6 +124,20 @@  static void aehd_add_routing_entry(AEHDState *s,
     set_gsi(s, entry->gsi);
 }
 
+void aehd_irqchip_add_irq_route(AEHDState *s, int irq, int irqchip, int pin)
+{
+    struct aehd_irq_routing_entry e = {};
+
+    assert(pin < s->gsi_count);
+
+    e.gsi = irq;
+    e.type = AEHD_IRQ_ROUTING_IRQCHIP;
+    e.flags = 0;
+    e.u.irqchip.irqchip = irqchip;
+    e.u.irqchip.pin = pin;
+    aehd_add_routing_entry(s, &e);
+}
+
 void aehd_irqchip_release_virq(AEHDState *s, int virq)
 {
     struct aehd_irq_routing_entry *e;