]> Git Repo - qemu.git/blame - hw/misc/tz-mpc.c
hw/misc/tz-mpc.c: Implement registers
[qemu.git] / hw / misc / tz-mpc.c
CommitLineData
344f4b15
PM
1/*
2 * ARM AHB5 TrustZone Memory Protection Controller emulation
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 "qapi/error.h"
15#include "trace.h"
16#include "hw/sysbus.h"
17#include "hw/registerfields.h"
18#include "hw/misc/tz-mpc.h"
19
20/* Our IOMMU has two IOMMU indexes, one for secure transactions and one for
21 * non-secure transactions.
22 */
23enum {
24 IOMMU_IDX_S,
25 IOMMU_IDX_NS,
26 IOMMU_NUM_INDEXES,
27};
28
29/* Config registers */
30REG32(CTRL, 0x00)
cdb60998
PM
31 FIELD(CTRL, SEC_RESP, 4, 1)
32 FIELD(CTRL, AUTOINC, 8, 1)
33 FIELD(CTRL, LOCKDOWN, 31, 1)
344f4b15
PM
34REG32(BLK_MAX, 0x10)
35REG32(BLK_CFG, 0x14)
36REG32(BLK_IDX, 0x18)
37REG32(BLK_LUT, 0x1c)
38REG32(INT_STAT, 0x20)
cdb60998 39 FIELD(INT_STAT, IRQ, 0, 1)
344f4b15 40REG32(INT_CLEAR, 0x24)
cdb60998 41 FIELD(INT_CLEAR, IRQ, 0, 1)
344f4b15 42REG32(INT_EN, 0x28)
cdb60998 43 FIELD(INT_EN, IRQ, 0, 1)
344f4b15
PM
44REG32(INT_INFO1, 0x2c)
45REG32(INT_INFO2, 0x30)
46REG32(INT_SET, 0x34)
cdb60998 47 FIELD(INT_SET, IRQ, 0, 1)
344f4b15
PM
48REG32(PIDR4, 0xfd0)
49REG32(PIDR5, 0xfd4)
50REG32(PIDR6, 0xfd8)
51REG32(PIDR7, 0xfdc)
52REG32(PIDR0, 0xfe0)
53REG32(PIDR1, 0xfe4)
54REG32(PIDR2, 0xfe8)
55REG32(PIDR3, 0xfec)
56REG32(CIDR0, 0xff0)
57REG32(CIDR1, 0xff4)
58REG32(CIDR2, 0xff8)
59REG32(CIDR3, 0xffc)
60
61static const uint8_t tz_mpc_idregs[] = {
62 0x04, 0x00, 0x00, 0x00,
63 0x60, 0xb8, 0x1b, 0x00,
64 0x0d, 0xf0, 0x05, 0xb1,
65};
66
cdb60998
PM
67static void tz_mpc_irq_update(TZMPC *s)
68{
69 qemu_set_irq(s->irq, s->int_stat && s->int_en);
70}
71
72static void tz_mpc_autoinc_idx(TZMPC *s, unsigned access_size)
73{
74 /* Auto-increment BLK_IDX if necessary */
75 if (access_size == 4 && (s->ctrl & R_CTRL_AUTOINC_MASK)) {
76 s->blk_idx++;
77 s->blk_idx %= s->blk_max;
78 }
79}
80
344f4b15
PM
81static MemTxResult tz_mpc_reg_read(void *opaque, hwaddr addr,
82 uint64_t *pdata,
83 unsigned size, MemTxAttrs attrs)
84{
cdb60998 85 TZMPC *s = TZ_MPC(opaque);
344f4b15
PM
86 uint64_t r;
87 uint32_t offset = addr & ~0x3;
88
89 if (!attrs.secure && offset < A_PIDR4) {
90 /* NS accesses can only see the ID registers */
91 qemu_log_mask(LOG_GUEST_ERROR,
92 "TZ MPC register read: NS access to offset 0x%x\n",
93 offset);
94 r = 0;
95 goto read_out;
96 }
97
98 switch (offset) {
cdb60998
PM
99 case A_CTRL:
100 r = s->ctrl;
101 break;
102 case A_BLK_MAX:
103 r = s->blk_max;
104 break;
105 case A_BLK_CFG:
106 /* We are never in "init in progress state", so this just indicates
107 * the block size. s->blocksize == (1 << BLK_CFG + 5), so
108 * BLK_CFG == ctz32(s->blocksize) - 5
109 */
110 r = ctz32(s->blocksize) - 5;
111 break;
112 case A_BLK_IDX:
113 r = s->blk_idx;
114 break;
115 case A_BLK_LUT:
116 r = s->blk_lut[s->blk_idx];
117 tz_mpc_autoinc_idx(s, size);
118 break;
119 case A_INT_STAT:
120 r = s->int_stat;
121 break;
122 case A_INT_EN:
123 r = s->int_en;
124 break;
125 case A_INT_INFO1:
126 r = s->int_info1;
127 break;
128 case A_INT_INFO2:
129 r = s->int_info2;
130 break;
344f4b15
PM
131 case A_PIDR4:
132 case A_PIDR5:
133 case A_PIDR6:
134 case A_PIDR7:
135 case A_PIDR0:
136 case A_PIDR1:
137 case A_PIDR2:
138 case A_PIDR3:
139 case A_CIDR0:
140 case A_CIDR1:
141 case A_CIDR2:
142 case A_CIDR3:
143 r = tz_mpc_idregs[(offset - A_PIDR4) / 4];
144 break;
145 case A_INT_CLEAR:
146 case A_INT_SET:
147 qemu_log_mask(LOG_GUEST_ERROR,
148 "TZ MPC register read: write-only offset 0x%x\n",
149 offset);
150 r = 0;
151 break;
152 default:
153 qemu_log_mask(LOG_GUEST_ERROR,
154 "TZ MPC register read: bad offset 0x%x\n", offset);
155 r = 0;
156 break;
157 }
158
159 if (size != 4) {
160 /* None of our registers are read-sensitive (except BLK_LUT,
161 * which can special case the "size not 4" case), so just
162 * pull the right bytes out of the word read result.
163 */
164 r = extract32(r, (addr & 3) * 8, size * 8);
165 }
166
167read_out:
168 trace_tz_mpc_reg_read(addr, r, size);
169 *pdata = r;
170 return MEMTX_OK;
171}
172
173static MemTxResult tz_mpc_reg_write(void *opaque, hwaddr addr,
174 uint64_t value,
175 unsigned size, MemTxAttrs attrs)
176{
cdb60998 177 TZMPC *s = TZ_MPC(opaque);
344f4b15
PM
178 uint32_t offset = addr & ~0x3;
179
180 trace_tz_mpc_reg_write(addr, value, size);
181
182 if (!attrs.secure && offset < A_PIDR4) {
183 /* NS accesses can only see the ID registers */
184 qemu_log_mask(LOG_GUEST_ERROR,
185 "TZ MPC register write: NS access to offset 0x%x\n",
186 offset);
187 return MEMTX_OK;
188 }
189
190 if (size != 4) {
191 /* Expand the byte or halfword write to a full word size.
192 * In most cases we can do this with zeroes; the exceptions
193 * are CTRL, BLK_IDX and BLK_LUT.
194 */
195 uint32_t oldval;
196
197 switch (offset) {
cdb60998
PM
198 case A_CTRL:
199 oldval = s->ctrl;
200 break;
201 case A_BLK_IDX:
202 oldval = s->blk_idx;
203 break;
204 case A_BLK_LUT:
205 oldval = s->blk_lut[s->blk_idx];
206 break;
344f4b15
PM
207 default:
208 oldval = 0;
209 break;
210 }
211 value = deposit32(oldval, (addr & 3) * 8, size * 8, value);
212 }
213
cdb60998
PM
214 if ((s->ctrl & R_CTRL_LOCKDOWN_MASK) &&
215 (offset == A_CTRL || offset == A_BLK_LUT || offset == A_INT_EN)) {
216 /* Lockdown mode makes these three registers read-only, and
217 * the only way out of it is to reset the device.
218 */
219 qemu_log_mask(LOG_GUEST_ERROR, "TZ MPC register write to offset 0x%x "
220 "while MPC is in lockdown mode\n", offset);
221 return MEMTX_OK;
222 }
223
344f4b15 224 switch (offset) {
cdb60998
PM
225 case A_CTRL:
226 /* We don't implement the 'data gating' feature so all other bits
227 * are reserved and we make them RAZ/WI.
228 */
229 s->ctrl = value & (R_CTRL_SEC_RESP_MASK |
230 R_CTRL_AUTOINC_MASK |
231 R_CTRL_LOCKDOWN_MASK);
232 break;
233 case A_BLK_IDX:
234 s->blk_idx = value % s->blk_max;
235 break;
236 case A_BLK_LUT:
237 s->blk_lut[s->blk_idx] = value;
238 tz_mpc_autoinc_idx(s, size);
239 break;
240 case A_INT_CLEAR:
241 if (value & R_INT_CLEAR_IRQ_MASK) {
242 s->int_stat = 0;
243 tz_mpc_irq_update(s);
244 }
245 break;
246 case A_INT_EN:
247 s->int_en = value & R_INT_EN_IRQ_MASK;
248 tz_mpc_irq_update(s);
249 break;
250 case A_INT_SET:
251 if (value & R_INT_SET_IRQ_MASK) {
252 s->int_stat = R_INT_STAT_IRQ_MASK;
253 tz_mpc_irq_update(s);
254 }
255 break;
344f4b15
PM
256 case A_PIDR4:
257 case A_PIDR5:
258 case A_PIDR6:
259 case A_PIDR7:
260 case A_PIDR0:
261 case A_PIDR1:
262 case A_PIDR2:
263 case A_PIDR3:
264 case A_CIDR0:
265 case A_CIDR1:
266 case A_CIDR2:
267 case A_CIDR3:
268 qemu_log_mask(LOG_GUEST_ERROR,
269 "TZ MPC register write: read-only offset 0x%x\n", offset);
270 break;
271 default:
272 qemu_log_mask(LOG_GUEST_ERROR,
273 "TZ MPC register write: bad offset 0x%x\n", offset);
274 break;
275 }
276
277 return MEMTX_OK;
278}
279
280static const MemoryRegionOps tz_mpc_reg_ops = {
281 .read_with_attrs = tz_mpc_reg_read,
282 .write_with_attrs = tz_mpc_reg_write,
283 .endianness = DEVICE_LITTLE_ENDIAN,
284 .valid.min_access_size = 1,
285 .valid.max_access_size = 4,
286 .impl.min_access_size = 1,
287 .impl.max_access_size = 4,
288};
289
290/* Accesses only reach these read and write functions if the MPC is
291 * blocking them; non-blocked accesses go directly to the downstream
292 * memory region without passing through this code.
293 */
294static MemTxResult tz_mpc_mem_blocked_read(void *opaque, hwaddr addr,
295 uint64_t *pdata,
296 unsigned size, MemTxAttrs attrs)
297{
298 trace_tz_mpc_mem_blocked_read(addr, size, attrs.secure);
299
300 *pdata = 0;
301 return MEMTX_OK;
302}
303
304static MemTxResult tz_mpc_mem_blocked_write(void *opaque, hwaddr addr,
305 uint64_t value,
306 unsigned size, MemTxAttrs attrs)
307{
308 trace_tz_mpc_mem_blocked_write(addr, value, size, attrs.secure);
309
310 return MEMTX_OK;
311}
312
313static const MemoryRegionOps tz_mpc_mem_blocked_ops = {
314 .read_with_attrs = tz_mpc_mem_blocked_read,
315 .write_with_attrs = tz_mpc_mem_blocked_write,
316 .endianness = DEVICE_LITTLE_ENDIAN,
317 .valid.min_access_size = 1,
318 .valid.max_access_size = 8,
319 .impl.min_access_size = 1,
320 .impl.max_access_size = 8,
321};
322
323static IOMMUTLBEntry tz_mpc_translate(IOMMUMemoryRegion *iommu,
324 hwaddr addr, IOMMUAccessFlags flags,
325 int iommu_idx)
326{
327 TZMPC *s = TZ_MPC(container_of(iommu, TZMPC, upstream));
328 bool ok;
329
330 IOMMUTLBEntry ret = {
331 .iova = addr & ~(s->blocksize - 1),
332 .translated_addr = addr & ~(s->blocksize - 1),
333 .addr_mask = s->blocksize - 1,
334 .perm = IOMMU_RW,
335 };
336
337 /* Look at the per-block configuration for this address, and
338 * return a TLB entry directing the transaction at either
339 * downstream_as or blocked_io_as, as appropriate.
340 * For the moment, always permit accesses.
341 */
342 ok = true;
343
344 trace_tz_mpc_translate(addr, flags,
345 iommu_idx == IOMMU_IDX_S ? "S" : "NS",
346 ok ? "pass" : "block");
347
348 ret.target_as = ok ? &s->downstream_as : &s->blocked_io_as;
349 return ret;
350}
351
352static int tz_mpc_attrs_to_index(IOMMUMemoryRegion *iommu, MemTxAttrs attrs)
353{
354 /* We treat unspecified attributes like secure. Transactions with
355 * unspecified attributes come from places like
356 * cpu_physical_memory_write_rom() for initial image load, and we want
357 * those to pass through the from-reset "everything is secure" config.
358 * All the real during-emulation transactions from the CPU will
359 * specify attributes.
360 */
361 return (attrs.unspecified || attrs.secure) ? IOMMU_IDX_S : IOMMU_IDX_NS;
362}
363
364static int tz_mpc_num_indexes(IOMMUMemoryRegion *iommu)
365{
366 return IOMMU_NUM_INDEXES;
367}
368
369static void tz_mpc_reset(DeviceState *dev)
370{
cdb60998
PM
371 TZMPC *s = TZ_MPC(dev);
372
373 s->ctrl = 0x00000100;
374 s->blk_idx = 0;
375 s->int_stat = 0;
376 s->int_en = 1;
377 s->int_info1 = 0;
378 s->int_info2 = 0;
379
380 memset(s->blk_lut, 0, s->blk_max * sizeof(uint32_t));
344f4b15
PM
381}
382
383static void tz_mpc_init(Object *obj)
384{
385 DeviceState *dev = DEVICE(obj);
386 TZMPC *s = TZ_MPC(obj);
387
388 qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
389}
390
391static void tz_mpc_realize(DeviceState *dev, Error **errp)
392{
393 Object *obj = OBJECT(dev);
394 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
395 TZMPC *s = TZ_MPC(dev);
396 uint64_t size;
397
398 /* We can't create the upstream end of the port until realize,
399 * as we don't know the size of the MR used as the downstream until then.
400 * We insist on having a downstream, to avoid complicating the code
401 * with handling the "don't know how big this is" case. It's easy
402 * enough for the user to create an unimplemented_device as downstream
403 * if they have nothing else to plug into this.
404 */
405 if (!s->downstream) {
406 error_setg(errp, "MPC 'downstream' link not set");
407 return;
408 }
409
410 size = memory_region_size(s->downstream);
411
412 memory_region_init_iommu(&s->upstream, sizeof(s->upstream),
413 TYPE_TZ_MPC_IOMMU_MEMORY_REGION,
414 obj, "tz-mpc-upstream", size);
415
416 /* In real hardware the block size is configurable. In QEMU we could
417 * make it configurable but will need it to be at least as big as the
418 * target page size so we can execute out of the resulting MRs. Guest
419 * software is supposed to check the block size using the BLK_CFG
420 * register, so make it fixed at the page size.
421 */
422 s->blocksize = memory_region_iommu_get_min_page_size(&s->upstream);
423 if (size % s->blocksize != 0) {
424 error_setg(errp,
425 "MPC 'downstream' size %" PRId64
426 " is not a multiple of %" HWADDR_PRIx " bytes",
427 size, s->blocksize);
428 object_unref(OBJECT(&s->upstream));
429 return;
430 }
431
432 /* BLK_MAX is the max value of BLK_IDX, which indexes an array of 32-bit
433 * words, each bit of which indicates one block.
434 */
435 s->blk_max = DIV_ROUND_UP(size / s->blocksize, 32);
436
437 memory_region_init_io(&s->regmr, obj, &tz_mpc_reg_ops,
438 s, "tz-mpc-regs", 0x1000);
439 sysbus_init_mmio(sbd, &s->regmr);
440
441 sysbus_init_mmio(sbd, MEMORY_REGION(&s->upstream));
442
443 /* This memory region is not exposed to users of this device as a
444 * sysbus MMIO region, but is instead used internally as something
445 * that our IOMMU translate function might direct accesses to.
446 */
447 memory_region_init_io(&s->blocked_io, obj, &tz_mpc_mem_blocked_ops,
448 s, "tz-mpc-blocked-io", size);
449
450 address_space_init(&s->downstream_as, s->downstream,
451 "tz-mpc-downstream");
452 address_space_init(&s->blocked_io_as, &s->blocked_io,
453 "tz-mpc-blocked-io");
cdb60998
PM
454
455 s->blk_lut = g_new(uint32_t, s->blk_max);
456}
457
458static int tz_mpc_post_load(void *opaque, int version_id)
459{
460 TZMPC *s = TZ_MPC(opaque);
461
462 /* Check the incoming data doesn't point blk_idx off the end of blk_lut. */
463 if (s->blk_idx >= s->blk_max) {
464 return -1;
465 }
466 return 0;
344f4b15
PM
467}
468
469static const VMStateDescription tz_mpc_vmstate = {
470 .name = "tz-mpc",
471 .version_id = 1,
472 .minimum_version_id = 1,
cdb60998 473 .post_load = tz_mpc_post_load,
344f4b15 474 .fields = (VMStateField[]) {
cdb60998
PM
475 VMSTATE_UINT32(ctrl, TZMPC),
476 VMSTATE_UINT32(blk_idx, TZMPC),
477 VMSTATE_UINT32(int_stat, TZMPC),
478 VMSTATE_UINT32(int_en, TZMPC),
479 VMSTATE_UINT32(int_info1, TZMPC),
480 VMSTATE_UINT32(int_info2, TZMPC),
481 VMSTATE_VARRAY_UINT32(blk_lut, TZMPC, blk_max,
482 0, vmstate_info_uint32, uint32_t),
344f4b15
PM
483 VMSTATE_END_OF_LIST()
484 }
485};
486
487static Property tz_mpc_properties[] = {
488 DEFINE_PROP_LINK("downstream", TZMPC, downstream,
489 TYPE_MEMORY_REGION, MemoryRegion *),
490 DEFINE_PROP_END_OF_LIST(),
491};
492
493static void tz_mpc_class_init(ObjectClass *klass, void *data)
494{
495 DeviceClass *dc = DEVICE_CLASS(klass);
496
497 dc->realize = tz_mpc_realize;
498 dc->vmsd = &tz_mpc_vmstate;
499 dc->reset = tz_mpc_reset;
500 dc->props = tz_mpc_properties;
501}
502
503static const TypeInfo tz_mpc_info = {
504 .name = TYPE_TZ_MPC,
505 .parent = TYPE_SYS_BUS_DEVICE,
506 .instance_size = sizeof(TZMPC),
507 .instance_init = tz_mpc_init,
508 .class_init = tz_mpc_class_init,
509};
510
511static void tz_mpc_iommu_memory_region_class_init(ObjectClass *klass,
512 void *data)
513{
514 IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
515
516 imrc->translate = tz_mpc_translate;
517 imrc->attrs_to_index = tz_mpc_attrs_to_index;
518 imrc->num_indexes = tz_mpc_num_indexes;
519}
520
521static const TypeInfo tz_mpc_iommu_memory_region_info = {
522 .name = TYPE_TZ_MPC_IOMMU_MEMORY_REGION,
523 .parent = TYPE_IOMMU_MEMORY_REGION,
524 .class_init = tz_mpc_iommu_memory_region_class_init,
525};
526
527static void tz_mpc_register_types(void)
528{
529 type_register_static(&tz_mpc_info);
530 type_register_static(&tz_mpc_iommu_memory_region_info);
531}
532
533type_init(tz_mpc_register_types);
This page took 0.076519 seconds and 4 git commands to generate.