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

msf2-soc.c (9955B)


      1/*
      2 * SmartFusion2 SoC emulation.
      3 *
      4 * Copyright (c) 2017-2020 Subbaraya Sundeep <sundeep.lkml@gmail.com>
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22 * THE SOFTWARE.
     23 */
     24
     25#include "qemu/osdep.h"
     26#include "qemu/units.h"
     27#include "qapi/error.h"
     28#include "exec/address-spaces.h"
     29#include "hw/char/serial.h"
     30#include "hw/arm/msf2-soc.h"
     31#include "hw/misc/unimp.h"
     32#include "hw/qdev-clock.h"
     33#include "sysemu/sysemu.h"
     34
     35#define MSF2_TIMER_BASE       0x40004000
     36#define MSF2_SYSREG_BASE      0x40038000
     37#define MSF2_EMAC_BASE        0x40041000
     38
     39#define ENVM_BASE_ADDRESS     0x60000000
     40
     41#define SRAM_BASE_ADDRESS     0x20000000
     42
     43#define MSF2_EMAC_IRQ         12
     44
     45#define MSF2_ENVM_MAX_SIZE    (512 * KiB)
     46
     47/*
     48 * eSRAM max size is 80k without SECDED(Single error correction and
     49 * dual error detection) feature and 64k with SECDED.
     50 * We do not support SECDED now.
     51 */
     52#define MSF2_ESRAM_MAX_SIZE       (80 * KiB)
     53
     54static const uint32_t spi_addr[MSF2_NUM_SPIS] = { 0x40001000 , 0x40011000 };
     55static const uint32_t uart_addr[MSF2_NUM_UARTS] = { 0x40000000 , 0x40010000 };
     56
     57static const int spi_irq[MSF2_NUM_SPIS] = { 2, 3 };
     58static const int uart_irq[MSF2_NUM_UARTS] = { 10, 11 };
     59static const int timer_irq[MSF2_NUM_TIMERS] = { 14, 15 };
     60
     61static void m2sxxx_soc_initfn(Object *obj)
     62{
     63    MSF2State *s = MSF2_SOC(obj);
     64    int i;
     65
     66    object_initialize_child(obj, "armv7m", &s->armv7m, TYPE_ARMV7M);
     67
     68    object_initialize_child(obj, "sysreg", &s->sysreg, TYPE_MSF2_SYSREG);
     69
     70    object_initialize_child(obj, "timer", &s->timer, TYPE_MSS_TIMER);
     71
     72    for (i = 0; i < MSF2_NUM_SPIS; i++) {
     73        object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_MSS_SPI);
     74    }
     75
     76    object_initialize_child(obj, "emac", &s->emac, TYPE_MSS_EMAC);
     77
     78    s->m3clk = qdev_init_clock_in(DEVICE(obj), "m3clk", NULL, NULL, 0);
     79    s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", NULL, NULL, 0);
     80}
     81
     82static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
     83{
     84    MSF2State *s = MSF2_SOC(dev_soc);
     85    DeviceState *dev, *armv7m;
     86    SysBusDevice *busdev;
     87    int i;
     88
     89    MemoryRegion *system_memory = get_system_memory();
     90
     91    if (!clock_has_source(s->m3clk)) {
     92        error_setg(errp, "m3clk must be wired up by the board code");
     93        return;
     94    }
     95
     96    /*
     97     * We use s->refclk internally and only define it with qdev_init_clock_in()
     98     * so it is correctly parented and not leaked on an init/deinit; it is not
     99     * intended as an externally exposed clock.
    100     */
    101    if (clock_has_source(s->refclk)) {
    102        error_setg(errp, "refclk must not be wired up by the board code");
    103        return;
    104    }
    105
    106    /*
    107     * TODO: ideally we should model the SoC SYSTICK_CR register at 0xe0042038,
    108     * which allows the guest to program the divisor between the m3clk and
    109     * the systick refclk to either /4, /8, /16 or /32, as well as setting
    110     * the value the guest can read in the STCALIB register. Currently we
    111     * implement the divisor as a fixed /32, which matches the reset value
    112     * of SYSTICK_CR.
    113     */
    114    clock_set_mul_div(s->refclk, 32, 1);
    115    clock_set_source(s->refclk, s->m3clk);
    116
    117    memory_region_init_rom(&s->nvm, OBJECT(dev_soc), "MSF2.eNVM", s->envm_size,
    118                           &error_fatal);
    119    /*
    120     * On power-on, the eNVM region 0x60000000 is automatically
    121     * remapped to the Cortex-M3 processor executable region
    122     * start address (0x0). We do not support remapping other eNVM,
    123     * eSRAM and DDR regions by guest(via Sysreg) currently.
    124     */
    125    memory_region_init_alias(&s->nvm_alias, OBJECT(dev_soc), "MSF2.eNVM",
    126                             &s->nvm, 0, s->envm_size);
    127
    128    memory_region_add_subregion(system_memory, ENVM_BASE_ADDRESS, &s->nvm);
    129    memory_region_add_subregion(system_memory, 0, &s->nvm_alias);
    130
    131    memory_region_init_ram(&s->sram, NULL, "MSF2.eSRAM", s->esram_size,
    132                           &error_fatal);
    133    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &s->sram);
    134
    135    armv7m = DEVICE(&s->armv7m);
    136    qdev_prop_set_uint32(armv7m, "num-irq", 81);
    137    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
    138    qdev_prop_set_bit(armv7m, "enable-bitband", true);
    139    qdev_connect_clock_in(armv7m, "cpuclk", s->m3clk);
    140    qdev_connect_clock_in(armv7m, "refclk", s->refclk);
    141    object_property_set_link(OBJECT(&s->armv7m), "memory",
    142                             OBJECT(get_system_memory()), &error_abort);
    143    if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
    144        return;
    145    }
    146
    147    for (i = 0; i < MSF2_NUM_UARTS; i++) {
    148        if (serial_hd(i)) {
    149            serial_mm_init(get_system_memory(), uart_addr[i], 2,
    150                           qdev_get_gpio_in(armv7m, uart_irq[i]),
    151                           115200, serial_hd(i), DEVICE_NATIVE_ENDIAN);
    152        }
    153    }
    154
    155    dev = DEVICE(&s->timer);
    156    /*
    157     * APB0 clock is the timer input clock.
    158     * TODO: ideally the MSF2 timer device should use a Clock rather than a
    159     * clock-frequency integer property.
    160     */
    161    qdev_prop_set_uint32(dev, "clock-frequency",
    162                         clock_get_hz(s->m3clk) / s->apb0div);
    163    if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer), errp)) {
    164        return;
    165    }
    166    busdev = SYS_BUS_DEVICE(dev);
    167    sysbus_mmio_map(busdev, 0, MSF2_TIMER_BASE);
    168    sysbus_connect_irq(busdev, 0,
    169                           qdev_get_gpio_in(armv7m, timer_irq[0]));
    170    sysbus_connect_irq(busdev, 1,
    171                           qdev_get_gpio_in(armv7m, timer_irq[1]));
    172
    173    dev = DEVICE(&s->sysreg);
    174    qdev_prop_set_uint32(dev, "apb0divisor", s->apb0div);
    175    qdev_prop_set_uint32(dev, "apb1divisor", s->apb1div);
    176    if (!sysbus_realize(SYS_BUS_DEVICE(&s->sysreg), errp)) {
    177        return;
    178    }
    179    busdev = SYS_BUS_DEVICE(dev);
    180    sysbus_mmio_map(busdev, 0, MSF2_SYSREG_BASE);
    181
    182    for (i = 0; i < MSF2_NUM_SPIS; i++) {
    183        gchar *bus_name;
    184
    185        if (!sysbus_realize(SYS_BUS_DEVICE(&s->spi[i]), errp)) {
    186            return;
    187        }
    188
    189        sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0, spi_addr[i]);
    190        sysbus_connect_irq(SYS_BUS_DEVICE(&s->spi[i]), 0,
    191                           qdev_get_gpio_in(armv7m, spi_irq[i]));
    192
    193        /* Alias controller SPI bus to the SoC itself */
    194        bus_name = g_strdup_printf("spi%d", i);
    195        object_property_add_alias(OBJECT(s), bus_name,
    196                                  OBJECT(&s->spi[i]), "spi");
    197        g_free(bus_name);
    198    }
    199
    200    /* FIXME use qdev NIC properties instead of nd_table[] */
    201    if (nd_table[0].used) {
    202        qemu_check_nic_model(&nd_table[0], TYPE_MSS_EMAC);
    203        qdev_set_nic_properties(DEVICE(&s->emac), &nd_table[0]);
    204    }
    205    dev = DEVICE(&s->emac);
    206    object_property_set_link(OBJECT(&s->emac), "ahb-bus",
    207                             OBJECT(get_system_memory()), &error_abort);
    208    if (!sysbus_realize(SYS_BUS_DEVICE(&s->emac), errp)) {
    209        return;
    210    }
    211    busdev = SYS_BUS_DEVICE(dev);
    212    sysbus_mmio_map(busdev, 0, MSF2_EMAC_BASE);
    213    sysbus_connect_irq(busdev, 0,
    214                       qdev_get_gpio_in(armv7m, MSF2_EMAC_IRQ));
    215
    216    /* Below devices are not modelled yet. */
    217    create_unimplemented_device("i2c_0", 0x40002000, 0x1000);
    218    create_unimplemented_device("dma", 0x40003000, 0x1000);
    219    create_unimplemented_device("watchdog", 0x40005000, 0x1000);
    220    create_unimplemented_device("i2c_1", 0x40012000, 0x1000);
    221    create_unimplemented_device("gpio", 0x40013000, 0x1000);
    222    create_unimplemented_device("hs-dma", 0x40014000, 0x1000);
    223    create_unimplemented_device("can", 0x40015000, 0x1000);
    224    create_unimplemented_device("rtc", 0x40017000, 0x1000);
    225    create_unimplemented_device("apb_config", 0x40020000, 0x10000);
    226    create_unimplemented_device("usb", 0x40043000, 0x1000);
    227}
    228
    229static Property m2sxxx_soc_properties[] = {
    230    /*
    231     * part name specifies the type of SmartFusion2 device variant(this
    232     * property is for information purpose only.
    233     */
    234    DEFINE_PROP_STRING("cpu-type", MSF2State, cpu_type),
    235    DEFINE_PROP_STRING("part-name", MSF2State, part_name),
    236    DEFINE_PROP_UINT64("eNVM-size", MSF2State, envm_size, MSF2_ENVM_MAX_SIZE),
    237    DEFINE_PROP_UINT64("eSRAM-size", MSF2State, esram_size,
    238                        MSF2_ESRAM_MAX_SIZE),
    239    /* default divisors in Libero GUI */
    240    DEFINE_PROP_UINT8("apb0div", MSF2State, apb0div, 2),
    241    DEFINE_PROP_UINT8("apb1div", MSF2State, apb1div, 2),
    242    DEFINE_PROP_END_OF_LIST(),
    243};
    244
    245static void m2sxxx_soc_class_init(ObjectClass *klass, void *data)
    246{
    247    DeviceClass *dc = DEVICE_CLASS(klass);
    248
    249    dc->realize = m2sxxx_soc_realize;
    250    device_class_set_props(dc, m2sxxx_soc_properties);
    251}
    252
    253static const TypeInfo m2sxxx_soc_info = {
    254    .name          = TYPE_MSF2_SOC,
    255    .parent        = TYPE_SYS_BUS_DEVICE,
    256    .instance_size = sizeof(MSF2State),
    257    .instance_init = m2sxxx_soc_initfn,
    258    .class_init    = m2sxxx_soc_class_init,
    259};
    260
    261static void m2sxxx_soc_types(void)
    262{
    263    type_register_static(&m2sxxx_soc_info);
    264}
    265
    266type_init(m2sxxx_soc_types)