2 * Arm IoT Kit security controller
4 * Copyright (c) 2018 Linaro Limited
5 * Written by Peter Maydell
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.
12 #include "qemu/osdep.h"
14 #include "qapi/error.h"
16 #include "hw/sysbus.h"
17 #include "hw/registerfields.h"
18 #include "hw/misc/iotkit-secctl.h"
20 /* Registers in the secure privilege control block */
21 REG32(SECRESPCFG, 0x10)
23 REG32(SECMPCINTSTATUS, 0x1c)
24 REG32(SECPPCINTSTAT, 0x20)
25 REG32(SECPPCINTCLR, 0x24)
26 REG32(SECPPCINTEN, 0x28)
27 REG32(SECMSCINTSTAT, 0x30)
28 REG32(SECMSCINTCLR, 0x34)
29 REG32(SECMSCINTEN, 0x38)
30 REG32(BRGINTSTAT, 0x40)
31 REG32(BRGINTCLR, 0x44)
33 REG32(AHBNSPPC0, 0x50)
34 REG32(AHBNSPPCEXP0, 0x60)
35 REG32(AHBNSPPCEXP1, 0x64)
36 REG32(AHBNSPPCEXP2, 0x68)
37 REG32(AHBNSPPCEXP3, 0x6c)
38 REG32(APBNSPPC0, 0x70)
39 REG32(APBNSPPC1, 0x74)
40 REG32(APBNSPPCEXP0, 0x80)
41 REG32(APBNSPPCEXP1, 0x84)
42 REG32(APBNSPPCEXP2, 0x88)
43 REG32(APBNSPPCEXP3, 0x8c)
44 REG32(AHBSPPPC0, 0x90)
45 REG32(AHBSPPPCEXP0, 0xa0)
46 REG32(AHBSPPPCEXP1, 0xa4)
47 REG32(AHBSPPPCEXP2, 0xa8)
48 REG32(AHBSPPPCEXP3, 0xac)
49 REG32(APBSPPPC0, 0xb0)
50 REG32(APBSPPPC1, 0xb4)
51 REG32(APBSPPPCEXP0, 0xc0)
52 REG32(APBSPPPCEXP1, 0xc4)
53 REG32(APBSPPPCEXP2, 0xc8)
54 REG32(APBSPPPCEXP3, 0xcc)
69 /* Registers in the non-secure privilege control block */
70 REG32(AHBNSPPPC0, 0x90)
71 REG32(AHBNSPPPCEXP0, 0xa0)
72 REG32(AHBNSPPPCEXP1, 0xa4)
73 REG32(AHBNSPPPCEXP2, 0xa8)
74 REG32(AHBNSPPPCEXP3, 0xac)
75 REG32(APBNSPPPC0, 0xb0)
76 REG32(APBNSPPPC1, 0xb4)
77 REG32(APBNSPPPCEXP0, 0xc0)
78 REG32(APBNSPPPCEXP1, 0xc4)
79 REG32(APBNSPPPCEXP2, 0xc8)
80 REG32(APBNSPPPCEXP3, 0xcc)
81 /* PID and CID registers are also present in the NS block */
83 static const uint8_t iotkit_secctl_s_idregs[] = {
84 0x04, 0x00, 0x00, 0x00,
85 0x52, 0xb8, 0x0b, 0x00,
86 0x0d, 0xf0, 0x05, 0xb1,
89 static const uint8_t iotkit_secctl_ns_idregs[] = {
90 0x04, 0x00, 0x00, 0x00,
91 0x53, 0xb8, 0x0b, 0x00,
92 0x0d, 0xf0, 0x05, 0xb1,
95 /* The register sets for the various PPCs (AHB internal, APB internal,
96 * AHB expansion, APB expansion) are all set up so that they are
97 * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
98 * 0, 1, 2, 3 of that type, so we can convert a register address offset
99 * into an an index into a PPC array easily.
101 static inline int offset_to_ppc_idx(uint32_t offset)
103 return extract32(offset, 2, 2);
106 typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
108 static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
112 for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
115 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
118 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
123 static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
125 unsigned size, MemTxAttrs attrs)
128 uint32_t offset = addr & ~0x3;
129 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
142 case A_SECMPCINTSTATUS:
145 case A_SECPPCINTSTAT:
146 r = s->secppcintstat;
152 /* QEMU's bus fabric can never report errors as it doesn't buffer
153 * writes, so we never report bridge interrupts.
164 r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
168 r = s->apb[offset_to_ppc_idx(offset)].ns;
174 r = s->apbexp[offset_to_ppc_idx(offset)].ns;
180 r = s->apbexp[offset_to_ppc_idx(offset)].sp;
184 r = s->apb[offset_to_ppc_idx(offset)].sp;
190 r = s->apbexp[offset_to_ppc_idx(offset)].sp;
192 case A_SECMSCINTSTAT:
193 r = s->secmscintstat;
213 r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
218 qemu_log_mask(LOG_GUEST_ERROR,
219 "IotKit SecCtl S block read: write-only offset 0x%x\n",
224 qemu_log_mask(LOG_GUEST_ERROR,
225 "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
231 /* None of our registers are access-sensitive, so just pull the right
232 * byte out of the word read result.
234 r = extract32(r, (addr & 3) * 8, size * 8);
237 trace_iotkit_secctl_s_read(offset, r, size);
242 static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
246 for (i = 0; i < ppc->numports; i++) {
249 if (extract32(ppc->ns, i, 1)) {
250 v = extract32(ppc->nsp, i, 1);
252 v = extract32(ppc->sp, i, 1);
254 qemu_set_irq(ppc->ap[i], v);
258 static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
262 ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
263 for (i = 0; i < ppc->numports; i++) {
264 qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
266 iotkit_secctl_update_ppc_ap(ppc);
269 static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
271 ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
272 iotkit_secctl_update_ppc_ap(ppc);
275 static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
277 ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
278 iotkit_secctl_update_ppc_ap(ppc);
281 static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
283 uint32_t value = ppc->parent->secppcintstat;
285 qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
288 static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
290 uint32_t value = ppc->parent->secppcinten;
292 qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
295 static void iotkit_secctl_update_mscexp_irqs(qemu_irq *msc_irqs, uint32_t value)
299 for (i = 0; i < IOTS_NUM_EXP_MSC; i++) {
300 qemu_set_irq(msc_irqs[i], extract32(value, i + 16, 1));
304 static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s)
306 /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_EN */
307 bool level = s->secmscintstat & s->secmscinten;
309 qemu_set_irq(s->msc_irq, level);
312 static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
314 unsigned size, MemTxAttrs attrs)
316 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
317 uint32_t offset = addr;
318 IoTKitSecCtlPPC *ppc;
320 trace_iotkit_secctl_s_write(offset, value, size);
323 /* Byte and halfword writes are ignored */
324 qemu_log_mask(LOG_GUEST_ERROR,
325 "IotKit SecCtl S block write: bad size, ignored\n");
331 s->nsccfg = value & 3;
332 qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
336 s->secrespcfg = value;
337 qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
341 foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
344 s->secppcinten = value & 0x00f000f3;
345 foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
350 s->brginten = value & 0xffff0000;
356 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
357 iotkit_secctl_ppc_ns_write(ppc, value);
361 ppc = &s->apb[offset_to_ppc_idx(offset)];
362 iotkit_secctl_ppc_ns_write(ppc, value);
368 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
369 iotkit_secctl_ppc_ns_write(ppc, value);
375 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
376 iotkit_secctl_ppc_sp_write(ppc, value);
380 ppc = &s->apb[offset_to_ppc_idx(offset)];
381 iotkit_secctl_ppc_sp_write(ppc, value);
387 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
388 iotkit_secctl_ppc_sp_write(ppc, value);
391 iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value);
394 s->secmscinten = value;
395 iotkit_secctl_update_msc_irq(s);
399 iotkit_secctl_update_mscexp_irqs(s->mscexp_ns, value);
401 case A_SECMPCINTSTATUS:
402 case A_SECPPCINTSTAT:
403 case A_SECMSCINTSTAT:
419 qemu_log_mask(LOG_GUEST_ERROR,
420 "IoTKit SecCtl S block write: "
421 "read-only offset 0x%x\n", offset);
424 qemu_log_mask(LOG_GUEST_ERROR,
425 "IotKit SecCtl S block write: bad offset 0x%x\n",
433 static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
435 unsigned size, MemTxAttrs attrs)
437 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
439 uint32_t offset = addr & ~0x3;
445 case A_AHBNSPPPCEXP0:
446 case A_AHBNSPPPCEXP1:
447 case A_AHBNSPPPCEXP2:
448 case A_AHBNSPPPCEXP3:
449 r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
453 r = s->apb[offset_to_ppc_idx(offset)].nsp;
455 case A_APBNSPPPCEXP0:
456 case A_APBNSPPPCEXP1:
457 case A_APBNSPPPCEXP2:
458 case A_APBNSPPPCEXP3:
459 r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
473 r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
476 qemu_log_mask(LOG_GUEST_ERROR,
477 "IotKit SecCtl NS block write: bad offset 0x%x\n",
484 /* None of our registers are access-sensitive, so just pull the right
485 * byte out of the word read result.
487 r = extract32(r, (addr & 3) * 8, size * 8);
490 trace_iotkit_secctl_ns_read(offset, r, size);
495 static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
497 unsigned size, MemTxAttrs attrs)
499 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
500 uint32_t offset = addr;
501 IoTKitSecCtlPPC *ppc;
503 trace_iotkit_secctl_ns_write(offset, value, size);
506 /* Byte and halfword writes are ignored */
507 qemu_log_mask(LOG_GUEST_ERROR,
508 "IotKit SecCtl NS block write: bad size, ignored\n");
513 case A_AHBNSPPPCEXP0:
514 case A_AHBNSPPPCEXP1:
515 case A_AHBNSPPPCEXP2:
516 case A_AHBNSPPPCEXP3:
517 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
518 iotkit_secctl_ppc_nsp_write(ppc, value);
522 ppc = &s->apb[offset_to_ppc_idx(offset)];
523 iotkit_secctl_ppc_nsp_write(ppc, value);
525 case A_APBNSPPPCEXP0:
526 case A_APBNSPPPCEXP1:
527 case A_APBNSPPPCEXP2:
528 case A_APBNSPPPCEXP3:
529 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
530 iotkit_secctl_ppc_nsp_write(ppc, value);
545 qemu_log_mask(LOG_GUEST_ERROR,
546 "IoTKit SecCtl NS block write: "
547 "read-only offset 0x%x\n", offset);
550 qemu_log_mask(LOG_GUEST_ERROR,
551 "IotKit SecCtl NS block write: bad offset 0x%x\n",
559 static const MemoryRegionOps iotkit_secctl_s_ops = {
560 .read_with_attrs = iotkit_secctl_s_read,
561 .write_with_attrs = iotkit_secctl_s_write,
562 .endianness = DEVICE_LITTLE_ENDIAN,
563 .valid.min_access_size = 1,
564 .valid.max_access_size = 4,
565 .impl.min_access_size = 1,
566 .impl.max_access_size = 4,
569 static const MemoryRegionOps iotkit_secctl_ns_ops = {
570 .read_with_attrs = iotkit_secctl_ns_read,
571 .write_with_attrs = iotkit_secctl_ns_write,
572 .endianness = DEVICE_LITTLE_ENDIAN,
573 .valid.min_access_size = 1,
574 .valid.max_access_size = 4,
575 .impl.min_access_size = 1,
576 .impl.max_access_size = 4,
579 static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
586 static void iotkit_secctl_reset(DeviceState *dev)
588 IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
590 s->secppcintstat = 0;
596 foreach_ppc(s, iotkit_secctl_reset_ppc);
599 static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
601 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
603 s->mpcintstatus = deposit32(s->mpcintstatus, 0, 1, !!level);
606 static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
608 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
610 s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
613 static void iotkit_secctl_mscexp_status(void *opaque, int n, int level)
615 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
617 s->secmscintstat = deposit32(s->secmscintstat, n + 16, 1, !!level);
618 iotkit_secctl_update_msc_irq(s);
621 static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
623 IoTKitSecCtlPPC *ppc = opaque;
624 IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
625 int irqbit = ppc->irq_bit_offset + n;
627 s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
630 static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
631 IoTKitSecCtlPPC *ppc,
637 DeviceState *dev = DEVICE(s);
639 ppc->numports = numports;
640 ppc->irq_bit_offset = irq_bit_offset;
643 gpioname = g_strdup_printf("%s_nonsec", name);
644 qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
646 gpioname = g_strdup_printf("%s_ap", name);
647 qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
649 gpioname = g_strdup_printf("%s_irq_enable", name);
650 qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
652 gpioname = g_strdup_printf("%s_irq_clear", name);
653 qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
655 gpioname = g_strdup_printf("%s_irq_status", name);
656 qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
661 static void iotkit_secctl_init(Object *obj)
663 IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
664 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
665 DeviceState *dev = DEVICE(obj);
668 iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
669 IOTS_APB_PPC0_NUM_PORTS, 0);
670 iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
671 IOTS_APB_PPC1_NUM_PORTS, 1);
673 for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
674 IoTKitSecCtlPPC *ppc = &s->apbexp[i];
675 char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
676 iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
679 for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
680 IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
681 char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
682 iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
686 qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
687 qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
689 qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status", 1);
690 qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
691 "mpcexp_status", IOTS_NUM_EXP_MPC);
693 qdev_init_gpio_in_named(dev, iotkit_secctl_mscexp_status,
694 "mscexp_status", IOTS_NUM_EXP_MSC);
695 qdev_init_gpio_out_named(dev, s->mscexp_clear, "mscexp_clear",
697 qdev_init_gpio_out_named(dev, s->mscexp_ns, "mscexp_ns",
699 qdev_init_gpio_out_named(dev, &s->msc_irq, "msc_irq", 1);
701 memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
702 s, "iotkit-secctl-s-regs", 0x1000);
703 memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
704 s, "iotkit-secctl-ns-regs", 0x1000);
705 sysbus_init_mmio(sbd, &s->s_regs);
706 sysbus_init_mmio(sbd, &s->ns_regs);
709 static const VMStateDescription iotkit_secctl_ppc_vmstate = {
710 .name = "iotkit-secctl-ppc",
712 .minimum_version_id = 1,
713 .fields = (VMStateField[]) {
714 VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
715 VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
716 VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
717 VMSTATE_END_OF_LIST()
721 static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
722 .name = "iotkit-secctl-mpcintstatus",
724 .minimum_version_id = 1,
725 .fields = (VMStateField[]) {
726 VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
727 VMSTATE_END_OF_LIST()
731 static bool needed_always(void *opaque)
736 static const VMStateDescription iotkit_secctl_msc_vmstate = {
737 .name = "iotkit-secctl/msc",
739 .minimum_version_id = 1,
740 .needed = needed_always,
741 .fields = (VMStateField[]) {
742 VMSTATE_UINT32(secmscintstat, IoTKitSecCtl),
743 VMSTATE_UINT32(secmscinten, IoTKitSecCtl),
744 VMSTATE_UINT32(nsmscexp, IoTKitSecCtl),
745 VMSTATE_END_OF_LIST()
749 static const VMStateDescription iotkit_secctl_vmstate = {
750 .name = "iotkit-secctl",
752 .minimum_version_id = 1,
753 .fields = (VMStateField[]) {
754 VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
755 VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
756 VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
757 VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
758 VMSTATE_UINT32(brginten, IoTKitSecCtl),
759 VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
760 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
761 VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
762 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
763 VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
764 iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
765 VMSTATE_END_OF_LIST()
767 .subsections = (const VMStateDescription*[]) {
768 &iotkit_secctl_mpcintstatus_vmstate,
769 &iotkit_secctl_msc_vmstate,
774 static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
776 DeviceClass *dc = DEVICE_CLASS(klass);
778 dc->vmsd = &iotkit_secctl_vmstate;
779 dc->reset = iotkit_secctl_reset;
782 static const TypeInfo iotkit_secctl_info = {
783 .name = TYPE_IOTKIT_SECCTL,
784 .parent = TYPE_SYS_BUS_DEVICE,
785 .instance_size = sizeof(IoTKitSecCtl),
786 .instance_init = iotkit_secctl_init,
787 .class_init = iotkit_secctl_class_init,
790 static void iotkit_secctl_register_types(void)
792 type_register_static(&iotkit_secctl_info);
795 type_init(iotkit_secctl_register_types);