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