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

xlnx-zcu102.c (9649B)


      1/*
      2 * Xilinx ZynqMP ZCU102 board
      3 *
      4 * Copyright (C) 2015 Xilinx Inc
      5 * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
      6 *
      7 * This program is free software; you can redistribute it and/or modify it
      8 * under the terms of the GNU General Public License as published by the
      9 * Free Software Foundation; either version 2 of the License, or
     10 * (at your option) any later version.
     11 *
     12 * This program is distributed in the hope that it will be useful, but WITHOUT
     13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
     15 * for more details.
     16 */
     17
     18#include "qemu/osdep.h"
     19#include "qapi/error.h"
     20#include "hw/arm/xlnx-zynqmp.h"
     21#include "hw/boards.h"
     22#include "qemu/error-report.h"
     23#include "qemu/log.h"
     24#include "sysemu/device_tree.h"
     25#include "qom/object.h"
     26#include "net/can_emu.h"
     27
     28struct XlnxZCU102 {
     29    MachineState parent_obj;
     30
     31    XlnxZynqMPState soc;
     32
     33    bool secure;
     34    bool virt;
     35
     36    CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
     37
     38    struct arm_boot_info binfo;
     39};
     40
     41#define TYPE_ZCU102_MACHINE   MACHINE_TYPE_NAME("xlnx-zcu102")
     42OBJECT_DECLARE_SIMPLE_TYPE(XlnxZCU102, ZCU102_MACHINE)
     43
     44
     45static bool zcu102_get_secure(Object *obj, Error **errp)
     46{
     47    XlnxZCU102 *s = ZCU102_MACHINE(obj);
     48
     49    return s->secure;
     50}
     51
     52static void zcu102_set_secure(Object *obj, bool value, Error **errp)
     53{
     54    XlnxZCU102 *s = ZCU102_MACHINE(obj);
     55
     56    s->secure = value;
     57}
     58
     59static bool zcu102_get_virt(Object *obj, Error **errp)
     60{
     61    XlnxZCU102 *s = ZCU102_MACHINE(obj);
     62
     63    return s->virt;
     64}
     65
     66static void zcu102_set_virt(Object *obj, bool value, Error **errp)
     67{
     68    XlnxZCU102 *s = ZCU102_MACHINE(obj);
     69
     70    s->virt = value;
     71}
     72
     73static void zcu102_modify_dtb(const struct arm_boot_info *binfo, void *fdt)
     74{
     75    XlnxZCU102 *s = container_of(binfo, XlnxZCU102, binfo);
     76    bool method_is_hvc;
     77    char **node_path;
     78    const char *r;
     79    int prop_len;
     80    int i;
     81
     82    /* If EL3 is enabled, we keep all firmware nodes active.  */
     83    if (!s->secure) {
     84        node_path = qemu_fdt_node_path(fdt, NULL, "xlnx,zynqmp-firmware",
     85                                       &error_fatal);
     86
     87        for (i = 0; node_path && node_path[i]; i++) {
     88            r = qemu_fdt_getprop(fdt, node_path[i], "method", &prop_len, NULL);
     89            method_is_hvc = r && !strcmp("hvc", r);
     90
     91            /* Allow HVC based firmware if EL2 is enabled.  */
     92            if (method_is_hvc && s->virt) {
     93                continue;
     94            }
     95            qemu_fdt_setprop_string(fdt, node_path[i], "status", "disabled");
     96        }
     97        g_strfreev(node_path);
     98    }
     99}
    100
    101static void bbram_attach_drive(XlnxBBRam *dev)
    102{
    103    DriveInfo *dinfo;
    104    BlockBackend *blk;
    105
    106    dinfo = drive_get_by_index(IF_PFLASH, 2);
    107    blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
    108    if (blk) {
    109        qdev_prop_set_drive(DEVICE(dev), "drive", blk);
    110    }
    111}
    112
    113static void efuse_attach_drive(XlnxEFuse *dev)
    114{
    115    DriveInfo *dinfo;
    116    BlockBackend *blk;
    117
    118    dinfo = drive_get_by_index(IF_PFLASH, 3);
    119    blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
    120    if (blk) {
    121        qdev_prop_set_drive(DEVICE(dev), "drive", blk);
    122    }
    123}
    124
    125static void xlnx_zcu102_init(MachineState *machine)
    126{
    127    XlnxZCU102 *s = ZCU102_MACHINE(machine);
    128    int i;
    129    uint64_t ram_size = machine->ram_size;
    130
    131    /* Create the memory region to pass to the SoC */
    132    if (ram_size > XLNX_ZYNQMP_MAX_RAM_SIZE) {
    133        error_report("ERROR: RAM size 0x%" PRIx64 " above max supported of "
    134                     "0x%llx", ram_size,
    135                     XLNX_ZYNQMP_MAX_RAM_SIZE);
    136        exit(1);
    137    }
    138
    139    if (ram_size < 0x08000000) {
    140        qemu_log("WARNING: RAM size 0x%" PRIx64 " is small for ZCU102",
    141                 ram_size);
    142    }
    143
    144    object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_XLNX_ZYNQMP);
    145
    146    object_property_set_link(OBJECT(&s->soc), "ddr-ram", OBJECT(machine->ram),
    147                             &error_abort);
    148    object_property_set_bool(OBJECT(&s->soc), "secure", s->secure,
    149                             &error_fatal);
    150    object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
    151                             &error_fatal);
    152
    153    for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
    154        gchar *bus_name = g_strdup_printf("canbus%d", i);
    155
    156        object_property_set_link(OBJECT(&s->soc), bus_name,
    157                                 OBJECT(s->canbus[i]), &error_fatal);
    158        g_free(bus_name);
    159    }
    160
    161    qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
    162
    163    /* Attach bbram backend, if given */
    164    bbram_attach_drive(&s->soc.bbram);
    165
    166    /* Attach efuse backend, if given */
    167    efuse_attach_drive(&s->soc.efuse);
    168
    169    /* Create and plug in the SD cards */
    170    for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
    171        BusState *bus;
    172        DriveInfo *di = drive_get_next(IF_SD);
    173        BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
    174        DeviceState *carddev;
    175        char *bus_name;
    176
    177        bus_name = g_strdup_printf("sd-bus%d", i);
    178        bus = qdev_get_child_bus(DEVICE(&s->soc), bus_name);
    179        g_free(bus_name);
    180        if (!bus) {
    181            error_report("No SD bus found for SD card %d", i);
    182            exit(1);
    183        }
    184        carddev = qdev_new(TYPE_SD_CARD);
    185        qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
    186        qdev_realize_and_unref(carddev, bus, &error_fatal);
    187    }
    188
    189    for (i = 0; i < XLNX_ZYNQMP_NUM_SPIS; i++) {
    190        BusState *spi_bus;
    191        DeviceState *flash_dev;
    192        qemu_irq cs_line;
    193        DriveInfo *dinfo = drive_get_next(IF_MTD);
    194        gchar *bus_name = g_strdup_printf("spi%d", i);
    195
    196        spi_bus = qdev_get_child_bus(DEVICE(&s->soc), bus_name);
    197        g_free(bus_name);
    198
    199        flash_dev = qdev_new("sst25wf080");
    200        if (dinfo) {
    201            qdev_prop_set_drive_err(flash_dev, "drive",
    202                                    blk_by_legacy_dinfo(dinfo), &error_fatal);
    203        }
    204        qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal);
    205
    206        cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
    207
    208        sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.spi[i]), 1, cs_line);
    209    }
    210
    211    for (i = 0; i < XLNX_ZYNQMP_NUM_QSPI_FLASH; i++) {
    212        BusState *spi_bus;
    213        DeviceState *flash_dev;
    214        qemu_irq cs_line;
    215        DriveInfo *dinfo = drive_get_next(IF_MTD);
    216        int bus = i / XLNX_ZYNQMP_NUM_QSPI_BUS_CS;
    217        gchar *bus_name = g_strdup_printf("qspi%d", bus);
    218
    219        spi_bus = qdev_get_child_bus(DEVICE(&s->soc), bus_name);
    220        g_free(bus_name);
    221
    222        flash_dev = qdev_new("n25q512a11");
    223        if (dinfo) {
    224            qdev_prop_set_drive_err(flash_dev, "drive",
    225                                    blk_by_legacy_dinfo(dinfo), &error_fatal);
    226        }
    227        qdev_realize_and_unref(flash_dev, spi_bus, &error_fatal);
    228
    229        cs_line = qdev_get_gpio_in_named(flash_dev, SSI_GPIO_CS, 0);
    230
    231        sysbus_connect_irq(SYS_BUS_DEVICE(&s->soc.qspi), i + 1, cs_line);
    232    }
    233
    234    /* TODO create and connect IDE devices for ide_drive_get() */
    235
    236    s->binfo.ram_size = ram_size;
    237    s->binfo.loader_start = 0;
    238    s->binfo.modify_dtb = zcu102_modify_dtb;
    239    arm_load_kernel(s->soc.boot_cpu_ptr, machine, &s->binfo);
    240}
    241
    242static void xlnx_zcu102_machine_instance_init(Object *obj)
    243{
    244    XlnxZCU102 *s = ZCU102_MACHINE(obj);
    245
    246    /* Default to secure mode being disabled */
    247    s->secure = false;
    248    /* Default to virt (EL2) being disabled */
    249    s->virt = false;
    250    object_property_add_link(obj, "canbus0", TYPE_CAN_BUS,
    251                             (Object **)&s->canbus[0],
    252                             object_property_allow_set_link,
    253                             0);
    254
    255    object_property_add_link(obj, "canbus1", TYPE_CAN_BUS,
    256                             (Object **)&s->canbus[1],
    257                             object_property_allow_set_link,
    258                             0);
    259}
    260
    261static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
    262{
    263    MachineClass *mc = MACHINE_CLASS(oc);
    264
    265    mc->desc = "Xilinx ZynqMP ZCU102 board with 4xA53s and 2xR5Fs based on " \
    266               "the value of smp";
    267    mc->init = xlnx_zcu102_init;
    268    mc->block_default_type = IF_IDE;
    269    mc->units_per_default_bus = 1;
    270    mc->ignore_memory_transaction_failures = true;
    271    mc->max_cpus = XLNX_ZYNQMP_NUM_APU_CPUS + XLNX_ZYNQMP_NUM_RPU_CPUS;
    272    mc->default_cpus = XLNX_ZYNQMP_NUM_APU_CPUS;
    273    mc->default_ram_id = "ddr-ram";
    274
    275    object_class_property_add_bool(oc, "secure", zcu102_get_secure,
    276                                   zcu102_set_secure);
    277    object_class_property_set_description(oc, "secure",
    278                                          "Set on/off to enable/disable the ARM "
    279                                          "Security Extensions (TrustZone)");
    280
    281    object_class_property_add_bool(oc, "virtualization", zcu102_get_virt,
    282                                   zcu102_set_virt);
    283    object_class_property_set_description(oc, "virtualization",
    284                                          "Set on/off to enable/disable emulating a "
    285                                          "guest CPU which implements the ARM "
    286                                          "Virtualization Extensions");
    287}
    288
    289static const TypeInfo xlnx_zcu102_machine_init_typeinfo = {
    290    .name       = TYPE_ZCU102_MACHINE,
    291    .parent     = TYPE_MACHINE,
    292    .class_init = xlnx_zcu102_machine_class_init,
    293    .instance_init = xlnx_zcu102_machine_instance_init,
    294    .instance_size = sizeof(XlnxZCU102),
    295};
    296
    297static void xlnx_zcu102_machine_init_register_types(void)
    298{
    299    type_register_static(&xlnx_zcu102_machine_init_typeinfo);
    300}
    301
    302type_init(xlnx_zcu102_machine_init_register_types)