aboutsummaryrefslogtreecommitdiff
path: root/hw/cpu
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-08-24 13:17:34 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-08-24 13:17:34 +0100
commitba3287d117066fef2ebfea9555197f94c950afc5 (patch)
treea4f2e4fa2a3b1dd1c70db649393608eecb74b4f4 /hw/cpu
parentb558e295211deecdc769835a0a400f8aa59c53fd (diff)
hw/cpu/a15mpcore: If CPU has EL2, enable it on the GIC and wire it up
For the A15MPCore internal peripheral object, we handle GIC security extensions support by checking whether the CPUs have EL3 enabled; if so then we enable it also on the GIC. Handle the virtualization extensions in the same way: if the CPU has EL2 then enable it on the GIC and wire up the virtualization-specific memory regions and the maintenance interrupt. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Luc Michel <luc.michel@greensocs.com> Message-id: 20180821132811.17675-8-peter.maydell@linaro.org
Diffstat (limited to 'hw/cpu')
-rw-r--r--hw/cpu/a15mpcore.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index 43c1079493..5649843cd8 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -53,6 +53,7 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
int i;
Error *err = NULL;
bool has_el3;
+ bool has_el2 = false;
Object *cpuobj;
gicdev = DEVICE(&s->gic);
@@ -67,6 +68,10 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
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);
+ /* Similarly for virtualization support */
+ has_el2 = object_property_find(cpuobj, "has_el2", NULL) &&
+ object_property_get_bool(cpuobj, "has_el2", &error_abort);
+ qdev_prop_set_bit(gicdev, "has-virtualization-extensions", has_el2);
}
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
@@ -103,20 +108,40 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(gicdev,
ppibase + timer_irq[irq]));
}
+ if (has_el2) {
+ /* Connect the GIC maintenance interrupt to PPI ID 25 */
+ sysbus_connect_irq(SYS_BUS_DEVICE(gicdev), i + 4 * s->num_cpu,
+ qdev_get_gpio_in(gicdev, ppibase + 25));
+ }
}
/* Memory map (addresses are offsets from PERIPHBASE):
* 0x0000-0x0fff -- reserved
* 0x1000-0x1fff -- GIC Distributor
* 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)
+ * 0x4000-0x4fff -- GIC virtual interface control for this CPU
+ * 0x5000-0x51ff -- GIC virtual interface control for CPU 0
+ * 0x5200-0x53ff -- GIC virtual interface control for CPU 1
+ * 0x5400-0x55ff -- GIC virtual interface control for CPU 2
+ * 0x5600-0x57ff -- GIC virtual interface control for CPU 3
+ * 0x6000-0x7fff -- GIC virtual CPU interface
*/
memory_region_add_subregion(&s->container, 0x1000,
sysbus_mmio_get_region(busdev, 0));
memory_region_add_subregion(&s->container, 0x2000,
sysbus_mmio_get_region(busdev, 1));
+ if (has_el2) {
+ memory_region_add_subregion(&s->container, 0x4000,
+ sysbus_mmio_get_region(busdev, 2));
+ memory_region_add_subregion(&s->container, 0x6000,
+ sysbus_mmio_get_region(busdev, 3));
+ for (i = 0; i < s->num_cpu; i++) {
+ hwaddr base = 0x5000 + i * 0x200;
+ MemoryRegion *mr = sysbus_mmio_get_region(busdev,
+ 4 + s->num_cpu + i);
+ memory_region_add_subregion(&s->container, base, mr);
+ }
+ }
}
static Property a15mp_priv_properties[] = {