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

tz-ppc.c (9727B)


      1/*
      2 * ARM TrustZone peripheral protection controller emulation
      3 *
      4 * Copyright (c) 2018 Linaro Limited
      5 * Written by Peter Maydell
      6 *
      7 * This program is free software; you can redistribute it and/or modify
      8 * it under the terms of the GNU General Public License version 2 or
      9 * (at your option) any later version.
     10 */
     11
     12#include "qemu/osdep.h"
     13#include "qemu/log.h"
     14#include "qemu/module.h"
     15#include "qapi/error.h"
     16#include "trace.h"
     17#include "hw/sysbus.h"
     18#include "migration/vmstate.h"
     19#include "hw/registerfields.h"
     20#include "hw/irq.h"
     21#include "hw/misc/tz-ppc.h"
     22#include "hw/qdev-properties.h"
     23
     24static void tz_ppc_update_irq(TZPPC *s)
     25{
     26    bool level = s->irq_status && s->irq_enable;
     27
     28    trace_tz_ppc_update_irq(level);
     29    qemu_set_irq(s->irq, level);
     30}
     31
     32static void tz_ppc_cfg_nonsec(void *opaque, int n, int level)
     33{
     34    TZPPC *s = TZ_PPC(opaque);
     35
     36    assert(n < TZ_NUM_PORTS);
     37    trace_tz_ppc_cfg_nonsec(n, level);
     38    s->cfg_nonsec[n] = level;
     39}
     40
     41static void tz_ppc_cfg_ap(void *opaque, int n, int level)
     42{
     43    TZPPC *s = TZ_PPC(opaque);
     44
     45    assert(n < TZ_NUM_PORTS);
     46    trace_tz_ppc_cfg_ap(n, level);
     47    s->cfg_ap[n] = level;
     48}
     49
     50static void tz_ppc_cfg_sec_resp(void *opaque, int n, int level)
     51{
     52    TZPPC *s = TZ_PPC(opaque);
     53
     54    trace_tz_ppc_cfg_sec_resp(level);
     55    s->cfg_sec_resp = level;
     56}
     57
     58static void tz_ppc_irq_enable(void *opaque, int n, int level)
     59{
     60    TZPPC *s = TZ_PPC(opaque);
     61
     62    trace_tz_ppc_irq_enable(level);
     63    s->irq_enable = level;
     64    tz_ppc_update_irq(s);
     65}
     66
     67static void tz_ppc_irq_clear(void *opaque, int n, int level)
     68{
     69    TZPPC *s = TZ_PPC(opaque);
     70
     71    trace_tz_ppc_irq_clear(level);
     72
     73    s->irq_clear = level;
     74    if (level) {
     75        s->irq_status = false;
     76        tz_ppc_update_irq(s);
     77    }
     78}
     79
     80static bool tz_ppc_check(TZPPC *s, int n, MemTxAttrs attrs)
     81{
     82    /* Check whether to allow an access to port n; return true if
     83     * the check passes, and false if the transaction must be blocked.
     84     * If the latter, the caller must check cfg_sec_resp to determine
     85     * whether to abort or RAZ/WI the transaction.
     86     * The checks are:
     87     *  + nonsec_mask suppresses any check of the secure attribute
     88     *  + otherwise, block if cfg_nonsec is 1 and transaction is secure,
     89     *    or if cfg_nonsec is 0 and transaction is non-secure
     90     *  + block if transaction is usermode and cfg_ap is 0
     91     */
     92    if ((attrs.secure == s->cfg_nonsec[n] && !(s->nonsec_mask & (1 << n))) ||
     93        (attrs.user && !s->cfg_ap[n])) {
     94        /* Block the transaction. */
     95        if (!s->irq_clear) {
     96            /* Note that holding irq_clear high suppresses interrupts */
     97            s->irq_status = true;
     98            tz_ppc_update_irq(s);
     99        }
    100        return false;
    101    }
    102    return true;
    103}
    104
    105static MemTxResult tz_ppc_read(void *opaque, hwaddr addr, uint64_t *pdata,
    106                               unsigned size, MemTxAttrs attrs)
    107{
    108    TZPPCPort *p = opaque;
    109    TZPPC *s = p->ppc;
    110    int n = p - s->port;
    111    AddressSpace *as = &p->downstream_as;
    112    uint64_t data;
    113    MemTxResult res;
    114
    115    if (!tz_ppc_check(s, n, attrs)) {
    116        trace_tz_ppc_read_blocked(n, addr, attrs.secure, attrs.user);
    117        if (s->cfg_sec_resp) {
    118            return MEMTX_ERROR;
    119        } else {
    120            *pdata = 0;
    121            return MEMTX_OK;
    122        }
    123    }
    124
    125    switch (size) {
    126    case 1:
    127        data = address_space_ldub(as, addr, attrs, &res);
    128        break;
    129    case 2:
    130        data = address_space_lduw_le(as, addr, attrs, &res);
    131        break;
    132    case 4:
    133        data = address_space_ldl_le(as, addr, attrs, &res);
    134        break;
    135    case 8:
    136        data = address_space_ldq_le(as, addr, attrs, &res);
    137        break;
    138    default:
    139        g_assert_not_reached();
    140    }
    141    *pdata = data;
    142    return res;
    143}
    144
    145static MemTxResult tz_ppc_write(void *opaque, hwaddr addr, uint64_t val,
    146                                unsigned size, MemTxAttrs attrs)
    147{
    148    TZPPCPort *p = opaque;
    149    TZPPC *s = p->ppc;
    150    AddressSpace *as = &p->downstream_as;
    151    int n = p - s->port;
    152    MemTxResult res;
    153
    154    if (!tz_ppc_check(s, n, attrs)) {
    155        trace_tz_ppc_write_blocked(n, addr, attrs.secure, attrs.user);
    156        if (s->cfg_sec_resp) {
    157            return MEMTX_ERROR;
    158        } else {
    159            return MEMTX_OK;
    160        }
    161    }
    162
    163    switch (size) {
    164    case 1:
    165        address_space_stb(as, addr, val, attrs, &res);
    166        break;
    167    case 2:
    168        address_space_stw_le(as, addr, val, attrs, &res);
    169        break;
    170    case 4:
    171        address_space_stl_le(as, addr, val, attrs, &res);
    172        break;
    173    case 8:
    174        address_space_stq_le(as, addr, val, attrs, &res);
    175        break;
    176    default:
    177        g_assert_not_reached();
    178    }
    179    return res;
    180}
    181
    182static const MemoryRegionOps tz_ppc_ops = {
    183    .read_with_attrs = tz_ppc_read,
    184    .write_with_attrs = tz_ppc_write,
    185    .endianness = DEVICE_LITTLE_ENDIAN,
    186};
    187
    188static bool tz_ppc_dummy_accepts(void *opaque, hwaddr addr,
    189                                 unsigned size, bool is_write,
    190                                 MemTxAttrs attrs)
    191{
    192    /*
    193     * Board code should never map the upstream end of an unused port,
    194     * so we should never try to make a memory access to it.
    195     */
    196    g_assert_not_reached();
    197}
    198
    199static uint64_t tz_ppc_dummy_read(void *opaque, hwaddr addr, unsigned size)
    200{
    201    g_assert_not_reached();
    202}
    203
    204static void tz_ppc_dummy_write(void *opaque, hwaddr addr,
    205                                        uint64_t data, unsigned size)
    206{
    207    g_assert_not_reached();
    208}
    209
    210static const MemoryRegionOps tz_ppc_dummy_ops = {
    211    /* define r/w methods to avoid assert failure in memory_region_init_io */
    212    .read = tz_ppc_dummy_read,
    213    .write = tz_ppc_dummy_write,
    214    .valid.accepts = tz_ppc_dummy_accepts,
    215};
    216
    217static void tz_ppc_reset(DeviceState *dev)
    218{
    219    TZPPC *s = TZ_PPC(dev);
    220
    221    trace_tz_ppc_reset();
    222    s->cfg_sec_resp = false;
    223    memset(s->cfg_nonsec, 0, sizeof(s->cfg_nonsec));
    224    memset(s->cfg_ap, 0, sizeof(s->cfg_ap));
    225}
    226
    227static void tz_ppc_init(Object *obj)
    228{
    229    DeviceState *dev = DEVICE(obj);
    230    TZPPC *s = TZ_PPC(obj);
    231
    232    qdev_init_gpio_in_named(dev, tz_ppc_cfg_nonsec, "cfg_nonsec", TZ_NUM_PORTS);
    233    qdev_init_gpio_in_named(dev, tz_ppc_cfg_ap, "cfg_ap", TZ_NUM_PORTS);
    234    qdev_init_gpio_in_named(dev, tz_ppc_cfg_sec_resp, "cfg_sec_resp", 1);
    235    qdev_init_gpio_in_named(dev, tz_ppc_irq_enable, "irq_enable", 1);
    236    qdev_init_gpio_in_named(dev, tz_ppc_irq_clear, "irq_clear", 1);
    237    qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
    238}
    239
    240static void tz_ppc_realize(DeviceState *dev, Error **errp)
    241{
    242    Object *obj = OBJECT(dev);
    243    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
    244    TZPPC *s = TZ_PPC(dev);
    245    int i;
    246    int max_port = 0;
    247
    248    /* We can't create the upstream end of the port until realize,
    249     * as we don't know the size of the MR used as the downstream until then.
    250     */
    251    for (i = 0; i < TZ_NUM_PORTS; i++) {
    252        if (s->port[i].downstream) {
    253            max_port = i;
    254        }
    255    }
    256
    257    for (i = 0; i <= max_port; i++) {
    258        TZPPCPort *port = &s->port[i];
    259        char *name;
    260        uint64_t size;
    261
    262        if (!port->downstream) {
    263            /*
    264             * Create dummy sysbus MMIO region so the sysbus region
    265             * numbering doesn't get out of sync with the port numbers.
    266             * The size is entirely arbitrary.
    267             */
    268            name = g_strdup_printf("tz-ppc-dummy-port[%d]", i);
    269            memory_region_init_io(&port->upstream, obj, &tz_ppc_dummy_ops,
    270                                  port, name, 0x10000);
    271            sysbus_init_mmio(sbd, &port->upstream);
    272            g_free(name);
    273            continue;
    274        }
    275
    276        name = g_strdup_printf("tz-ppc-port[%d]", i);
    277
    278        port->ppc = s;
    279        address_space_init(&port->downstream_as, port->downstream, name);
    280
    281        size = memory_region_size(port->downstream);
    282        memory_region_init_io(&port->upstream, obj, &tz_ppc_ops,
    283                              port, name, size);
    284        sysbus_init_mmio(sbd, &port->upstream);
    285        g_free(name);
    286    }
    287}
    288
    289static const VMStateDescription tz_ppc_vmstate = {
    290    .name = "tz-ppc",
    291    .version_id = 1,
    292    .minimum_version_id = 1,
    293    .fields = (VMStateField[]) {
    294        VMSTATE_BOOL_ARRAY(cfg_nonsec, TZPPC, 16),
    295        VMSTATE_BOOL_ARRAY(cfg_ap, TZPPC, 16),
    296        VMSTATE_BOOL(cfg_sec_resp, TZPPC),
    297        VMSTATE_BOOL(irq_enable, TZPPC),
    298        VMSTATE_BOOL(irq_clear, TZPPC),
    299        VMSTATE_BOOL(irq_status, TZPPC),
    300        VMSTATE_END_OF_LIST()
    301    }
    302};
    303
    304#define DEFINE_PORT(N)                                          \
    305    DEFINE_PROP_LINK("port[" #N "]", TZPPC, port[N].downstream, \
    306                     TYPE_MEMORY_REGION, MemoryRegion *)
    307
    308static Property tz_ppc_properties[] = {
    309    DEFINE_PROP_UINT32("NONSEC_MASK", TZPPC, nonsec_mask, 0),
    310    DEFINE_PORT(0),
    311    DEFINE_PORT(1),
    312    DEFINE_PORT(2),
    313    DEFINE_PORT(3),
    314    DEFINE_PORT(4),
    315    DEFINE_PORT(5),
    316    DEFINE_PORT(6),
    317    DEFINE_PORT(7),
    318    DEFINE_PORT(8),
    319    DEFINE_PORT(9),
    320    DEFINE_PORT(10),
    321    DEFINE_PORT(11),
    322    DEFINE_PORT(12),
    323    DEFINE_PORT(13),
    324    DEFINE_PORT(14),
    325    DEFINE_PORT(15),
    326    DEFINE_PROP_END_OF_LIST(),
    327};
    328
    329static void tz_ppc_class_init(ObjectClass *klass, void *data)
    330{
    331    DeviceClass *dc = DEVICE_CLASS(klass);
    332
    333    dc->realize = tz_ppc_realize;
    334    dc->vmsd = &tz_ppc_vmstate;
    335    dc->reset = tz_ppc_reset;
    336    device_class_set_props(dc, tz_ppc_properties);
    337}
    338
    339static const TypeInfo tz_ppc_info = {
    340    .name = TYPE_TZ_PPC,
    341    .parent = TYPE_SYS_BUS_DEVICE,
    342    .instance_size = sizeof(TZPPC),
    343    .instance_init = tz_ppc_init,
    344    .class_init = tz_ppc_class_init,
    345};
    346
    347static void tz_ppc_register_types(void)
    348{
    349    type_register_static(&tz_ppc_info);
    350}
    351
    352type_init(tz_ppc_register_types);