2 * ARM TrustZone master security controller emulation
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 "qemu/module.h"
15 #include "qapi/error.h"
17 #include "hw/sysbus.h"
18 #include "migration/vmstate.h"
19 #include "hw/registerfields.h"
21 #include "hw/misc/tz-msc.h"
23 static void tz_msc_update_irq(TZMSC
*s
)
25 bool level
= s
->irq_status
;
27 trace_tz_msc_update_irq(level
);
28 qemu_set_irq(s
->irq
, level
);
31 static void tz_msc_cfg_nonsec(void *opaque
, int n
, int level
)
33 TZMSC
*s
= TZ_MSC(opaque
);
35 trace_tz_msc_cfg_nonsec(level
);
36 s
->cfg_nonsec
= level
;
39 static void tz_msc_cfg_sec_resp(void *opaque
, int n
, int level
)
41 TZMSC
*s
= TZ_MSC(opaque
);
43 trace_tz_msc_cfg_sec_resp(level
);
44 s
->cfg_sec_resp
= level
;
47 static void tz_msc_irq_clear(void *opaque
, int n
, int level
)
49 TZMSC
*s
= TZ_MSC(opaque
);
51 trace_tz_msc_irq_clear(level
);
55 s
->irq_status
= false;
60 /* The MSC may either block a transaction by aborting it, block a
61 * transaction by making it RAZ/WI, allow it through with
62 * MemTxAttrs indicating a secure transaction, or allow it with
63 * MemTxAttrs indicating a non-secure transaction.
65 typedef enum MSCAction
{
72 static MSCAction
tz_msc_check(TZMSC
*s
, hwaddr addr
)
75 * Check whether to allow an access from the bus master, returning
76 * an MSCAction indicating the required behaviour. If the transaction
77 * is blocked, the caller must check cfg_sec_resp to determine
78 * whether to abort or RAZ/WI the transaction.
80 IDAUInterfaceClass
*iic
= IDAU_INTERFACE_GET_CLASS(s
->idau
);
81 IDAUInterface
*ii
= IDAU_INTERFACE(s
->idau
);
82 bool idau_exempt
= false, idau_ns
= true, idau_nsc
= true;
83 int idau_region
= IREGION_NOTVALID
;
85 iic
->check(ii
, addr
, &idau_region
, &idau_exempt
, &idau_ns
, &idau_nsc
);
89 * Uncheck region -- OK, transaction type depends on
90 * whether bus master is configured as Secure or NonSecure
92 return s
->cfg_nonsec
? MSCAllowNonSecure
: MSCAllowSecure
;
96 /* NonSecure region -- always forward as NS transaction */
97 return MSCAllowNonSecure
;
100 if (!s
->cfg_nonsec
) {
101 /* Access to Secure region by Secure bus master: OK */
102 return MSCAllowSecure
;
105 /* Attempted access to Secure region by NS bus master: block */
106 trace_tz_msc_access_blocked(addr
);
107 if (!s
->cfg_sec_resp
) {
108 return MSCBlockRAZWI
;
112 * The TRM isn't clear on behaviour if irq_clear is high when a
113 * transaction is blocked. We assume that the MSC behaves like the
114 * PPC, where holding irq_clear high suppresses the interrupt.
117 s
->irq_status
= true;
118 tz_msc_update_irq(s
);
120 return MSCBlockAbort
;
123 static MemTxResult
tz_msc_read(void *opaque
, hwaddr addr
, uint64_t *pdata
,
124 unsigned size
, MemTxAttrs attrs
)
127 AddressSpace
*as
= &s
->downstream_as
;
131 switch (tz_msc_check(s
, addr
)) {
139 attrs
.unspecified
= 0;
141 case MSCAllowNonSecure
:
143 attrs
.unspecified
= 0;
149 data
= address_space_ldub(as
, addr
, attrs
, &res
);
152 data
= address_space_lduw_le(as
, addr
, attrs
, &res
);
155 data
= address_space_ldl_le(as
, addr
, attrs
, &res
);
158 data
= address_space_ldq_le(as
, addr
, attrs
, &res
);
161 g_assert_not_reached();
167 static MemTxResult
tz_msc_write(void *opaque
, hwaddr addr
, uint64_t val
,
168 unsigned size
, MemTxAttrs attrs
)
171 AddressSpace
*as
= &s
->downstream_as
;
174 switch (tz_msc_check(s
, addr
)) {
181 attrs
.unspecified
= 0;
183 case MSCAllowNonSecure
:
185 attrs
.unspecified
= 0;
191 address_space_stb(as
, addr
, val
, attrs
, &res
);
194 address_space_stw_le(as
, addr
, val
, attrs
, &res
);
197 address_space_stl_le(as
, addr
, val
, attrs
, &res
);
200 address_space_stq_le(as
, addr
, val
, attrs
, &res
);
203 g_assert_not_reached();
208 static const MemoryRegionOps tz_msc_ops
= {
209 .read_with_attrs
= tz_msc_read
,
210 .write_with_attrs
= tz_msc_write
,
211 .endianness
= DEVICE_LITTLE_ENDIAN
,
214 static void tz_msc_reset(DeviceState
*dev
)
216 TZMSC
*s
= TZ_MSC(dev
);
218 trace_tz_msc_reset();
219 s
->cfg_sec_resp
= false;
220 s
->cfg_nonsec
= false;
225 static void tz_msc_init(Object
*obj
)
227 DeviceState
*dev
= DEVICE(obj
);
228 TZMSC
*s
= TZ_MSC(obj
);
230 qdev_init_gpio_in_named(dev
, tz_msc_cfg_nonsec
, "cfg_nonsec", 1);
231 qdev_init_gpio_in_named(dev
, tz_msc_cfg_sec_resp
, "cfg_sec_resp", 1);
232 qdev_init_gpio_in_named(dev
, tz_msc_irq_clear
, "irq_clear", 1);
233 qdev_init_gpio_out_named(dev
, &s
->irq
, "irq", 1);
236 static void tz_msc_realize(DeviceState
*dev
, Error
**errp
)
238 Object
*obj
= OBJECT(dev
);
239 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
240 TZMSC
*s
= TZ_MSC(dev
);
241 const char *name
= "tz-msc-downstream";
245 * We can't create the upstream end of the port until realize,
246 * as we don't know the size of the MR used as the downstream until then.
247 * We insist on having a downstream, to avoid complicating the
248 * code with handling the "don't know how big this is" case. It's easy
249 * enough for the user to create an unimplemented_device as downstream
250 * if they have nothing else to plug into this.
252 if (!s
->downstream
) {
253 error_setg(errp
, "MSC 'downstream' link not set");
257 error_setg(errp
, "MSC 'idau' link not set");
261 size
= memory_region_size(s
->downstream
);
262 address_space_init(&s
->downstream_as
, s
->downstream
, name
);
263 memory_region_init_io(&s
->upstream
, obj
, &tz_msc_ops
, s
, name
, size
);
264 sysbus_init_mmio(sbd
, &s
->upstream
);
267 static const VMStateDescription tz_msc_vmstate
= {
270 .minimum_version_id
= 1,
271 .fields
= (VMStateField
[]) {
272 VMSTATE_BOOL(cfg_nonsec
, TZMSC
),
273 VMSTATE_BOOL(cfg_sec_resp
, TZMSC
),
274 VMSTATE_BOOL(irq_clear
, TZMSC
),
275 VMSTATE_BOOL(irq_status
, TZMSC
),
276 VMSTATE_END_OF_LIST()
280 static Property tz_msc_properties
[] = {
281 DEFINE_PROP_LINK("downstream", TZMSC
, downstream
,
282 TYPE_MEMORY_REGION
, MemoryRegion
*),
283 DEFINE_PROP_LINK("idau", TZMSC
, idau
,
284 TYPE_IDAU_INTERFACE
, IDAUInterface
*),
285 DEFINE_PROP_END_OF_LIST(),
288 static void tz_msc_class_init(ObjectClass
*klass
, void *data
)
290 DeviceClass
*dc
= DEVICE_CLASS(klass
);
292 dc
->realize
= tz_msc_realize
;
293 dc
->vmsd
= &tz_msc_vmstate
;
294 dc
->reset
= tz_msc_reset
;
295 dc
->props
= tz_msc_properties
;
298 static const TypeInfo tz_msc_info
= {
300 .parent
= TYPE_SYS_BUS_DEVICE
,
301 .instance_size
= sizeof(TZMSC
),
302 .instance_init
= tz_msc_init
,
303 .class_init
= tz_msc_class_init
,
306 static void tz_msc_register_types(void)
308 type_register_static(&tz_msc_info
);
311 type_init(tz_msc_register_types
);