qemu

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

iotkit-secctl.c (24131B)


      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 */
     26 REG32(SECRESPCFG, 0x10)
     27 REG32(NSCCFG, 0x14)
     28 REG32(SECMPCINTSTATUS, 0x1c)
     29 REG32(SECPPCINTSTAT, 0x20)
     30 REG32(SECPPCINTCLR, 0x24)
     31 REG32(SECPPCINTEN, 0x28)
     32 REG32(SECMSCINTSTAT, 0x30)
     33 REG32(SECMSCINTCLR, 0x34)
     34 REG32(SECMSCINTEN, 0x38)
     35 REG32(BRGINTSTAT, 0x40)
     36 REG32(BRGINTCLR, 0x44)
     37 REG32(BRGINTEN, 0x48)
     38 REG32(AHBNSPPC0, 0x50)
     39 REG32(AHBNSPPCEXP0, 0x60)
     40 REG32(AHBNSPPCEXP1, 0x64)
     41 REG32(AHBNSPPCEXP2, 0x68)
     42 REG32(AHBNSPPCEXP3, 0x6c)
     43 REG32(APBNSPPC0, 0x70)
     44 REG32(APBNSPPC1, 0x74)
     45 REG32(APBNSPPCEXP0, 0x80)
     46 REG32(APBNSPPCEXP1, 0x84)
     47 REG32(APBNSPPCEXP2, 0x88)
     48 REG32(APBNSPPCEXP3, 0x8c)
     49 REG32(AHBSPPPC0, 0x90)
     50 REG32(AHBSPPPCEXP0, 0xa0)
     51 REG32(AHBSPPPCEXP1, 0xa4)
     52 REG32(AHBSPPPCEXP2, 0xa8)
     53 REG32(AHBSPPPCEXP3, 0xac)
     54 REG32(APBSPPPC0, 0xb0)
     55 REG32(APBSPPPC1, 0xb4)
     56 REG32(APBSPPPCEXP0, 0xc0)
     57 REG32(APBSPPPCEXP1, 0xc4)
     58 REG32(APBSPPPCEXP2, 0xc8)
     59 REG32(APBSPPPCEXP3, 0xcc)
     60 REG32(NSMSCEXP, 0xd0)
     61 REG32(PID4, 0xfd0)
     62 REG32(PID5, 0xfd4)
     63 REG32(PID6, 0xfd8)
     64 REG32(PID7, 0xfdc)
     65 REG32(PID0, 0xfe0)
     66 REG32(PID1, 0xfe4)
     67 REG32(PID2, 0xfe8)
     68 REG32(PID3, 0xfec)
     69 REG32(CID0, 0xff0)
     70 REG32(CID1, 0xff4)
     71 REG32(CID2, 0xff8)
     72 REG32(CID3, 0xffc)
     73 
     74 /* Registers in the non-secure privilege control block */
     75 REG32(AHBNSPPPC0, 0x90)
     76 REG32(AHBNSPPPCEXP0, 0xa0)
     77 REG32(AHBNSPPPCEXP1, 0xa4)
     78 REG32(AHBNSPPPCEXP2, 0xa8)
     79 REG32(AHBNSPPPCEXP3, 0xac)
     80 REG32(APBNSPPPC0, 0xb0)
     81 REG32(APBNSPPPC1, 0xb4)
     82 REG32(APBNSPPPCEXP0, 0xc0)
     83 REG32(APBNSPPPCEXP1, 0xc4)
     84 REG32(APBNSPPPCEXP2, 0xc8)
     85 REG32(APBNSPPPCEXP3, 0xcc)
     86 /* PID and CID registers are also present in the NS block */
     87 
     88 static const uint8_t iotkit_secctl_s_idregs[] = {
     89     0x04, 0x00, 0x00, 0x00,
     90     0x52, 0xb8, 0x0b, 0x00,
     91     0x0d, 0xf0, 0x05, 0xb1,
     92 };
     93 
     94 static const uint8_t iotkit_secctl_ns_idregs[] = {
     95     0x04, 0x00, 0x00, 0x00,
     96     0x53, 0xb8, 0x0b, 0x00,
     97     0x0d, 0xf0, 0x05, 0xb1,
     98 };
     99 
    100 static 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 
    106 static 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 index into a PPC array easily.
    118  */
    119 static inline int offset_to_ppc_idx(uint32_t offset)
    120 {
    121     return extract32(offset, 2, 2);
    122 }
    123 
    124 typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
    125 
    126 static 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 
    141 static 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 
    267 static 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 
    283 static 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 
    294 static 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 
    300 static 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 
    306 static 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 
    313 static 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 
    320 static 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 
    329 static 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 
    337 static 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 
    458 static 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 
    527 static 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 
    591 static 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 
    601 static 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 
    611 static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
    612 {
    613     ppc->ns = 0;
    614     ppc->sp = 0;
    615     ppc->nsp = 0;
    616 }
    617 
    618 static 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 
    631 static 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 
    638 static 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 
    645 static 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 
    653 static 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 
    662 static 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 
    693 static 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 
    742 static 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 
    752 static 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 
    764 static 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 
    774 static bool needed_always(void *opaque)
    775 {
    776     return true;
    777 }
    778 
    779 static 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 
    792 static 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 
    817 static Property iotkit_secctl_props[] = {
    818     DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
    819     DEFINE_PROP_END_OF_LIST()
    820 };
    821 
    822 static 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 
    832 static 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 
    840 static void iotkit_secctl_register_types(void)
    841 {
    842     type_register_static(&iotkit_secctl_info);
    843 }
    844 
    845 type_init(iotkit_secctl_register_types);