qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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 
     24 static 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 
     32 static 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 
     41 static 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 
     50 static 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 
     58 static 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 
     67 static 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 
     80 static 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 
    105 static 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 
    145 static 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 
    182 static 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 
    188 static 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 
    199 static uint64_t tz_ppc_dummy_read(void *opaque, hwaddr addr, unsigned size)
    200 {
    201     g_assert_not_reached();
    202 }
    203 
    204 static void tz_ppc_dummy_write(void *opaque, hwaddr addr,
    205                                         uint64_t data, unsigned size)
    206 {
    207     g_assert_not_reached();
    208 }
    209 
    210 static 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 
    217 static 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 
    227 static 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 
    240 static 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 
    289 static 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 
    308 static 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 
    329 static 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 
    339 static 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 
    347 static void tz_ppc_register_types(void)
    348 {
    349     type_register_static(&tz_ppc_info);
    350 }
    351 
    352 type_init(tz_ppc_register_types);