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

iotkit-secctl.c (24134B)


      1/*
      2 * Arm IoT Kit security controller
      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/iotkit-secctl.h"
     22#include "hw/arm/armsse-version.h"
     23#include "hw/qdev-properties.h"
     24
     25/* Registers in the secure privilege control block */
     26REG32(SECRESPCFG, 0x10)
     27REG32(NSCCFG, 0x14)
     28REG32(SECMPCINTSTATUS, 0x1c)
     29REG32(SECPPCINTSTAT, 0x20)
     30REG32(SECPPCINTCLR, 0x24)
     31REG32(SECPPCINTEN, 0x28)
     32REG32(SECMSCINTSTAT, 0x30)
     33REG32(SECMSCINTCLR, 0x34)
     34REG32(SECMSCINTEN, 0x38)
     35REG32(BRGINTSTAT, 0x40)
     36REG32(BRGINTCLR, 0x44)
     37REG32(BRGINTEN, 0x48)
     38REG32(AHBNSPPC0, 0x50)
     39REG32(AHBNSPPCEXP0, 0x60)
     40REG32(AHBNSPPCEXP1, 0x64)
     41REG32(AHBNSPPCEXP2, 0x68)
     42REG32(AHBNSPPCEXP3, 0x6c)
     43REG32(APBNSPPC0, 0x70)
     44REG32(APBNSPPC1, 0x74)
     45REG32(APBNSPPCEXP0, 0x80)
     46REG32(APBNSPPCEXP1, 0x84)
     47REG32(APBNSPPCEXP2, 0x88)
     48REG32(APBNSPPCEXP3, 0x8c)
     49REG32(AHBSPPPC0, 0x90)
     50REG32(AHBSPPPCEXP0, 0xa0)
     51REG32(AHBSPPPCEXP1, 0xa4)
     52REG32(AHBSPPPCEXP2, 0xa8)
     53REG32(AHBSPPPCEXP3, 0xac)
     54REG32(APBSPPPC0, 0xb0)
     55REG32(APBSPPPC1, 0xb4)
     56REG32(APBSPPPCEXP0, 0xc0)
     57REG32(APBSPPPCEXP1, 0xc4)
     58REG32(APBSPPPCEXP2, 0xc8)
     59REG32(APBSPPPCEXP3, 0xcc)
     60REG32(NSMSCEXP, 0xd0)
     61REG32(PID4, 0xfd0)
     62REG32(PID5, 0xfd4)
     63REG32(PID6, 0xfd8)
     64REG32(PID7, 0xfdc)
     65REG32(PID0, 0xfe0)
     66REG32(PID1, 0xfe4)
     67REG32(PID2, 0xfe8)
     68REG32(PID3, 0xfec)
     69REG32(CID0, 0xff0)
     70REG32(CID1, 0xff4)
     71REG32(CID2, 0xff8)
     72REG32(CID3, 0xffc)
     73
     74/* Registers in the non-secure privilege control block */
     75REG32(AHBNSPPPC0, 0x90)
     76REG32(AHBNSPPPCEXP0, 0xa0)
     77REG32(AHBNSPPPCEXP1, 0xa4)
     78REG32(AHBNSPPPCEXP2, 0xa8)
     79REG32(AHBNSPPPCEXP3, 0xac)
     80REG32(APBNSPPPC0, 0xb0)
     81REG32(APBNSPPPC1, 0xb4)
     82REG32(APBNSPPPCEXP0, 0xc0)
     83REG32(APBNSPPPCEXP1, 0xc4)
     84REG32(APBNSPPPCEXP2, 0xc8)
     85REG32(APBNSPPPCEXP3, 0xcc)
     86/* PID and CID registers are also present in the NS block */
     87
     88static const uint8_t iotkit_secctl_s_idregs[] = {
     89    0x04, 0x00, 0x00, 0x00,
     90    0x52, 0xb8, 0x0b, 0x00,
     91    0x0d, 0xf0, 0x05, 0xb1,
     92};
     93
     94static const uint8_t iotkit_secctl_ns_idregs[] = {
     95    0x04, 0x00, 0x00, 0x00,
     96    0x53, 0xb8, 0x0b, 0x00,
     97    0x0d, 0xf0, 0x05, 0xb1,
     98};
     99
    100static const uint8_t iotkit_secctl_s_sse300_idregs[] = {
    101    0x04, 0x00, 0x00, 0x00,
    102    0x52, 0xb8, 0x2b, 0x00,
    103    0x0d, 0xf0, 0x05, 0xb1,
    104};
    105
    106static const uint8_t iotkit_secctl_ns_sse300_idregs[] = {
    107    0x04, 0x00, 0x00, 0x00,
    108    0x53, 0xb8, 0x2b, 0x00,
    109    0x0d, 0xf0, 0x05, 0xb1,
    110};
    111
    112
    113/* The register sets for the various PPCs (AHB internal, APB internal,
    114 * AHB expansion, APB expansion) are all set up so that they are
    115 * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
    116 * 0, 1, 2, 3 of that type, so we can convert a register address offset
    117 * into an an index into a PPC array easily.
    118 */
    119static inline int offset_to_ppc_idx(uint32_t offset)
    120{
    121    return extract32(offset, 2, 2);
    122}
    123
    124typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
    125
    126static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
    127{
    128    int i;
    129
    130    for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
    131        fn(&s->apb[i]);
    132    }
    133    for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
    134        fn(&s->apbexp[i]);
    135    }
    136    for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
    137        fn(&s->ahbexp[i]);
    138    }
    139}
    140
    141static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
    142                                        uint64_t *pdata,
    143                                        unsigned size, MemTxAttrs attrs)
    144{
    145    uint64_t r;
    146    uint32_t offset = addr & ~0x3;
    147    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
    148
    149    switch (offset) {
    150    case A_AHBNSPPC0:
    151    case A_AHBSPPPC0:
    152        r = 0;
    153        break;
    154    case A_SECRESPCFG:
    155        r = s->secrespcfg;
    156        break;
    157    case A_NSCCFG:
    158        r = s->nsccfg;
    159        break;
    160    case A_SECMPCINTSTATUS:
    161        r = s->mpcintstatus;
    162        break;
    163    case A_SECPPCINTSTAT:
    164        r = s->secppcintstat;
    165        break;
    166    case A_SECPPCINTEN:
    167        r = s->secppcinten;
    168        break;
    169    case A_BRGINTSTAT:
    170        /* QEMU's bus fabric can never report errors as it doesn't buffer
    171         * writes, so we never report bridge interrupts.
    172         */
    173        r = 0;
    174        break;
    175    case A_BRGINTEN:
    176        r = s->brginten;
    177        break;
    178    case A_AHBNSPPCEXP0:
    179    case A_AHBNSPPCEXP1:
    180    case A_AHBNSPPCEXP2:
    181    case A_AHBNSPPCEXP3:
    182        r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
    183        break;
    184    case A_APBNSPPC0:
    185    case A_APBNSPPC1:
    186        r = s->apb[offset_to_ppc_idx(offset)].ns;
    187        break;
    188    case A_APBNSPPCEXP0:
    189    case A_APBNSPPCEXP1:
    190    case A_APBNSPPCEXP2:
    191    case A_APBNSPPCEXP3:
    192        r = s->apbexp[offset_to_ppc_idx(offset)].ns;
    193        break;
    194    case A_AHBSPPPCEXP0:
    195    case A_AHBSPPPCEXP1:
    196    case A_AHBSPPPCEXP2:
    197    case A_AHBSPPPCEXP3:
    198        r = s->apbexp[offset_to_ppc_idx(offset)].sp;
    199        break;
    200    case A_APBSPPPC0:
    201    case A_APBSPPPC1:
    202        r = s->apb[offset_to_ppc_idx(offset)].sp;
    203        break;
    204    case A_APBSPPPCEXP0:
    205    case A_APBSPPPCEXP1:
    206    case A_APBSPPPCEXP2:
    207    case A_APBSPPPCEXP3:
    208        r = s->apbexp[offset_to_ppc_idx(offset)].sp;
    209        break;
    210    case A_SECMSCINTSTAT:
    211        r = s->secmscintstat;
    212        break;
    213    case A_SECMSCINTEN:
    214        r = s->secmscinten;
    215        break;
    216    case A_NSMSCEXP:
    217        r = s->nsmscexp;
    218        break;
    219    case A_PID4:
    220    case A_PID5:
    221    case A_PID6:
    222    case A_PID7:
    223    case A_PID0:
    224    case A_PID1:
    225    case A_PID2:
    226    case A_PID3:
    227    case A_CID0:
    228    case A_CID1:
    229    case A_CID2:
    230    case A_CID3:
    231        switch (s->sse_version) {
    232        case ARMSSE_SSE300:
    233            r = iotkit_secctl_s_sse300_idregs[(offset - A_PID4) / 4];
    234            break;
    235        default:
    236            r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
    237            break;
    238        }
    239        break;
    240    case A_SECPPCINTCLR:
    241    case A_SECMSCINTCLR:
    242    case A_BRGINTCLR:
    243        qemu_log_mask(LOG_GUEST_ERROR,
    244                      "IotKit SecCtl S block read: write-only offset 0x%x\n",
    245                      offset);
    246        r = 0;
    247        break;
    248    default:
    249        qemu_log_mask(LOG_GUEST_ERROR,
    250                      "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
    251        r = 0;
    252        break;
    253    }
    254
    255    if (size != 4) {
    256        /* None of our registers are access-sensitive, so just pull the right
    257         * byte out of the word read result.
    258         */
    259        r = extract32(r, (addr & 3) * 8, size * 8);
    260    }
    261
    262    trace_iotkit_secctl_s_read(offset, r, size);
    263    *pdata = r;
    264    return MEMTX_OK;
    265}
    266
    267static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
    268{
    269    int i;
    270
    271    for (i = 0; i < ppc->numports; i++) {
    272        bool v;
    273
    274        if (extract32(ppc->ns, i, 1)) {
    275            v = extract32(ppc->nsp, i, 1);
    276        } else {
    277            v = extract32(ppc->sp, i, 1);
    278        }
    279        qemu_set_irq(ppc->ap[i], v);
    280    }
    281}
    282
    283static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
    284{
    285    int i;
    286
    287    ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
    288    for (i = 0; i < ppc->numports; i++) {
    289        qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
    290    }
    291    iotkit_secctl_update_ppc_ap(ppc);
    292}
    293
    294static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
    295{
    296    ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
    297    iotkit_secctl_update_ppc_ap(ppc);
    298}
    299
    300static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
    301{
    302    ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
    303    iotkit_secctl_update_ppc_ap(ppc);
    304}
    305
    306static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
    307{
    308    uint32_t value = ppc->parent->secppcintstat;
    309
    310    qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
    311}
    312
    313static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
    314{
    315    uint32_t value = ppc->parent->secppcinten;
    316
    317    qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
    318}
    319
    320static void iotkit_secctl_update_mscexp_irqs(qemu_irq *msc_irqs, uint32_t value)
    321{
    322    int i;
    323
    324    for (i = 0; i < IOTS_NUM_EXP_MSC; i++) {
    325        qemu_set_irq(msc_irqs[i], extract32(value, i + 16, 1));
    326    }
    327}
    328
    329static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s)
    330{
    331    /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_EN */
    332    bool level = s->secmscintstat & s->secmscinten;
    333
    334    qemu_set_irq(s->msc_irq, level);
    335}
    336
    337static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
    338                                         uint64_t value,
    339                                         unsigned size, MemTxAttrs attrs)
    340{
    341    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
    342    uint32_t offset = addr;
    343    IoTKitSecCtlPPC *ppc;
    344
    345    trace_iotkit_secctl_s_write(offset, value, size);
    346
    347    if (size != 4) {
    348        /* Byte and halfword writes are ignored */
    349        qemu_log_mask(LOG_GUEST_ERROR,
    350                      "IotKit SecCtl S block write: bad size, ignored\n");
    351        return MEMTX_OK;
    352    }
    353
    354    switch (offset) {
    355    case A_NSCCFG:
    356        s->nsccfg = value & 3;
    357        qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
    358        break;
    359    case A_SECRESPCFG:
    360        value &= 1;
    361        s->secrespcfg = value;
    362        qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
    363        break;
    364    case A_SECPPCINTCLR:
    365        s->secppcintstat &= ~(value & 0x00f000f3);
    366        foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
    367        break;
    368    case A_SECPPCINTEN:
    369        s->secppcinten = value & 0x00f000f3;
    370        foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
    371        break;
    372    case A_BRGINTCLR:
    373        break;
    374    case A_BRGINTEN:
    375        s->brginten = value & 0xffff0000;
    376        break;
    377    case A_AHBNSPPCEXP0:
    378    case A_AHBNSPPCEXP1:
    379    case A_AHBNSPPCEXP2:
    380    case A_AHBNSPPCEXP3:
    381        ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
    382        iotkit_secctl_ppc_ns_write(ppc, value);
    383        break;
    384    case A_APBNSPPC0:
    385    case A_APBNSPPC1:
    386        ppc = &s->apb[offset_to_ppc_idx(offset)];
    387        iotkit_secctl_ppc_ns_write(ppc, value);
    388        break;
    389    case A_APBNSPPCEXP0:
    390    case A_APBNSPPCEXP1:
    391    case A_APBNSPPCEXP2:
    392    case A_APBNSPPCEXP3:
    393        ppc = &s->apbexp[offset_to_ppc_idx(offset)];
    394        iotkit_secctl_ppc_ns_write(ppc, value);
    395        break;
    396    case A_AHBSPPPCEXP0:
    397    case A_AHBSPPPCEXP1:
    398    case A_AHBSPPPCEXP2:
    399    case A_AHBSPPPCEXP3:
    400        ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
    401        iotkit_secctl_ppc_sp_write(ppc, value);
    402        break;
    403    case A_APBSPPPC0:
    404    case A_APBSPPPC1:
    405        ppc = &s->apb[offset_to_ppc_idx(offset)];
    406        iotkit_secctl_ppc_sp_write(ppc, value);
    407        break;
    408    case A_APBSPPPCEXP0:
    409    case A_APBSPPPCEXP1:
    410    case A_APBSPPPCEXP2:
    411    case A_APBSPPPCEXP3:
    412        ppc = &s->apbexp[offset_to_ppc_idx(offset)];
    413        iotkit_secctl_ppc_sp_write(ppc, value);
    414        break;
    415    case A_SECMSCINTCLR:
    416        iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value);
    417        break;
    418    case A_SECMSCINTEN:
    419        s->secmscinten = value;
    420        iotkit_secctl_update_msc_irq(s);
    421        break;
    422    case A_NSMSCEXP:
    423        s->nsmscexp = value;
    424        iotkit_secctl_update_mscexp_irqs(s->mscexp_ns, value);
    425        break;
    426    case A_SECMPCINTSTATUS:
    427    case A_SECPPCINTSTAT:
    428    case A_SECMSCINTSTAT:
    429    case A_BRGINTSTAT:
    430    case A_AHBNSPPC0:
    431    case A_AHBSPPPC0:
    432    case A_PID4:
    433    case A_PID5:
    434    case A_PID6:
    435    case A_PID7:
    436    case A_PID0:
    437    case A_PID1:
    438    case A_PID2:
    439    case A_PID3:
    440    case A_CID0:
    441    case A_CID1:
    442    case A_CID2:
    443    case A_CID3:
    444        qemu_log_mask(LOG_GUEST_ERROR,
    445                      "IoTKit SecCtl S block write: "
    446                      "read-only offset 0x%x\n", offset);
    447        break;
    448    default:
    449        qemu_log_mask(LOG_GUEST_ERROR,
    450                      "IotKit SecCtl S block write: bad offset 0x%x\n",
    451                      offset);
    452        break;
    453    }
    454
    455    return MEMTX_OK;
    456}
    457
    458static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
    459                                         uint64_t *pdata,
    460                                         unsigned size, MemTxAttrs attrs)
    461{
    462    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
    463    uint64_t r;
    464    uint32_t offset = addr & ~0x3;
    465
    466    switch (offset) {
    467    case A_AHBNSPPPC0:
    468        r = 0;
    469        break;
    470    case A_AHBNSPPPCEXP0:
    471    case A_AHBNSPPPCEXP1:
    472    case A_AHBNSPPPCEXP2:
    473    case A_AHBNSPPPCEXP3:
    474        r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
    475        break;
    476    case A_APBNSPPPC0:
    477    case A_APBNSPPPC1:
    478        r = s->apb[offset_to_ppc_idx(offset)].nsp;
    479        break;
    480    case A_APBNSPPPCEXP0:
    481    case A_APBNSPPPCEXP1:
    482    case A_APBNSPPPCEXP2:
    483    case A_APBNSPPPCEXP3:
    484        r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
    485        break;
    486    case A_PID4:
    487    case A_PID5:
    488    case A_PID6:
    489    case A_PID7:
    490    case A_PID0:
    491    case A_PID1:
    492    case A_PID2:
    493    case A_PID3:
    494    case A_CID0:
    495    case A_CID1:
    496    case A_CID2:
    497    case A_CID3:
    498        switch (s->sse_version) {
    499        case ARMSSE_SSE300:
    500            r = iotkit_secctl_ns_sse300_idregs[(offset - A_PID4) / 4];
    501            break;
    502        default:
    503            r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
    504            break;
    505        }
    506        break;
    507    default:
    508        qemu_log_mask(LOG_GUEST_ERROR,
    509                      "IotKit SecCtl NS block write: bad offset 0x%x\n",
    510                      offset);
    511        r = 0;
    512        break;
    513    }
    514
    515    if (size != 4) {
    516        /* None of our registers are access-sensitive, so just pull the right
    517         * byte out of the word read result.
    518         */
    519        r = extract32(r, (addr & 3) * 8, size * 8);
    520    }
    521
    522    trace_iotkit_secctl_ns_read(offset, r, size);
    523    *pdata = r;
    524    return MEMTX_OK;
    525}
    526
    527static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
    528                                          uint64_t value,
    529                                          unsigned size, MemTxAttrs attrs)
    530{
    531    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
    532    uint32_t offset = addr;
    533    IoTKitSecCtlPPC *ppc;
    534
    535    trace_iotkit_secctl_ns_write(offset, value, size);
    536
    537    if (size != 4) {
    538        /* Byte and halfword writes are ignored */
    539        qemu_log_mask(LOG_GUEST_ERROR,
    540                      "IotKit SecCtl NS block write: bad size, ignored\n");
    541        return MEMTX_OK;
    542    }
    543
    544    switch (offset) {
    545    case A_AHBNSPPPCEXP0:
    546    case A_AHBNSPPPCEXP1:
    547    case A_AHBNSPPPCEXP2:
    548    case A_AHBNSPPPCEXP3:
    549        ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
    550        iotkit_secctl_ppc_nsp_write(ppc, value);
    551        break;
    552    case A_APBNSPPPC0:
    553    case A_APBNSPPPC1:
    554        ppc = &s->apb[offset_to_ppc_idx(offset)];
    555        iotkit_secctl_ppc_nsp_write(ppc, value);
    556        break;
    557    case A_APBNSPPPCEXP0:
    558    case A_APBNSPPPCEXP1:
    559    case A_APBNSPPPCEXP2:
    560    case A_APBNSPPPCEXP3:
    561        ppc = &s->apbexp[offset_to_ppc_idx(offset)];
    562        iotkit_secctl_ppc_nsp_write(ppc, value);
    563        break;
    564    case A_AHBNSPPPC0:
    565    case A_PID4:
    566    case A_PID5:
    567    case A_PID6:
    568    case A_PID7:
    569    case A_PID0:
    570    case A_PID1:
    571    case A_PID2:
    572    case A_PID3:
    573    case A_CID0:
    574    case A_CID1:
    575    case A_CID2:
    576    case A_CID3:
    577        qemu_log_mask(LOG_GUEST_ERROR,
    578                      "IoTKit SecCtl NS block write: "
    579                      "read-only offset 0x%x\n", offset);
    580        break;
    581    default:
    582        qemu_log_mask(LOG_GUEST_ERROR,
    583                      "IotKit SecCtl NS block write: bad offset 0x%x\n",
    584                      offset);
    585        break;
    586    }
    587
    588    return MEMTX_OK;
    589}
    590
    591static const MemoryRegionOps iotkit_secctl_s_ops = {
    592    .read_with_attrs = iotkit_secctl_s_read,
    593    .write_with_attrs = iotkit_secctl_s_write,
    594    .endianness = DEVICE_LITTLE_ENDIAN,
    595    .valid.min_access_size = 1,
    596    .valid.max_access_size = 4,
    597    .impl.min_access_size = 1,
    598    .impl.max_access_size = 4,
    599};
    600
    601static const MemoryRegionOps iotkit_secctl_ns_ops = {
    602    .read_with_attrs = iotkit_secctl_ns_read,
    603    .write_with_attrs = iotkit_secctl_ns_write,
    604    .endianness = DEVICE_LITTLE_ENDIAN,
    605    .valid.min_access_size = 1,
    606    .valid.max_access_size = 4,
    607    .impl.min_access_size = 1,
    608    .impl.max_access_size = 4,
    609};
    610
    611static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
    612{
    613    ppc->ns = 0;
    614    ppc->sp = 0;
    615    ppc->nsp = 0;
    616}
    617
    618static void iotkit_secctl_reset(DeviceState *dev)
    619{
    620    IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
    621
    622    s->secppcintstat = 0;
    623    s->secppcinten = 0;
    624    s->secrespcfg = 0;
    625    s->nsccfg = 0;
    626    s->brginten = 0;
    627
    628    foreach_ppc(s, iotkit_secctl_reset_ppc);
    629}
    630
    631static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
    632{
    633    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
    634
    635    s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
    636}
    637
    638static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
    639{
    640    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
    641
    642    s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
    643}
    644
    645static void iotkit_secctl_mscexp_status(void *opaque, int n, int level)
    646{
    647    IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
    648
    649    s->secmscintstat = deposit32(s->secmscintstat, n + 16, 1, !!level);
    650    iotkit_secctl_update_msc_irq(s);
    651}
    652
    653static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
    654{
    655    IoTKitSecCtlPPC *ppc = opaque;
    656    IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
    657    int irqbit = ppc->irq_bit_offset + n;
    658
    659    s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
    660}
    661
    662static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
    663                                   IoTKitSecCtlPPC *ppc,
    664                                   const char *name,
    665                                   int numports,
    666                                   int irq_bit_offset)
    667{
    668    char *gpioname;
    669    DeviceState *dev = DEVICE(s);
    670
    671    ppc->numports = numports;
    672    ppc->irq_bit_offset = irq_bit_offset;
    673    ppc->parent = s;
    674
    675    gpioname = g_strdup_printf("%s_nonsec", name);
    676    qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
    677    g_free(gpioname);
    678    gpioname = g_strdup_printf("%s_ap", name);
    679    qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
    680    g_free(gpioname);
    681    gpioname = g_strdup_printf("%s_irq_enable", name);
    682    qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
    683    g_free(gpioname);
    684    gpioname = g_strdup_printf("%s_irq_clear", name);
    685    qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
    686    g_free(gpioname);
    687    gpioname = g_strdup_printf("%s_irq_status", name);
    688    qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
    689                                        ppc, gpioname, 1);
    690    g_free(gpioname);
    691}
    692
    693static void iotkit_secctl_init(Object *obj)
    694{
    695    IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
    696    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    697    DeviceState *dev = DEVICE(obj);
    698    int i;
    699
    700    iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
    701                           IOTS_APB_PPC0_NUM_PORTS, 0);
    702    iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
    703                           IOTS_APB_PPC1_NUM_PORTS, 1);
    704
    705    for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
    706        IoTKitSecCtlPPC *ppc = &s->apbexp[i];
    707        char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
    708        iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
    709        g_free(ppcname);
    710    }
    711    for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
    712        IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
    713        char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
    714        iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
    715        g_free(ppcname);
    716    }
    717
    718    qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
    719    qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
    720
    721    qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
    722                            IOTS_NUM_MPC);
    723    qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
    724                            "mpcexp_status", IOTS_NUM_EXP_MPC);
    725
    726    qdev_init_gpio_in_named(dev, iotkit_secctl_mscexp_status,
    727                            "mscexp_status", IOTS_NUM_EXP_MSC);
    728    qdev_init_gpio_out_named(dev, s->mscexp_clear, "mscexp_clear",
    729                             IOTS_NUM_EXP_MSC);
    730    qdev_init_gpio_out_named(dev, s->mscexp_ns, "mscexp_ns",
    731                             IOTS_NUM_EXP_MSC);
    732    qdev_init_gpio_out_named(dev, &s->msc_irq, "msc_irq", 1);
    733
    734    memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
    735                          s, "iotkit-secctl-s-regs", 0x1000);
    736    memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
    737                          s, "iotkit-secctl-ns-regs", 0x1000);
    738    sysbus_init_mmio(sbd, &s->s_regs);
    739    sysbus_init_mmio(sbd, &s->ns_regs);
    740}
    741
    742static void iotkit_secctl_realize(DeviceState *dev, Error **errp)
    743{
    744    IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
    745
    746    if (!armsse_version_valid(s->sse_version)) {
    747        error_setg(errp, "invalid sse-version value %d", s->sse_version);
    748        return;
    749    }
    750}
    751
    752static const VMStateDescription iotkit_secctl_ppc_vmstate = {
    753    .name = "iotkit-secctl-ppc",
    754    .version_id = 1,
    755    .minimum_version_id = 1,
    756    .fields = (VMStateField[]) {
    757        VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
    758        VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
    759        VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
    760        VMSTATE_END_OF_LIST()
    761    }
    762};
    763
    764static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
    765    .name = "iotkit-secctl-mpcintstatus",
    766    .version_id = 1,
    767    .minimum_version_id = 1,
    768    .fields = (VMStateField[]) {
    769        VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
    770        VMSTATE_END_OF_LIST()
    771    }
    772};
    773
    774static bool needed_always(void *opaque)
    775{
    776    return true;
    777}
    778
    779static const VMStateDescription iotkit_secctl_msc_vmstate = {
    780    .name = "iotkit-secctl/msc",
    781    .version_id = 1,
    782    .minimum_version_id = 1,
    783    .needed = needed_always,
    784    .fields = (VMStateField[]) {
    785        VMSTATE_UINT32(secmscintstat, IoTKitSecCtl),
    786        VMSTATE_UINT32(secmscinten, IoTKitSecCtl),
    787        VMSTATE_UINT32(nsmscexp, IoTKitSecCtl),
    788        VMSTATE_END_OF_LIST()
    789    }
    790};
    791
    792static const VMStateDescription iotkit_secctl_vmstate = {
    793    .name = "iotkit-secctl",
    794    .version_id = 1,
    795    .minimum_version_id = 1,
    796    .fields = (VMStateField[]) {
    797        VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
    798        VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
    799        VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
    800        VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
    801        VMSTATE_UINT32(brginten, IoTKitSecCtl),
    802        VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
    803                             iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
    804        VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
    805                             iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
    806        VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
    807                             iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
    808        VMSTATE_END_OF_LIST()
    809    },
    810    .subsections = (const VMStateDescription*[]) {
    811        &iotkit_secctl_mpcintstatus_vmstate,
    812        &iotkit_secctl_msc_vmstate,
    813        NULL
    814    },
    815};
    816
    817static Property iotkit_secctl_props[] = {
    818    DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
    819    DEFINE_PROP_END_OF_LIST()
    820};
    821
    822static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
    823{
    824    DeviceClass *dc = DEVICE_CLASS(klass);
    825
    826    dc->vmsd = &iotkit_secctl_vmstate;
    827    dc->reset = iotkit_secctl_reset;
    828    dc->realize = iotkit_secctl_realize;
    829    device_class_set_props(dc, iotkit_secctl_props);
    830}
    831
    832static const TypeInfo iotkit_secctl_info = {
    833    .name = TYPE_IOTKIT_SECCTL,
    834    .parent = TYPE_SYS_BUS_DEVICE,
    835    .instance_size = sizeof(IoTKitSecCtl),
    836    .instance_init = iotkit_secctl_init,
    837    .class_init = iotkit_secctl_class_init,
    838};
    839
    840static void iotkit_secctl_register_types(void)
    841{
    842    type_register_static(&iotkit_secctl_info);
    843}
    844
    845type_init(iotkit_secctl_register_types);