blob: 6e22f2aad62ca3ff39408c7c34173271d6a64048 [file] [log] [blame]
Peter Maydellde343bb2018-03-02 10:45:39 +00001/*
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"
Markus Armbruster0b8fa322019-05-23 16:35:07 +020014#include "qemu/module.h"
Peter Maydellde343bb2018-03-02 10:45:39 +000015#include "qapi/error.h"
16#include "trace.h"
17#include "hw/sysbus.h"
Markus Armbrusterd6454272019-08-12 07:23:45 +020018#include "migration/vmstate.h"
Peter Maydellde343bb2018-03-02 10:45:39 +000019#include "hw/registerfields.h"
Markus Armbruster64552b62019-08-12 07:23:42 +020020#include "hw/irq.h"
Peter Maydellde343bb2018-03-02 10:45:39 +000021#include "hw/misc/iotkit-secctl.h"
Peter Maydell0eb6b0a2021-02-19 14:45:40 +000022#include "hw/arm/armsse-version.h"
23#include "hw/qdev-properties.h"
Peter Maydellde343bb2018-03-02 10:45:39 +000024
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
Peter Maydell0eb6b0a2021-02-19 14:45:40 +0000100static 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
Peter Maydellb3717c22018-03-02 10:45:39 +0000113/* 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
Daniel P. Berrangé7a21bee2022-07-07 17:37:15 +0100117 * into an index into a PPC array easily.
Peter Maydellb3717c22018-03-02 10:45:39 +0000118 */
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
Peter Maydellde343bb2018-03-02 10:45:39 +0000141static 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;
Peter Maydellb3717c22018-03-02 10:45:39 +0000147 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
Peter Maydellde343bb2018-03-02 10:45:39 +0000148
149 switch (offset) {
150 case A_AHBNSPPC0:
151 case A_AHBSPPPC0:
152 r = 0;
153 break;
154 case A_SECRESPCFG:
Peter Maydellb3717c22018-03-02 10:45:39 +0000155 r = s->secrespcfg;
156 break;
Peter Maydellb1ce38e2018-03-02 10:45:40 +0000157 case A_NSCCFG:
158 r = s->nsccfg;
159 break;
Peter Maydell3fd3cb22018-06-22 13:28:40 +0100160 case A_SECMPCINTSTATUS:
161 r = s->mpcintstatus;
162 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000163 case A_SECPPCINTSTAT:
Peter Maydellb3717c22018-03-02 10:45:39 +0000164 r = s->secppcintstat;
165 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000166 case A_SECPPCINTEN:
Peter Maydellb3717c22018-03-02 10:45:39 +0000167 r = s->secppcinten;
168 break;
Peter Maydellb1ce38e2018-03-02 10:45:40 +0000169 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;
Peter Maydellde343bb2018-03-02 10:45:39 +0000178 case A_AHBNSPPCEXP0:
179 case A_AHBNSPPCEXP1:
180 case A_AHBNSPPCEXP2:
181 case A_AHBNSPPCEXP3:
Peter Maydellb3717c22018-03-02 10:45:39 +0000182 r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
183 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000184 case A_APBNSPPC0:
185 case A_APBNSPPC1:
Peter Maydellb3717c22018-03-02 10:45:39 +0000186 r = s->apb[offset_to_ppc_idx(offset)].ns;
187 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000188 case A_APBNSPPCEXP0:
189 case A_APBNSPPCEXP1:
190 case A_APBNSPPCEXP2:
191 case A_APBNSPPCEXP3:
Peter Maydellb3717c22018-03-02 10:45:39 +0000192 r = s->apbexp[offset_to_ppc_idx(offset)].ns;
193 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000194 case A_AHBSPPPCEXP0:
195 case A_AHBSPPPCEXP1:
196 case A_AHBSPPPCEXP2:
197 case A_AHBSPPPCEXP3:
Peter Maydellb3717c22018-03-02 10:45:39 +0000198 r = s->apbexp[offset_to_ppc_idx(offset)].sp;
199 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000200 case A_APBSPPPC0:
201 case A_APBSPPPC1:
Peter Maydellb3717c22018-03-02 10:45:39 +0000202 r = s->apb[offset_to_ppc_idx(offset)].sp;
203 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000204 case A_APBSPPPCEXP0:
205 case A_APBSPPPCEXP1:
206 case A_APBSPPPCEXP2:
207 case A_APBSPPPCEXP3:
Peter Maydellb3717c22018-03-02 10:45:39 +0000208 r = s->apbexp[offset_to_ppc_idx(offset)].sp;
209 break;
Peter Maydellb3717c22018-03-02 10:45:39 +0000210 case A_SECMSCINTSTAT:
Peter Maydell81a75de2018-08-24 13:17:44 +0100211 r = s->secmscintstat;
212 break;
Peter Maydellb3717c22018-03-02 10:45:39 +0000213 case A_SECMSCINTEN:
Peter Maydell81a75de2018-08-24 13:17:44 +0100214 r = s->secmscinten;
215 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000216 case A_NSMSCEXP:
Peter Maydell81a75de2018-08-24 13:17:44 +0100217 r = s->nsmscexp;
Peter Maydellde343bb2018-03-02 10:45:39 +0000218 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:
Peter Maydell0eb6b0a2021-02-19 14:45:40 +0000231 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 }
Peter Maydellde343bb2018-03-02 10:45:39 +0000239 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
Peter Maydellb3717c22018-03-02 10:45:39 +0000267static 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
Peter Maydell81a75de2018-08-24 13:17:44 +0100320static 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
Peter Maydellde343bb2018-03-02 10:45:39 +0000337static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
338 uint64_t value,
339 unsigned size, MemTxAttrs attrs)
340{
Peter Maydellb3717c22018-03-02 10:45:39 +0000341 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
Peter Maydellde343bb2018-03-02 10:45:39 +0000342 uint32_t offset = addr;
Peter Maydellb3717c22018-03-02 10:45:39 +0000343 IoTKitSecCtlPPC *ppc;
Peter Maydellde343bb2018-03-02 10:45:39 +0000344
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) {
Peter Maydellb1ce38e2018-03-02 10:45:40 +0000355 case A_NSCCFG:
356 s->nsccfg = value & 3;
357 qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
358 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000359 case A_SECRESPCFG:
Peter Maydellb3717c22018-03-02 10:45:39 +0000360 value &= 1;
361 s->secrespcfg = value;
362 qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
363 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000364 case A_SECPPCINTCLR:
Philippe Mathieu-Daudé9df74012020-02-17 14:29:22 +0100365 s->secppcintstat &= ~(value & 0x00f000f3);
Peter Maydellb3717c22018-03-02 10:45:39 +0000366 foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
367 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000368 case A_SECPPCINTEN:
Peter Maydellb3717c22018-03-02 10:45:39 +0000369 s->secppcinten = value & 0x00f000f3;
370 foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
371 break;
Peter Maydellb1ce38e2018-03-02 10:45:40 +0000372 case A_BRGINTCLR:
373 break;
374 case A_BRGINTEN:
375 s->brginten = value & 0xffff0000;
376 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000377 case A_AHBNSPPCEXP0:
378 case A_AHBNSPPCEXP1:
379 case A_AHBNSPPCEXP2:
380 case A_AHBNSPPCEXP3:
Peter Maydellb3717c22018-03-02 10:45:39 +0000381 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
382 iotkit_secctl_ppc_ns_write(ppc, value);
383 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000384 case A_APBNSPPC0:
385 case A_APBNSPPC1:
Peter Maydellb3717c22018-03-02 10:45:39 +0000386 ppc = &s->apb[offset_to_ppc_idx(offset)];
387 iotkit_secctl_ppc_ns_write(ppc, value);
388 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000389 case A_APBNSPPCEXP0:
390 case A_APBNSPPCEXP1:
391 case A_APBNSPPCEXP2:
392 case A_APBNSPPCEXP3:
Peter Maydellb3717c22018-03-02 10:45:39 +0000393 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
394 iotkit_secctl_ppc_ns_write(ppc, value);
395 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000396 case A_AHBSPPPCEXP0:
397 case A_AHBSPPPCEXP1:
398 case A_AHBSPPPCEXP2:
399 case A_AHBSPPPCEXP3:
Peter Maydellb3717c22018-03-02 10:45:39 +0000400 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
401 iotkit_secctl_ppc_sp_write(ppc, value);
402 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000403 case A_APBSPPPC0:
404 case A_APBSPPPC1:
Peter Maydellb3717c22018-03-02 10:45:39 +0000405 ppc = &s->apb[offset_to_ppc_idx(offset)];
406 iotkit_secctl_ppc_sp_write(ppc, value);
407 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000408 case A_APBSPPPCEXP0:
409 case A_APBSPPPCEXP1:
410 case A_APBSPPPCEXP2:
411 case A_APBSPPPCEXP3:
Peter Maydellb3717c22018-03-02 10:45:39 +0000412 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
413 iotkit_secctl_ppc_sp_write(ppc, value);
414 break;
Peter Maydellb3717c22018-03-02 10:45:39 +0000415 case A_SECMSCINTCLR:
Peter Maydell81a75de2018-08-24 13:17:44 +0100416 iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value);
417 break;
Peter Maydellb3717c22018-03-02 10:45:39 +0000418 case A_SECMSCINTEN:
Peter Maydell81a75de2018-08-24 13:17:44 +0100419 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);
Peter Maydellde343bb2018-03-02 10:45:39 +0000425 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:
Peter Maydellde343bb2018-03-02 10:45:39 +0000432 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{
Peter Maydellb3717c22018-03-02 10:45:39 +0000462 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
Peter Maydellde343bb2018-03-02 10:45:39 +0000463 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:
Peter Maydellb3717c22018-03-02 10:45:39 +0000474 r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
475 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000476 case A_APBNSPPPC0:
477 case A_APBNSPPPC1:
Peter Maydellb3717c22018-03-02 10:45:39 +0000478 r = s->apb[offset_to_ppc_idx(offset)].nsp;
479 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000480 case A_APBNSPPPCEXP0:
481 case A_APBNSPPPCEXP1:
482 case A_APBNSPPPCEXP2:
483 case A_APBNSPPPCEXP3:
Peter Maydellb3717c22018-03-02 10:45:39 +0000484 r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
Peter Maydellde343bb2018-03-02 10:45:39 +0000485 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:
Peter Maydell0eb6b0a2021-02-19 14:45:40 +0000498 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 }
Peter Maydellde343bb2018-03-02 10:45:39 +0000506 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{
Peter Maydellb3717c22018-03-02 10:45:39 +0000531 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
Peter Maydellde343bb2018-03-02 10:45:39 +0000532 uint32_t offset = addr;
Peter Maydellb3717c22018-03-02 10:45:39 +0000533 IoTKitSecCtlPPC *ppc;
Peter Maydellde343bb2018-03-02 10:45:39 +0000534
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:
Peter Maydellb3717c22018-03-02 10:45:39 +0000549 ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
550 iotkit_secctl_ppc_nsp_write(ppc, value);
551 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000552 case A_APBNSPPPC0:
553 case A_APBNSPPPC1:
Peter Maydellb3717c22018-03-02 10:45:39 +0000554 ppc = &s->apb[offset_to_ppc_idx(offset)];
555 iotkit_secctl_ppc_nsp_write(ppc, value);
556 break;
Peter Maydellde343bb2018-03-02 10:45:39 +0000557 case A_APBNSPPPCEXP0:
558 case A_APBNSPPPCEXP1:
559 case A_APBNSPPPCEXP2:
560 case A_APBNSPPPCEXP3:
Peter Maydellb3717c22018-03-02 10:45:39 +0000561 ppc = &s->apbexp[offset_to_ppc_idx(offset)];
562 iotkit_secctl_ppc_nsp_write(ppc, value);
Peter Maydellde343bb2018-03-02 10:45:39 +0000563 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
Peter Maydellb3717c22018-03-02 10:45:39 +0000611static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
612{
613 ppc->ns = 0;
614 ppc->sp = 0;
615 ppc->nsp = 0;
616}
617
Peter Maydellde343bb2018-03-02 10:45:39 +0000618static void iotkit_secctl_reset(DeviceState *dev)
619{
Peter Maydellb3717c22018-03-02 10:45:39 +0000620 IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
Peter Maydellde343bb2018-03-02 10:45:39 +0000621
Peter Maydellb3717c22018-03-02 10:45:39 +0000622 s->secppcintstat = 0;
623 s->secppcinten = 0;
624 s->secrespcfg = 0;
Peter Maydellb1ce38e2018-03-02 10:45:40 +0000625 s->nsccfg = 0;
626 s->brginten = 0;
Peter Maydellb3717c22018-03-02 10:45:39 +0000627
628 foreach_ppc(s, iotkit_secctl_reset_ppc);
629}
630
Peter Maydell3fd3cb22018-06-22 13:28:40 +0100631static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
632{
633 IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
634
Peter Maydell0a78d7e2019-02-01 14:55:42 +0000635 s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
Peter Maydell3fd3cb22018-06-22 13:28:40 +0100636}
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
Peter Maydell81a75de2018-08-24 13:17:44 +0100645static 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
Peter Maydellb3717c22018-03-02 10:45:39 +0000653static 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);
Peter Maydellde343bb2018-03-02 10:45:39 +0000691}
692
693static void iotkit_secctl_init(Object *obj)
694{
695 IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
696 SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
Peter Maydellb3717c22018-03-02 10:45:39 +0000697 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);
Peter Maydellb1ce38e2018-03-02 10:45:40 +0000719 qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
Peter Maydellde343bb2018-03-02 10:45:39 +0000720
Peter Maydell0a78d7e2019-02-01 14:55:42 +0000721 qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
722 IOTS_NUM_MPC);
Peter Maydell3fd3cb22018-06-22 13:28:40 +0100723 qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
724 "mpcexp_status", IOTS_NUM_EXP_MPC);
725
Peter Maydell81a75de2018-08-24 13:17:44 +0100726 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
Peter Maydellde343bb2018-03-02 10:45:39 +0000734 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
Peter Maydell0eb6b0a2021-02-19 14:45:40 +0000742static 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
Peter Maydellb3717c22018-03-02 10:45:39 +0000752static const VMStateDescription iotkit_secctl_ppc_vmstate = {
753 .name = "iotkit-secctl-ppc",
754 .version_id = 1,
755 .minimum_version_id = 1,
Richard Hendersone4ea9522023-12-21 14:16:21 +1100756 .fields = (const VMStateField[]) {
Peter Maydellb3717c22018-03-02 10:45:39 +0000757 VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
758 VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
759 VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
760 VMSTATE_END_OF_LIST()
761 }
762};
763
Peter Maydell3fd3cb22018-06-22 13:28:40 +0100764static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
765 .name = "iotkit-secctl-mpcintstatus",
766 .version_id = 1,
767 .minimum_version_id = 1,
Richard Hendersone4ea9522023-12-21 14:16:21 +1100768 .fields = (const VMStateField[]) {
Peter Maydell3fd3cb22018-06-22 13:28:40 +0100769 VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
770 VMSTATE_END_OF_LIST()
771 }
772};
773
Peter Maydell81a75de2018-08-24 13:17:44 +0100774static 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,
Richard Hendersone4ea9522023-12-21 14:16:21 +1100784 .fields = (const VMStateField[]) {
Peter Maydell81a75de2018-08-24 13:17:44 +0100785 VMSTATE_UINT32(secmscintstat, IoTKitSecCtl),
786 VMSTATE_UINT32(secmscinten, IoTKitSecCtl),
787 VMSTATE_UINT32(nsmscexp, IoTKitSecCtl),
788 VMSTATE_END_OF_LIST()
789 }
790};
791
Peter Maydellde343bb2018-03-02 10:45:39 +0000792static const VMStateDescription iotkit_secctl_vmstate = {
793 .name = "iotkit-secctl",
794 .version_id = 1,
795 .minimum_version_id = 1,
Richard Hendersone4ea9522023-12-21 14:16:21 +1100796 .fields = (const VMStateField[]) {
Peter Maydellb3717c22018-03-02 10:45:39 +0000797 VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
798 VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
799 VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
Peter Maydellb1ce38e2018-03-02 10:45:40 +0000800 VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
801 VMSTATE_UINT32(brginten, IoTKitSecCtl),
Peter Maydellb3717c22018-03-02 10:45:39 +0000802 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),
Peter Maydellde343bb2018-03-02 10:45:39 +0000808 VMSTATE_END_OF_LIST()
Peter Maydell3fd3cb22018-06-22 13:28:40 +0100809 },
Richard Hendersone4ea9522023-12-21 14:16:21 +1100810 .subsections = (const VMStateDescription * const []) {
Peter Maydell3fd3cb22018-06-22 13:28:40 +0100811 &iotkit_secctl_mpcintstatus_vmstate,
Peter Maydell81a75de2018-08-24 13:17:44 +0100812 &iotkit_secctl_msc_vmstate,
Peter Maydell3fd3cb22018-06-22 13:28:40 +0100813 NULL
814 },
Peter Maydellde343bb2018-03-02 10:45:39 +0000815};
816
Peter Maydell0eb6b0a2021-02-19 14:45:40 +0000817static Property iotkit_secctl_props[] = {
818 DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
819 DEFINE_PROP_END_OF_LIST()
820};
821
Peter Maydellde343bb2018-03-02 10:45:39 +0000822static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
823{
824 DeviceClass *dc = DEVICE_CLASS(klass);
825
826 dc->vmsd = &iotkit_secctl_vmstate;
Peter Maydelle3d08142024-09-13 15:31:44 +0100827 device_class_set_legacy_reset(dc, iotkit_secctl_reset);
Peter Maydell0eb6b0a2021-02-19 14:45:40 +0000828 dc->realize = iotkit_secctl_realize;
829 device_class_set_props(dc, iotkit_secctl_props);
Peter Maydellde343bb2018-03-02 10:45:39 +0000830}
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);