summaryrefslogtreecommitdiffstats
path: root/qemu/hw/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/hw/cpu')
-rw-r--r--qemu/hw/cpu/Makefile.objs1
-rw-r--r--qemu/hw/cpu/a15mpcore.c46
-rw-r--r--qemu/hw/cpu/a9mpcore.c13
-rw-r--r--qemu/hw/cpu/arm11mpcore.c2
-rw-r--r--qemu/hw/cpu/icc_bus.c118
-rw-r--r--qemu/hw/cpu/realview_mpcore.c2
6 files changed, 49 insertions, 133 deletions
diff --git a/qemu/hw/cpu/Makefile.objs b/qemu/hw/cpu/Makefile.objs
index 6381238cc..0954a1872 100644
--- a/qemu/hw/cpu/Makefile.objs
+++ b/qemu/hw/cpu/Makefile.objs
@@ -2,5 +2,4 @@ obj-$(CONFIG_ARM11MPCORE) += arm11mpcore.o
obj-$(CONFIG_REALVIEW) += realview_mpcore.o
obj-$(CONFIG_A9MPCORE) += a9mpcore.o
obj-$(CONFIG_A15MPCORE) += a15mpcore.o
-obj-$(CONFIG_ICC_BUS) += icc_bus.o
diff --git a/qemu/hw/cpu/a15mpcore.c b/qemu/hw/cpu/a15mpcore.c
index acc419e11..bc05152fd 100644
--- a/qemu/hw/cpu/a15mpcore.c
+++ b/qemu/hw/cpu/a15mpcore.c
@@ -18,8 +18,11 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/cpu/a15mpcore.h"
#include "sysemu/kvm.h"
+#include "kvm_arm.h"
static void a15mp_priv_set_irq(void *opaque, int irq, int level)
{
@@ -33,16 +36,11 @@ static void a15mp_priv_initfn(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
A15MPPrivState *s = A15MPCORE_PRIV(obj);
DeviceState *gicdev;
- const char *gictype = "arm_gic";
-
- if (kvm_irqchip_in_kernel()) {
- gictype = "kvm-arm-gic";
- }
memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000);
sysbus_init_mmio(sbd, &s->container);
- object_initialize(&s->gic, sizeof(s->gic), gictype);
+ object_initialize(&s->gic, sizeof(s->gic), gic_class_name());
gicdev = DEVICE(&s->gic);
qdev_set_parent_bus(gicdev, sysbus_get_default());
qdev_prop_set_uint32(gicdev, "revision", 2);
@@ -56,10 +54,23 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
SysBusDevice *busdev;
int i;
Error *err = NULL;
+ bool has_el3;
+ Object *cpuobj;
gicdev = DEVICE(&s->gic);
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
+
+ if (!kvm_irqchip_in_kernel()) {
+ /* Make the GIC's TZ support match the CPUs. We assume that
+ * either all the CPUs have TZ, or none do.
+ */
+ cpuobj = OBJECT(qemu_get_cpu(0));
+ has_el3 = object_property_find(cpuobj, "has_el3", NULL) &&
+ object_property_get_bool(cpuobj, "has_el3", &error_abort);
+ qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
+ }
+
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
@@ -79,20 +90,27 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
for (i = 0; i < s->num_cpu; i++) {
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
int ppibase = s->num_irq - 32 + i * 32;
- /* physical timer; we wire it up to the non-secure timer's ID,
- * since a real A15 always has TrustZone but QEMU doesn't.
+ int irq;
+ /* Mapping from the output timer irq lines from the CPU to the
+ * GIC PPI inputs used on the A15:
*/
- qdev_connect_gpio_out(cpudev, 0,
- qdev_get_gpio_in(gicdev, ppibase + 30));
- /* virtual timer */
- qdev_connect_gpio_out(cpudev, 1,
- qdev_get_gpio_in(gicdev, ppibase + 27));
+ const int timer_irq[] = {
+ [GTIMER_PHYS] = 30,
+ [GTIMER_VIRT] = 27,
+ [GTIMER_HYP] = 26,
+ [GTIMER_SEC] = 29,
+ };
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
+ qdev_connect_gpio_out(cpudev, irq,
+ qdev_get_gpio_in(gicdev,
+ ppibase + timer_irq[irq]));
+ }
}
/* Memory map (addresses are offsets from PERIPHBASE):
* 0x0000-0x0fff -- reserved
* 0x1000-0x1fff -- GIC Distributor
- * 0x2000-0x2fff -- GIC CPU interface
+ * 0x2000-0x3fff -- GIC CPU interface
* 0x4000-0x4fff -- GIC virtual interface control (not modelled)
* 0x5000-0x5fff -- GIC virtual interface control (not modelled)
* 0x6000-0x7fff -- GIC virtual CPU interface (not modelled)
diff --git a/qemu/hw/cpu/a9mpcore.c b/qemu/hw/cpu/a9mpcore.c
index c09358c6e..5459ae8c1 100644
--- a/qemu/hw/cpu/a9mpcore.c
+++ b/qemu/hw/cpu/a9mpcore.c
@@ -8,6 +8,8 @@
* This code is licensed under the GPL.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/cpu/a9mpcore.h"
static void a9mp_priv_set_irq(void *opaque, int irq, int level)
@@ -49,6 +51,8 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
*wdtbusdev;
Error *err = NULL;
int i;
+ bool has_el3;
+ Object *cpuobj;
scudev = DEVICE(&s->scu);
qdev_prop_set_uint32(scudev, "num-cpu", s->num_cpu);
@@ -62,6 +66,15 @@ static void a9mp_priv_realize(DeviceState *dev, Error **errp)
gicdev = DEVICE(&s->gic);
qdev_prop_set_uint32(gicdev, "num-cpu", s->num_cpu);
qdev_prop_set_uint32(gicdev, "num-irq", s->num_irq);
+
+ /* Make the GIC's TZ support match the CPUs. We assume that
+ * either all the CPUs have TZ, or none do.
+ */
+ cpuobj = OBJECT(qemu_get_cpu(0));
+ has_el3 = object_property_find(cpuobj, "has_el3", NULL) &&
+ object_property_get_bool(cpuobj, "has_el3", &error_abort);
+ qdev_prop_set_bit(gicdev, "has-security-extensions", has_el3);
+
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
if (err != NULL) {
error_propagate(errp, err);
diff --git a/qemu/hw/cpu/arm11mpcore.c b/qemu/hw/cpu/arm11mpcore.c
index 717d3e4f8..eb244658b 100644
--- a/qemu/hw/cpu/arm11mpcore.c
+++ b/qemu/hw/cpu/arm11mpcore.c
@@ -7,6 +7,8 @@
* This code is licensed under the GPL.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/cpu/arm11mpcore.h"
#include "hw/intc/realview_gic.h"
diff --git a/qemu/hw/cpu/icc_bus.c b/qemu/hw/cpu/icc_bus.c
deleted file mode 100644
index 6646ea2b3..000000000
--- a/qemu/hw/cpu/icc_bus.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/* icc_bus.c
- * emulate x86 ICC (Interrupt Controller Communications) bus
- *
- * Copyright (c) 2013 Red Hat, Inc
- *
- * Authors:
- * Igor Mammedov <imammedo@redhat.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>
- */
-#include "hw/cpu/icc_bus.h"
-#include "hw/sysbus.h"
-
-/* icc-bridge implementation */
-
-static const TypeInfo icc_bus_info = {
- .name = TYPE_ICC_BUS,
- .parent = TYPE_BUS,
- .instance_size = sizeof(ICCBus),
-};
-
-
-/* icc-device implementation */
-
-static void icc_device_realize(DeviceState *dev, Error **errp)
-{
- ICCDeviceClass *idc = ICC_DEVICE_GET_CLASS(dev);
-
- /* convert to QOM */
- if (idc->realize) {
- idc->realize(dev, errp);
- }
-
-}
-
-static void icc_device_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- dc->realize = icc_device_realize;
- dc->bus_type = TYPE_ICC_BUS;
-}
-
-static const TypeInfo icc_device_info = {
- .name = TYPE_ICC_DEVICE,
- .parent = TYPE_DEVICE,
- .abstract = true,
- .instance_size = sizeof(ICCDevice),
- .class_size = sizeof(ICCDeviceClass),
- .class_init = icc_device_class_init,
-};
-
-
-/* icc-bridge implementation */
-
-typedef struct ICCBridgeState {
- /*< private >*/
- SysBusDevice parent_obj;
- /*< public >*/
-
- ICCBus icc_bus;
- MemoryRegion apic_container;
-} ICCBridgeState;
-
-#define ICC_BRIDGE(obj) OBJECT_CHECK(ICCBridgeState, (obj), TYPE_ICC_BRIDGE)
-
-static void icc_bridge_init(Object *obj)
-{
- ICCBridgeState *s = ICC_BRIDGE(obj);
- SysBusDevice *sb = SYS_BUS_DEVICE(obj);
-
- qbus_create_inplace(&s->icc_bus, sizeof(s->icc_bus), TYPE_ICC_BUS,
- DEVICE(s), "icc");
-
- /* Do not change order of registering regions,
- * APIC must be first registered region, board maps it by 0 index
- */
- memory_region_init(&s->apic_container, obj, "icc-apic-container",
- APIC_SPACE_SIZE);
- sysbus_init_mmio(sb, &s->apic_container);
- s->icc_bus.apic_address_space = &s->apic_container;
-}
-
-static void icc_bridge_class_init(ObjectClass *oc, void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(oc);
-
- set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
-}
-
-static const TypeInfo icc_bridge_info = {
- .name = TYPE_ICC_BRIDGE,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_init = icc_bridge_init,
- .instance_size = sizeof(ICCBridgeState),
- .class_init = icc_bridge_class_init,
-};
-
-
-static void icc_bus_register_types(void)
-{
- type_register_static(&icc_bus_info);
- type_register_static(&icc_device_info);
- type_register_static(&icc_bridge_info);
-}
-
-type_init(icc_bus_register_types)
diff --git a/qemu/hw/cpu/realview_mpcore.c b/qemu/hw/cpu/realview_mpcore.c
index c39a2da42..39d4ebeb1 100644
--- a/qemu/hw/cpu/realview_mpcore.c
+++ b/qemu/hw/cpu/realview_mpcore.c
@@ -8,6 +8,8 @@
* This code is licensed under the GPL.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "hw/cpu/arm11mpcore.h"
#include "hw/intc/realview_gic.h"