1
2
3
4
5
6
7
8
9
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/tz-mpc.h"
22#include "hw/qdev-properties.h"
23
24
25
26
27enum {
28 IOMMU_IDX_S,
29 IOMMU_IDX_NS,
30 IOMMU_NUM_INDEXES,
31};
32
33
34REG32(CTRL, 0x00)
35 FIELD(CTRL, SEC_RESP, 4, 1)
36 FIELD(CTRL, AUTOINC, 8, 1)
37 FIELD(CTRL, LOCKDOWN, 31, 1)
38REG32(BLK_MAX, 0x10)
39REG32(BLK_CFG, 0x14)
40REG32(BLK_IDX, 0x18)
41REG32(BLK_LUT, 0x1c)
42REG32(INT_STAT, 0x20)
43 FIELD(INT_STAT, IRQ, 0, 1)
44REG32(INT_CLEAR, 0x24)
45 FIELD(INT_CLEAR, IRQ, 0, 1)
46REG32(INT_EN, 0x28)
47 FIELD(INT_EN, IRQ, 0, 1)
48REG32(INT_INFO1, 0x2c)
49REG32(INT_INFO2, 0x30)
50 FIELD(INT_INFO2, HMASTER, 0, 16)
51 FIELD(INT_INFO2, HNONSEC, 16, 1)
52 FIELD(INT_INFO2, CFG_NS, 17, 1)
53REG32(INT_SET, 0x34)
54 FIELD(INT_SET, IRQ, 0, 1)
55REG32(PIDR4, 0xfd0)
56REG32(PIDR5, 0xfd4)
57REG32(PIDR6, 0xfd8)
58REG32(PIDR7, 0xfdc)
59REG32(PIDR0, 0xfe0)
60REG32(PIDR1, 0xfe4)
61REG32(PIDR2, 0xfe8)
62REG32(PIDR3, 0xfec)
63REG32(CIDR0, 0xff0)
64REG32(CIDR1, 0xff4)
65REG32(CIDR2, 0xff8)
66REG32(CIDR3, 0xffc)
67
68static const uint8_t tz_mpc_idregs[] = {
69 0x04, 0x00, 0x00, 0x00,
70 0x60, 0xb8, 0x1b, 0x00,
71 0x0d, 0xf0, 0x05, 0xb1,
72};
73
74static void tz_mpc_irq_update(TZMPC *s)
75{
76 qemu_set_irq(s->irq, s->int_stat && s->int_en);
77}
78
79static void tz_mpc_iommu_notify(TZMPC *s, uint32_t lutidx,
80 uint32_t oldlut, uint32_t newlut)
81{
82
83
84
85 IOMMUTLBEvent event = {
86 .entry = {
87 .addr_mask = s->blocksize - 1,
88 }
89 };
90 hwaddr addr = lutidx * s->blocksize * 32;
91 int i;
92
93 for (i = 0; i < 32; i++, addr += s->blocksize) {
94 bool block_is_ns;
95
96 if (!((oldlut ^ newlut) & (1 << i))) {
97 continue;
98 }
99
100
101
102 block_is_ns = newlut & (1 << i);
103
104 trace_tz_mpc_iommu_notify(addr);
105 event.entry.iova = addr;
106 event.entry.translated_addr = addr;
107
108 event.type = IOMMU_NOTIFIER_UNMAP;
109 event.entry.perm = IOMMU_NONE;
110 memory_region_notify_iommu(&s->upstream, IOMMU_IDX_S, event);
111 memory_region_notify_iommu(&s->upstream, IOMMU_IDX_NS, event);
112
113 event.type = IOMMU_NOTIFIER_MAP;
114 event.entry.perm = IOMMU_RW;
115 if (block_is_ns) {
116 event.entry.target_as = &s->blocked_io_as;
117 } else {
118 event.entry.target_as = &s->downstream_as;
119 }
120 memory_region_notify_iommu(&s->upstream, IOMMU_IDX_S, event);
121 if (block_is_ns) {
122 event.entry.target_as = &s->downstream_as;
123 } else {
124 event.entry.target_as = &s->blocked_io_as;
125 }
126 memory_region_notify_iommu(&s->upstream, IOMMU_IDX_NS, event);
127 }
128}
129
130static void tz_mpc_autoinc_idx(TZMPC *s, unsigned access_size)
131{
132
133 if (access_size == 4 && (s->ctrl & R_CTRL_AUTOINC_MASK)) {
134 s->blk_idx++;
135 s->blk_idx %= s->blk_max;
136 }
137}
138
139static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr,
140 uint64_t *pdata,
141 unsigned size, MemTxAttrs attrs)
142{
143 TZMPC *s = TZ_MPC(opaque);
144 uint64_t r;
145 uint32_t offset = addr & ~0x3;
146
147 if (!attrs.secure && offset < A_PIDR4) {
148
149 qemu_log_mask(LOG_GUEST_ERROR,
150 "TZ MPC register read: NS access to offset 0x%x\n",
151 offset);
152 r = 0;
153 goto read_out;
154 }
155
156 switch (offset) {
157 case A_CTRL:
158 r = s->ctrl;
159 break;
160 case A_BLK_MAX:
161 r = s->blk_max - 1;
162 break;
163 case A_BLK_CFG:
164
165
166
167
168 r = ctz32(s->blocksize) - 5;
169 break;
170 case A_BLK_IDX:
171 r = s->blk_idx;
172 break;
173 case A_BLK_LUT:
174 r = s->blk_lut[s->blk_idx];
175 tz_mpc_autoinc_idx(s, size);
176 break;
177 case A_INT_STAT:
178 r = s->int_stat;
179 break;
180 case A_INT_EN:
181 r = s->int_en;
182 break;
183 case A_INT_INFO1:
184 r = s->int_info1;
185 break;
186 case A_INT_INFO2:
187 r = s->int_info2;
188 break;
189 case A_PIDR4:
190 case A_PIDR5:
191 case A_PIDR6:
192 case A_PIDR7:
193 case A_PIDR0:
194 case A_PIDR1:
195 case A_PIDR2:
196 case A_PIDR3:
197 case A_CIDR0:
198 case A_CIDR1:
199 case A_CIDR2:
200 case A_CIDR3:
201 r = tz_mpc_idregs[(offset - A_PIDR4) / 4];
202 break;
203 case A_INT_CLEAR:
204 case A_INT_SET:
205 qemu_log_mask(LOG_GUEST_ERROR,
206 "TZ MPC register read: write-only offset 0x%x\n",
207 offset);
208 r = 0;
209 break;
210 default:
211 qemu_log_mask(LOG_GUEST_ERROR,
212 "TZ MPC register read: bad offset 0x%x\n", offset);
213 r = 0;
214 break;
215 }
216
217 if (size != 4) {
218
219
220
221
222 r = extract32(r, (addr & 3) * 8, size * 8);
223 }
224
225read_out:
226 trace_tz_mpc_reg_read(addr, r, size);
227 *pdata = r;
228 return MEMTX_OK;
229}
230
231static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
232 uint64_t value,
233 unsigned size, MemTxAttrs attrs)
234{
235 TZMPC *s = TZ_MPC(opaque);
236 uint32_t offset = addr & ~0x3;
237
238 trace_tz_mpc_reg_write(addr, value, size);
239
240 if (!attrs.secure && offset < A_PIDR4) {
241
242 qemu_log_mask(LOG_GUEST_ERROR,
243 "TZ MPC register write: NS access to offset 0x%x\n",
244 offset);
245 return MEMTX_OK;
246 }
247
248 if (size != 4) {
249
250
251
252
253 uint32_t oldval;
254
255 switch (offset) {
256 case A_CTRL:
257 oldval = s->ctrl;
258 break;
259 case A_BLK_IDX:
260 oldval = s->blk_idx;
261 break;
262 case A_BLK_LUT:
263 oldval = s->blk_lut[s->blk_idx];
264 break;
265 default:
266 oldval = 0;
267 break;
268 }
269 value = deposit32(oldval, (addr & 3) * 8, size * 8, value);
270 }
271
272 if ((s->ctrl & R_CTRL_LOCKDOWN_MASK) &&
273 (offset == A_CTRL || offset == A_BLK_LUT || offset == A_INT_EN)) {
274
275
276
277 qemu_log_mask(LOG_GUEST_ERROR, "TZ MPC register write to offset 0x%x "
278 "while MPC is in lockdown mode\n", offset);
279 return MEMTX_OK;
280 }
281
282 switch (offset) {
283 case A_CTRL:
284
285
286
287 s->ctrl = value & (R_CTRL_SEC_RESP_MASK |
288 R_CTRL_AUTOINC_MASK |
289 R_CTRL_LOCKDOWN_MASK);
290 break;
291 case A_BLK_IDX:
292 s->blk_idx = value % s->blk_max;
293 break;
294 case A_BLK_LUT:
295 tz_mpc_iommu_notify(s, s->blk_idx, s->blk_lut[s->blk_idx], value);
296 s->blk_lut[s->blk_idx] = value;
297 tz_mpc_autoinc_idx(s, size);
298 break;
299 case A_INT_CLEAR:
300 if (value & R_INT_CLEAR_IRQ_MASK) {
301 s->int_stat = 0;
302 tz_mpc_irq_update(s);
303 }
304 break;
305 case A_INT_EN:
306 s->int_en = value & R_INT_EN_IRQ_MASK;
307 tz_mpc_irq_update(s);
308 break;
309 case A_INT_SET:
310 if (value & R_INT_SET_IRQ_MASK) {
311 s->int_stat = R_INT_STAT_IRQ_MASK;
312 tz_mpc_irq_update(s);
313 }
314 break;
315 case A_PIDR4:
316 case A_PIDR5:
317 case A_PIDR6:
318 case A_PIDR7:
319 case A_PIDR0:
320 case A_PIDR1:
321 case A_PIDR2:
322 case A_PIDR3:
323 case A_CIDR0:
324 case A_CIDR1:
325 case A_CIDR2:
326 case A_CIDR3:
327 qemu_log_mask(LOG_GUEST_ERROR,
328 "TZ MPC register write: read-only offset 0x%x\n", offset);
329 break;
330 default:
331 qemu_log_mask(LOG_GUEST_ERROR,
332 "TZ MPC register write: bad offset 0x%x\n", offset);
333 break;
334 }
335
336 return MEMTX_OK;
337}
338
339static const MemoryRegionOps tz_mpc_reg_ops = {
340 .read_with_attrs = tz_mpc_reg_read,
341 .write_with_attrs = tz_mpc_reg_write,
342 .endianness = DEVICE_LITTLE_ENDIAN,
343 .valid.min_access_size = 1,
344 .valid.max_access_size = 4,
345 .impl.min_access_size = 1,
346 .impl.max_access_size = 4,
347};
348
349static inline bool tz_mpc_cfg_ns(TZMPC *s, hwaddr addr)
350{
351
352 hwaddr blknum = addr / s->blocksize;
353 hwaddr blkword = blknum / 32;
354 uint32_t blkbit = 1U << (blknum % 32);
355
356
357
358
359 assert(blkword < s->blk_max);
360 return s->blk_lut[blkword] & blkbit;
361}
362
363static MemTxResult tz_mpc_handle_block(TZMPC *s, hwaddr addr, MemTxAttrs attrs)
364{
365
366 if (!s->int_stat) {
367
368
369
370
371
372 s->int_info1 = addr;
373 s->int_info2 = 0;
374 s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, HMASTER,
375 attrs.requester_id & 0xffff);
376 s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, HNONSEC,
377 ~attrs.secure);
378 s->int_info2 = FIELD_DP32(s->int_info2, INT_INFO2, CFG_NS,
379 tz_mpc_cfg_ns(s, addr));
380 s->int_stat |= R_INT_STAT_IRQ_MASK;
381 tz_mpc_irq_update(s);
382 }
383
384
385 return (s->ctrl & R_CTRL_SEC_RESP_MASK) ? MEMTX_ERROR : MEMTX_OK;
386}
387
388
389
390
391
392static MemTxResult tz_mpc_mem_blocked_read(void *opaque, hwaddr addr,
393 uint64_t *pdata,
394 unsigned size, MemTxAttrs attrs)
395{
396 TZMPC *s = TZ_MPC(opaque);
397
398 trace_tz_mpc_mem_blocked_read(addr, size, attrs.secure);
399
400 *pdata = 0;
401 return tz_mpc_handle_block(s, addr, attrs);
402}
403
404static MemTxResult tz_mpc_mem_blocked_write(void *opaque, hwaddr addr,
405 uint64_t value,
406 unsigned size, MemTxAttrs attrs)
407{
408 TZMPC *s = TZ_MPC(opaque);
409
410 trace_tz_mpc_mem_blocked_write(addr, value, size, attrs.secure);
411
412 return tz_mpc_handle_block(s, addr, attrs);
413}
414
415static const MemoryRegionOps tz_mpc_mem_blocked_ops = {
416 .read_with_attrs = tz_mpc_mem_blocked_read,
417 .write_with_attrs = tz_mpc_mem_blocked_write,
418 .endianness = DEVICE_LITTLE_ENDIAN,
419 .valid.min_access_size = 1,
420 .valid.max_access_size = 8,
421 .impl.min_access_size = 1,
422 .impl.max_access_size = 8,
423};
424
425static IOMMUTLBEntry tz_mpc_translate(IOMMUMemoryRegion *iommu,
426 hwaddr addr, IOMMUAccessFlags flags,
427 int iommu_idx)
428{
429 TZMPC *s = TZ_MPC(container_of(iommu, TZMPC, upstream));
430 bool ok;
431
432 IOMMUTLBEntry ret = {
433 .iova = addr & ~(s->blocksize - 1),
434 .translated_addr = addr & ~(s->blocksize - 1),
435 .addr_mask = s->blocksize - 1,
436 .perm = IOMMU_RW,
437 };
438
439
440
441
442
443
444
445 ok = tz_mpc_cfg_ns(s, addr) == (iommu_idx == IOMMU_IDX_NS);
446
447 trace_tz_mpc_translate(addr, flags,
448 iommu_idx == IOMMU_IDX_S ? "S" : "NS",
449 ok ? "pass" : "block");
450
451 ret.target_as = ok ? &s->downstream_as : &s->blocked_io_as;
452 return ret;
453}
454
455static int tz_mpc_attrs_to_index(IOMMUMemoryRegion *iommu, MemTxAttrs attrs)
456{
457
458
459
460
461
462
463
464 return (attrs.unspecified || attrs.secure) ? IOMMU_IDX_S : IOMMU_IDX_NS;
465}
466
467static int tz_mpc_num_indexes(IOMMUMemoryRegion *iommu)
468{
469 return IOMMU_NUM_INDEXES;
470}
471
472static void tz_mpc_reset(DeviceState *dev)
473{
474 TZMPC *s = TZ_MPC(dev);
475
476 s->ctrl = 0x00000100;
477 s->blk_idx = 0;
478 s->int_stat = 0;
479 s->int_en = 1;
480 s->int_info1 = 0;
481 s->int_info2 = 0;
482
483 memset(s->blk_lut, 0, s->blk_max * sizeof(uint32_t));
484}
485
486static void tz_mpc_init(Object *obj)
487{
488 DeviceState *dev = DEVICE(obj);
489 TZMPC *s = TZ_MPC(obj);
490
491 qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
492}
493
494static void tz_mpc_realize(DeviceState *dev, Error **errp)
495{
496 Object *obj = OBJECT(dev);
497 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
498 TZMPC *s = TZ_MPC(dev);
499 uint64_t size;
500
501
502
503
504
505
506
507
508 if (!s->downstream) {
509 error_setg(errp, "MPC 'downstream' link not set");
510 return;
511 }
512
513 size = memory_region_size(s->downstream);
514
515 memory_region_init_iommu(&s->upstream, sizeof(s->upstream),
516 TYPE_TZ_MPC_IOMMU_MEMORY_REGION,
517 obj, "tz-mpc-upstream", size);
518
519
520
521
522
523
524
525 s->blocksize = memory_region_iommu_get_min_page_size(&s->upstream);
526 if (size % s->blocksize != 0) {
527 error_setg(errp,
528 "MPC 'downstream' size %" PRId64
529 " is not a multiple of %" HWADDR_PRIx " bytes",
530 size, s->blocksize);
531 object_unref(OBJECT(&s->upstream));
532 return;
533 }
534
535
536
537
538 s->blk_max = DIV_ROUND_UP(size / s->blocksize, 32);
539
540 memory_region_init_io(&s->regmr, obj, &tz_mpc_reg_ops,
541 s, "tz-mpc-regs", 0x1000);
542 sysbus_init_mmio(sbd, &s->regmr);
543
544 sysbus_init_mmio(sbd, MEMORY_REGION(&s->upstream));
545
546
547
548
549
550 memory_region_init_io(&s->blocked_io, obj, &tz_mpc_mem_blocked_ops,
551 s, "tz-mpc-blocked-io", size);
552
553 address_space_init(&s->downstream_as, s->downstream,
554 "tz-mpc-downstream");
555 address_space_init(&s->blocked_io_as, &s->blocked_io,
556 "tz-mpc-blocked-io");
557
558 s->blk_lut = g_new0(uint32_t, s->blk_max);
559}
560
561static int tz_mpc_post_load(void *opaque, int version_id)
562{
563 TZMPC *s = TZ_MPC(opaque);
564
565
566 if (s->blk_idx >= s->blk_max) {
567 return -1;
568 }
569 return 0;
570}
571
572static const VMStateDescription tz_mpc_vmstate = {
573 .name = "tz-mpc",
574 .version_id = 1,
575 .minimum_version_id = 1,
576 .post_load = tz_mpc_post_load,
577 .fields = (VMStateField[]) {
578 VMSTATE_UINT32(ctrl, TZMPC),
579 VMSTATE_UINT32(blk_idx, TZMPC),
580 VMSTATE_UINT32(int_stat, TZMPC),
581 VMSTATE_UINT32(int_en, TZMPC),
582 VMSTATE_UINT32(int_info1, TZMPC),
583 VMSTATE_UINT32(int_info2, TZMPC),
584 VMSTATE_VARRAY_UINT32(blk_lut, TZMPC, blk_max,
585 0, vmstate_info_uint32, uint32_t),
586 VMSTATE_END_OF_LIST()
587 }
588};
589
590static Property tz_mpc_properties[] = {
591 DEFINE_PROP_LINK("downstream", TZMPC, downstream,
592 TYPE_MEMORY_REGION, MemoryRegion *),
593 DEFINE_PROP_END_OF_LIST(),
594};
595
596static void tz_mpc_class_init(ObjectClass *klass, void *data)
597{
598 DeviceClass *dc = DEVICE_CLASS(klass);
599
600 dc->realize = tz_mpc_realize;
601 dc->vmsd = &tz_mpc_vmstate;
602 dc->reset = tz_mpc_reset;
603 device_class_set_props(dc, tz_mpc_properties);
604}
605
606static const TypeInfo tz_mpc_info = {
607 .name = TYPE_TZ_MPC,
608 .parent = TYPE_SYS_BUS_DEVICE,
609 .instance_size = sizeof(TZMPC),
610 .instance_init = tz_mpc_init,
611 .class_init = tz_mpc_class_init,
612};
613
614static void tz_mpc_iommu_memory_region_class_init(ObjectClass *klass,
615 void *data)
616{
617 IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
618
619 imrc->translate = tz_mpc_translate;
620 imrc->attrs_to_index = tz_mpc_attrs_to_index;
621 imrc->num_indexes = tz_mpc_num_indexes;
622}
623
624static const TypeInfo tz_mpc_iommu_memory_region_info = {
625 .name = TYPE_TZ_MPC_IOMMU_MEMORY_REGION,
626 .parent = TYPE_IOMMU_MEMORY_REGION,
627 .class_init = tz_mpc_iommu_memory_region_class_init,
628};
629
630static void tz_mpc_register_types(void)
631{
632 type_register_static(&tz_mpc_info);
633 type_register_static(&tz_mpc_iommu_memory_region_info);
634}
635
636type_init(tz_mpc_register_types);
637