summary refs log tree commit diff stats
path: root/hw/intc/arm_gicv3_common.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-09-24 01:32:11 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-09-24 01:32:11 +0100
commiteb9d0ea063fc7bdfab76b84085602a9e48d13ec7 (patch)
tree85d1aada3b8f8e8a7966b702dfcdc5c4e3defd1d /hw/intc/arm_gicv3_common.c
parentfefa4b128de06cec6d513f00ee61e8208aed4a87 (diff)
parent85b4d5dae12580ecdd446c0f71afa04a95641c91 (diff)
downloadfocaccia-qemu-eb9d0ea063fc7bdfab76b84085602a9e48d13ec7.tar.gz
focaccia-qemu-eb9d0ea063fc7bdfab76b84085602a9e48d13ec7.zip
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20150924' into staging
target-arm queue:
 * support VGICv3 in KVM
 * fix bug in ACPI table entries for flash devices in virt board
 * update Allwinner entry in MAINTAINERS

# gpg: Signature made Thu 24 Sep 2015 01:29:55 BST using RSA key ID 14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>"
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"

* remotes/pmaydell/tags/pull-target-arm-20150924:
  MAINTAINERS: update Allwinner A10 maintainer
  hw/arm/virt-acpi-build: Fix wrong size of flash in ACPI table
  hw/arm/virt: Add gic-version option to virt machine
  hw/intc: Initial implementation of vGICv3
  arm_kvm: Do not assume particular GIC type in kvm_arch_irqchip_create()
  intc/gic: Extract some reusable vGIC code
  hw/intc: Implement GIC-500 base class

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/intc/arm_gicv3_common.c')
-rw-r--r--hw/intc/arm_gicv3_common.c140
1 files changed, 140 insertions, 0 deletions
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
new file mode 100644
index 0000000000..032ece2166
--- /dev/null
+++ b/hw/intc/arm_gicv3_common.c
@@ -0,0 +1,140 @@
+/*
+ * ARM GICv3 support - common bits of emulated and KVM kernel model
+ *
+ * Copyright (c) 2012 Linaro Limited
+ * Copyright (c) 2015 Huawei.
+ * Written by Peter Maydell
+ * Extended to 64 cores by Shlomo Pongratz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hw/intc/arm_gicv3_common.h"
+
+static void gicv3_pre_save(void *opaque)
+{
+    GICv3State *s = (GICv3State *)opaque;
+    ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
+
+    if (c->pre_save) {
+        c->pre_save(s);
+    }
+}
+
+static int gicv3_post_load(void *opaque, int version_id)
+{
+    GICv3State *s = (GICv3State *)opaque;
+    ARMGICv3CommonClass *c = ARM_GICV3_COMMON_GET_CLASS(s);
+
+    if (c->post_load) {
+        c->post_load(s);
+    }
+    return 0;
+}
+
+static const VMStateDescription vmstate_gicv3 = {
+    .name = "arm_gicv3",
+    .unmigratable = 1,
+    .pre_save = gicv3_pre_save,
+    .post_load = gicv3_post_load,
+};
+
+void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
+                              const MemoryRegionOps *ops)
+{
+    SysBusDevice *sbd = SYS_BUS_DEVICE(s);
+    int i;
+
+    /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
+     * GPIO array layout is thus:
+     *  [0..N-1] spi
+     *  [N..N+31] PPIs for CPU 0
+     *  [N+32..N+63] PPIs for CPU 1
+     *   ...
+     */
+    i = s->num_irq - GIC_INTERNAL + GIC_INTERNAL * s->num_cpu;
+    qdev_init_gpio_in(DEVICE(s), handler, i);
+
+    s->parent_irq = g_malloc(s->num_cpu * sizeof(qemu_irq));
+    s->parent_fiq = g_malloc(s->num_cpu * sizeof(qemu_irq));
+
+    for (i = 0; i < s->num_cpu; i++) {
+        sysbus_init_irq(sbd, &s->parent_irq[i]);
+    }
+    for (i = 0; i < s->num_cpu; i++) {
+        sysbus_init_irq(sbd, &s->parent_fiq[i]);
+    }
+
+    memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
+                          "gicv3_dist", 0x10000);
+    memory_region_init_io(&s->iomem_redist, OBJECT(s), ops ? &ops[1] : NULL, s,
+                          "gicv3_redist", 0x20000 * s->num_cpu);
+
+    sysbus_init_mmio(sbd, &s->iomem_dist);
+    sysbus_init_mmio(sbd, &s->iomem_redist);
+}
+
+static void arm_gicv3_common_realize(DeviceState *dev, Error **errp)
+{
+    GICv3State *s = ARM_GICV3_COMMON(dev);
+
+    /* revision property is actually reserved and currently used only in order
+     * to keep the interface compatible with GICv2 code, avoiding extra
+     * conditions. However, in future it could be used, for example, if we
+     * implement GICv4.
+     */
+    if (s->revision != 3) {
+        error_setg(errp, "unsupported GIC revision %d", s->revision);
+        return;
+    }
+}
+
+static void arm_gicv3_common_reset(DeviceState *dev)
+{
+    /* TODO */
+}
+
+static Property arm_gicv3_common_properties[] = {
+    DEFINE_PROP_UINT32("num-cpu", GICv3State, num_cpu, 1),
+    DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
+    DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
+    DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void arm_gicv3_common_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = arm_gicv3_common_reset;
+    dc->realize = arm_gicv3_common_realize;
+    dc->props = arm_gicv3_common_properties;
+    dc->vmsd = &vmstate_gicv3;
+}
+
+static const TypeInfo arm_gicv3_common_type = {
+    .name = TYPE_ARM_GICV3_COMMON,
+    .parent = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(GICv3State),
+    .class_size = sizeof(ARMGICv3CommonClass),
+    .class_init = arm_gicv3_common_class_init,
+    .abstract = true,
+};
+
+static void register_types(void)
+{
+    type_register_static(&arm_gicv3_common_type);
+}
+
+type_init(register_types)