cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

bcm2836.c (8022B)


      1/*
      2 * Raspberry Pi emulation (c) 2012 Gregory Estrade
      3 * Upstreaming code cleanup [including bcm2835_*] (c) 2013 Jan Petrous
      4 *
      5 * Rasperry Pi 2 emulation and refactoring Copyright (c) 2015, Microsoft
      6 * Written by Andrew Baumann
      7 *
      8 * This work is licensed under the terms of the GNU GPL, version 2 or later.
      9 * See the COPYING file in the top-level directory.
     10 */
     11
     12#include "qemu/osdep.h"
     13#include "qapi/error.h"
     14#include "qemu/module.h"
     15#include "hw/arm/bcm2836.h"
     16#include "hw/arm/raspi_platform.h"
     17#include "hw/sysbus.h"
     18
     19typedef struct BCM283XClass {
     20    /*< private >*/
     21    DeviceClass parent_class;
     22    /*< public >*/
     23    const char *name;
     24    const char *cpu_type;
     25    unsigned core_count;
     26    hwaddr peri_base; /* Peripheral base address seen by the CPU */
     27    hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
     28    int clusterid;
     29} BCM283XClass;
     30
     31#define BCM283X_CLASS(klass) \
     32    OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
     33#define BCM283X_GET_CLASS(obj) \
     34    OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
     35
     36static Property bcm2836_enabled_cores_property =
     37    DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0);
     38
     39static void bcm2836_init(Object *obj)
     40{
     41    BCM283XState *s = BCM283X(obj);
     42    BCM283XClass *bc = BCM283X_GET_CLASS(obj);
     43    int n;
     44
     45    for (n = 0; n < bc->core_count; n++) {
     46        object_initialize_child(obj, "cpu[*]", &s->cpu[n].core,
     47                                bc->cpu_type);
     48    }
     49    if (bc->core_count > 1) {
     50        qdev_property_add_static(DEVICE(obj), &bcm2836_enabled_cores_property);
     51        qdev_prop_set_uint32(DEVICE(obj), "enabled-cpus", bc->core_count);
     52    }
     53
     54    if (bc->ctrl_base) {
     55        object_initialize_child(obj, "control", &s->control,
     56                                TYPE_BCM2836_CONTROL);
     57    }
     58
     59    object_initialize_child(obj, "peripherals", &s->peripherals,
     60                            TYPE_BCM2835_PERIPHERALS);
     61    object_property_add_alias(obj, "board-rev", OBJECT(&s->peripherals),
     62                              "board-rev");
     63    object_property_add_alias(obj, "vcram-size", OBJECT(&s->peripherals),
     64                              "vcram-size");
     65}
     66
     67static bool bcm283x_common_realize(DeviceState *dev, Error **errp)
     68{
     69    BCM283XState *s = BCM283X(dev);
     70    BCM283XClass *bc = BCM283X_GET_CLASS(dev);
     71    Object *obj;
     72
     73    /* common peripherals from bcm2835 */
     74
     75    obj = object_property_get_link(OBJECT(dev), "ram", &error_abort);
     76
     77    object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj);
     78
     79    if (!sysbus_realize(SYS_BUS_DEVICE(&s->peripherals), errp)) {
     80        return false;
     81    }
     82
     83    object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->peripherals),
     84                              "sd-bus");
     85
     86    sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0,
     87                            bc->peri_base, 1);
     88    return true;
     89}
     90
     91static void bcm2835_realize(DeviceState *dev, Error **errp)
     92{
     93    BCM283XState *s = BCM283X(dev);
     94
     95    if (!bcm283x_common_realize(dev, errp)) {
     96        return;
     97    }
     98
     99    if (!qdev_realize(DEVICE(&s->cpu[0].core), NULL, errp)) {
    100        return;
    101    }
    102
    103    /* Connect irq/fiq outputs from the interrupt controller. */
    104    sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
    105            qdev_get_gpio_in(DEVICE(&s->cpu[0].core), ARM_CPU_IRQ));
    106    sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
    107            qdev_get_gpio_in(DEVICE(&s->cpu[0].core), ARM_CPU_FIQ));
    108}
    109
    110static void bcm2836_realize(DeviceState *dev, Error **errp)
    111{
    112    BCM283XState *s = BCM283X(dev);
    113    BCM283XClass *bc = BCM283X_GET_CLASS(dev);
    114    int n;
    115
    116    if (!bcm283x_common_realize(dev, errp)) {
    117        return;
    118    }
    119
    120    /* bcm2836 interrupt controller (and mailboxes, etc.) */
    121    if (!sysbus_realize(SYS_BUS_DEVICE(&s->control), errp)) {
    122        return;
    123    }
    124
    125    sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, bc->ctrl_base);
    126
    127    sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0,
    128        qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-irq", 0));
    129    sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1,
    130        qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0));
    131
    132    for (n = 0; n < BCM283X_NCPUS; n++) {
    133        /* TODO: this should be converted to a property of ARM_CPU */
    134        s->cpu[n].core.mp_affinity = (bc->clusterid << 8) | n;
    135
    136        /* set periphbase/CBAR value for CPU-local registers */
    137        if (!object_property_set_int(OBJECT(&s->cpu[n].core), "reset-cbar",
    138                                     bc->peri_base, errp)) {
    139            return;
    140        }
    141
    142        /* start powered off if not enabled */
    143        if (!object_property_set_bool(OBJECT(&s->cpu[n].core),
    144                                      "start-powered-off",
    145                                      n >= s->enabled_cpus,
    146                                      errp)) {
    147            return;
    148        }
    149
    150        if (!qdev_realize(DEVICE(&s->cpu[n].core), NULL, errp)) {
    151            return;
    152        }
    153
    154        /* Connect irq/fiq outputs from the interrupt controller. */
    155        qdev_connect_gpio_out_named(DEVICE(&s->control), "irq", n,
    156                qdev_get_gpio_in(DEVICE(&s->cpu[n].core), ARM_CPU_IRQ));
    157        qdev_connect_gpio_out_named(DEVICE(&s->control), "fiq", n,
    158                qdev_get_gpio_in(DEVICE(&s->cpu[n].core), ARM_CPU_FIQ));
    159
    160        /* Connect timers from the CPU to the interrupt controller */
    161        qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_PHYS,
    162                qdev_get_gpio_in_named(DEVICE(&s->control), "cntpnsirq", n));
    163        qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_VIRT,
    164                qdev_get_gpio_in_named(DEVICE(&s->control), "cntvirq", n));
    165        qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_HYP,
    166                qdev_get_gpio_in_named(DEVICE(&s->control), "cnthpirq", n));
    167        qdev_connect_gpio_out(DEVICE(&s->cpu[n].core), GTIMER_SEC,
    168                qdev_get_gpio_in_named(DEVICE(&s->control), "cntpsirq", n));
    169    }
    170}
    171
    172static void bcm283x_class_init(ObjectClass *oc, void *data)
    173{
    174    DeviceClass *dc = DEVICE_CLASS(oc);
    175
    176    /* Reason: Must be wired up in code (see raspi_init() function) */
    177    dc->user_creatable = false;
    178}
    179
    180static void bcm2835_class_init(ObjectClass *oc, void *data)
    181{
    182    DeviceClass *dc = DEVICE_CLASS(oc);
    183    BCM283XClass *bc = BCM283X_CLASS(oc);
    184
    185    bc->cpu_type = ARM_CPU_TYPE_NAME("arm1176");
    186    bc->core_count = 1;
    187    bc->peri_base = 0x20000000;
    188    dc->realize = bcm2835_realize;
    189};
    190
    191static void bcm2836_class_init(ObjectClass *oc, void *data)
    192{
    193    DeviceClass *dc = DEVICE_CLASS(oc);
    194    BCM283XClass *bc = BCM283X_CLASS(oc);
    195
    196    bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
    197    bc->core_count = BCM283X_NCPUS;
    198    bc->peri_base = 0x3f000000;
    199    bc->ctrl_base = 0x40000000;
    200    bc->clusterid = 0xf;
    201    dc->realize = bcm2836_realize;
    202};
    203
    204#ifdef TARGET_AARCH64
    205static void bcm2837_class_init(ObjectClass *oc, void *data)
    206{
    207    DeviceClass *dc = DEVICE_CLASS(oc);
    208    BCM283XClass *bc = BCM283X_CLASS(oc);
    209
    210    bc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a53");
    211    bc->core_count = BCM283X_NCPUS;
    212    bc->peri_base = 0x3f000000;
    213    bc->ctrl_base = 0x40000000;
    214    bc->clusterid = 0x0;
    215    dc->realize = bcm2836_realize;
    216};
    217#endif
    218
    219static const TypeInfo bcm283x_types[] = {
    220    {
    221        .name           = TYPE_BCM2835,
    222        .parent         = TYPE_BCM283X,
    223        .class_init     = bcm2835_class_init,
    224    }, {
    225        .name           = TYPE_BCM2836,
    226        .parent         = TYPE_BCM283X,
    227        .class_init     = bcm2836_class_init,
    228#ifdef TARGET_AARCH64
    229    }, {
    230        .name           = TYPE_BCM2837,
    231        .parent         = TYPE_BCM283X,
    232        .class_init     = bcm2837_class_init,
    233#endif
    234    }, {
    235        .name           = TYPE_BCM283X,
    236        .parent         = TYPE_DEVICE,
    237        .instance_size  = sizeof(BCM283XState),
    238        .instance_init  = bcm2836_init,
    239        .class_size     = sizeof(BCM283XClass),
    240        .class_init     = bcm283x_class_init,
    241        .abstract       = true,
    242    }
    243};
    244
    245DEFINE_TYPES(bcm283x_types)