qemu/hw/misc/tz-msc.c
<<
>>
Prefs
   1/*
   2 * ARM TrustZone master security 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-msc.h"
  22#include "hw/qdev-properties.h"
  23
  24static void tz_msc_update_irq(TZMSC *s)
  25{
  26    bool level = s->irq_status;
  27
  28    trace_tz_msc_update_irq(level);
  29    qemu_set_irq(s->irq, level);
  30}
  31
  32static void tz_msc_cfg_nonsec(void *opaque, int n, int level)
  33{
  34    TZMSC *s = TZ_MSC(opaque);
  35
  36    trace_tz_msc_cfg_nonsec(level);
  37    s->cfg_nonsec = level;
  38}
  39
  40static void tz_msc_cfg_sec_resp(void *opaque, int n, int level)
  41{
  42    TZMSC *s = TZ_MSC(opaque);
  43
  44    trace_tz_msc_cfg_sec_resp(level);
  45    s->cfg_sec_resp = level;
  46}
  47
  48static void tz_msc_irq_clear(void *opaque, int n, int level)
  49{
  50    TZMSC *s = TZ_MSC(opaque);
  51
  52    trace_tz_msc_irq_clear(level);
  53
  54    s->irq_clear = level;
  55    if (level) {
  56        s->irq_status = false;
  57        tz_msc_update_irq(s);
  58    }
  59}
  60
  61/* The MSC may either block a transaction by aborting it, block a
  62 * transaction by making it RAZ/WI, allow it through with
  63 * MemTxAttrs indicating a secure transaction, or allow it with
  64 * MemTxAttrs indicating a non-secure transaction.
  65 */
  66typedef enum MSCAction {
  67    MSCBlockAbort,
  68    MSCBlockRAZWI,
  69    MSCAllowSecure,
  70    MSCAllowNonSecure,
  71} MSCAction;
  72
  73static MSCAction tz_msc_check(TZMSC *s, hwaddr addr)
  74{
  75    /*
  76     * Check whether to allow an access from the bus master, returning
  77     * an MSCAction indicating the required behaviour. If the transaction
  78     * is blocked, the caller must check cfg_sec_resp to determine
  79     * whether to abort or RAZ/WI the transaction.
  80     */
  81    IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(s->idau);
  82    IDAUInterface *ii = IDAU_INTERFACE(s->idau);
  83    bool idau_exempt = false, idau_ns = true, idau_nsc = true;
  84    int idau_region = IREGION_NOTVALID;
  85
  86    iic->check(ii, addr, &idau_region, &idau_exempt, &idau_ns, &idau_nsc);
  87
  88    if (idau_exempt) {
  89        /*
  90         * Uncheck region -- OK, transaction type depends on
  91         * whether bus master is configured as Secure or NonSecure
  92         */
  93        return s->cfg_nonsec ? MSCAllowNonSecure : MSCAllowSecure;
  94    }
  95
  96    if (idau_ns) {
  97        /* NonSecure region -- always forward as NS transaction */
  98        return MSCAllowNonSecure;
  99    }
 100
 101    if (!s->cfg_nonsec) {
 102        /* Access to Secure region by Secure bus master: OK */
 103        return MSCAllowSecure;
 104    }
 105
 106    /* Attempted access to Secure region by NS bus master: block */
 107    trace_tz_msc_access_blocked(addr);
 108    if (!s->cfg_sec_resp) {
 109        return MSCBlockRAZWI;
 110    }
 111
 112    /*
 113     * The TRM isn't clear on behaviour if irq_clear is high when a
 114     * transaction is blocked. We assume that the MSC behaves like the
 115     * PPC, where holding irq_clear high suppresses the interrupt.
 116     */
 117    if (!s->irq_clear) {
 118        s->irq_status = true;
 119        tz_msc_update_irq(s);
 120    }
 121    return MSCBlockAbort;
 122}
 123
 124static MemTxResult tz_msc_read(void *opaque, hwaddr addr, uint64_t *pdata,
 125                               unsigned size, MemTxAttrs attrs)
 126{
 127    TZMSC *s = opaque;
 128    AddressSpace *as = &s->downstream_as;
 129    uint64_t data;
 130    MemTxResult res;
 131
 132    switch (tz_msc_check(s, addr)) {
 133    case MSCBlockAbort:
 134        return MEMTX_ERROR;
 135    case MSCBlockRAZWI:
 136        *pdata = 0;
 137        return MEMTX_OK;
 138    case MSCAllowSecure:
 139        attrs.secure = 1;
 140        attrs.unspecified = 0;
 141        break;
 142    case MSCAllowNonSecure:
 143        attrs.secure = 0;
 144        attrs.unspecified = 0;
 145        break;
 146    }
 147
 148    switch (size) {
 149    case 1:
 150        data = address_space_ldub(as, addr, attrs, &res);
 151        break;
 152    case 2:
 153        data = address_space_lduw_le(as, addr, attrs, &res);
 154        break;
 155    case 4:
 156        data = address_space_ldl_le(as, addr, attrs, &res);
 157        break;
 158    case 8:
 159        data = address_space_ldq_le(as, addr, attrs, &res);
 160        break;
 161    default:
 162        g_assert_not_reached();
 163    }
 164    *pdata = data;
 165    return res;
 166}
 167
 168static MemTxResult tz_msc_write(void *opaque, hwaddr addr, uint64_t val,
 169                                unsigned size, MemTxAttrs attrs)
 170{
 171    TZMSC *s = opaque;
 172    AddressSpace *as = &s->downstream_as;
 173    MemTxResult res;
 174
 175    switch (tz_msc_check(s, addr)) {
 176    case MSCBlockAbort:
 177        return MEMTX_ERROR;
 178    case MSCBlockRAZWI:
 179        return MEMTX_OK;
 180    case MSCAllowSecure:
 181        attrs.secure = 1;
 182        attrs.unspecified = 0;
 183        break;
 184    case MSCAllowNonSecure:
 185        attrs.secure = 0;
 186        attrs.unspecified = 0;
 187        break;
 188    }
 189
 190    switch (size) {
 191    case 1:
 192        address_space_stb(as, addr, val, attrs, &res);
 193        break;
 194    case 2:
 195        address_space_stw_le(as, addr, val, attrs, &res);
 196        break;
 197    case 4:
 198        address_space_stl_le(as, addr, val, attrs, &res);
 199        break;
 200    case 8:
 201        address_space_stq_le(as, addr, val, attrs, &res);
 202        break;
 203    default:
 204        g_assert_not_reached();
 205    }
 206    return res;
 207}
 208
 209static const MemoryRegionOps tz_msc_ops = {
 210    .read_with_attrs = tz_msc_read,
 211    .write_with_attrs = tz_msc_write,
 212    .endianness = DEVICE_LITTLE_ENDIAN,
 213};
 214
 215static void tz_msc_reset(DeviceState *dev)
 216{
 217    TZMSC *s = TZ_MSC(dev);
 218
 219    trace_tz_msc_reset();
 220    s->cfg_sec_resp = false;
 221    s->cfg_nonsec = false;
 222    s->irq_clear = 0;
 223    s->irq_status = 0;
 224}
 225
 226static void tz_msc_init(Object *obj)
 227{
 228    DeviceState *dev = DEVICE(obj);
 229    TZMSC *s = TZ_MSC(obj);
 230
 231    qdev_init_gpio_in_named(dev, tz_msc_cfg_nonsec, "cfg_nonsec", 1);
 232    qdev_init_gpio_in_named(dev, tz_msc_cfg_sec_resp, "cfg_sec_resp", 1);
 233    qdev_init_gpio_in_named(dev, tz_msc_irq_clear, "irq_clear", 1);
 234    qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
 235}
 236
 237static void tz_msc_realize(DeviceState *dev, Error **errp)
 238{
 239    Object *obj = OBJECT(dev);
 240    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 241    TZMSC *s = TZ_MSC(dev);
 242    const char *name = "tz-msc-downstream";
 243    uint64_t size;
 244
 245    /*
 246     * We can't create the upstream end of the port until realize,
 247     * as we don't know the size of the MR used as the downstream until then.
 248     * We insist on having a downstream, to avoid complicating the
 249     * code with handling the "don't know how big this is" case. It's easy
 250     * enough for the user to create an unimplemented_device as downstream
 251     * if they have nothing else to plug into this.
 252     */
 253    if (!s->downstream) {
 254        error_setg(errp, "MSC 'downstream' link not set");
 255        return;
 256    }
 257    if (!s->idau) {
 258        error_setg(errp, "MSC 'idau' link not set");
 259        return;
 260    }
 261
 262    size = memory_region_size(s->downstream);
 263    address_space_init(&s->downstream_as, s->downstream, name);
 264    memory_region_init_io(&s->upstream, obj, &tz_msc_ops, s, name, size);
 265    sysbus_init_mmio(sbd, &s->upstream);
 266}
 267
 268static const VMStateDescription tz_msc_vmstate = {
 269    .name = "tz-msc",
 270    .version_id = 1,
 271    .minimum_version_id = 1,
 272    .fields = (VMStateField[]) {
 273        VMSTATE_BOOL(cfg_nonsec, TZMSC),
 274        VMSTATE_BOOL(cfg_sec_resp, TZMSC),
 275        VMSTATE_BOOL(irq_clear, TZMSC),
 276        VMSTATE_BOOL(irq_status, TZMSC),
 277        VMSTATE_END_OF_LIST()
 278    }
 279};
 280
 281static Property tz_msc_properties[] = {
 282    DEFINE_PROP_LINK("downstream", TZMSC, downstream,
 283                     TYPE_MEMORY_REGION, MemoryRegion *),
 284    DEFINE_PROP_LINK("idau", TZMSC, idau,
 285                     TYPE_IDAU_INTERFACE, IDAUInterface *),
 286    DEFINE_PROP_END_OF_LIST(),
 287};
 288
 289static void tz_msc_class_init(ObjectClass *klass, void *data)
 290{
 291    DeviceClass *dc = DEVICE_CLASS(klass);
 292
 293    dc->realize = tz_msc_realize;
 294    dc->vmsd = &tz_msc_vmstate;
 295    dc->reset = tz_msc_reset;
 296    device_class_set_props(dc, tz_msc_properties);
 297}
 298
 299static const TypeInfo tz_msc_info = {
 300    .name = TYPE_TZ_MSC,
 301    .parent = TYPE_SYS_BUS_DEVICE,
 302    .instance_size = sizeof(TZMSC),
 303    .instance_init = tz_msc_init,
 304    .class_init = tz_msc_class_init,
 305};
 306
 307static void tz_msc_register_types(void)
 308{
 309    type_register_static(&tz_msc_info);
 310}
 311
 312type_init(tz_msc_register_types);
 313