xref: /qemu/hw/misc/tz-msc.c (revision 06b40d250ecfa1633209c2e431a7a38acfd03a98)
1  /*
2   * ARM TrustZone master security 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 "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-msc.h"
22  #include "hw/qdev-properties.h"
23  
tz_msc_update_irq(TZMSC * s)24  static void tz_msc_update_irq(TZMSC *s)
25  {
26      bool level = s->irq_status;
27  
28      trace_tz_msc_update_irq(level);
29      qemu_set_irq(s->irq, level);
30  }
31  
tz_msc_cfg_nonsec(void * opaque,int n,int level)32  static void tz_msc_cfg_nonsec(void *opaque, int n, int level)
33  {
34      TZMSC *s = TZ_MSC(opaque);
35  
36      trace_tz_msc_cfg_nonsec(level);
37      s->cfg_nonsec = level;
38  }
39  
tz_msc_cfg_sec_resp(void * opaque,int n,int level)40  static void tz_msc_cfg_sec_resp(void *opaque, int n, int level)
41  {
42      TZMSC *s = TZ_MSC(opaque);
43  
44      trace_tz_msc_cfg_sec_resp(level);
45      s->cfg_sec_resp = level;
46  }
47  
tz_msc_irq_clear(void * opaque,int n,int level)48  static void tz_msc_irq_clear(void *opaque, int n, int level)
49  {
50      TZMSC *s = TZ_MSC(opaque);
51  
52      trace_tz_msc_irq_clear(level);
53  
54      s->irq_clear = level;
55      if (level) {
56          s->irq_status = false;
57          tz_msc_update_irq(s);
58      }
59  }
60  
61  /* The MSC may either block a transaction by aborting it, block a
62   * transaction by making it RAZ/WI, allow it through with
63   * MemTxAttrs indicating a secure transaction, or allow it with
64   * MemTxAttrs indicating a non-secure transaction.
65   */
66  typedef enum MSCAction {
67      MSCBlockAbort,
68      MSCBlockRAZWI,
69      MSCAllowSecure,
70      MSCAllowNonSecure,
71  } MSCAction;
72  
tz_msc_check(TZMSC * s,hwaddr addr)73  static MSCAction tz_msc_check(TZMSC *s, hwaddr addr)
74  {
75      /*
76       * Check whether to allow an access from the bus master, returning
77       * an MSCAction indicating the required behaviour. If the transaction
78       * is blocked, the caller must check cfg_sec_resp to determine
79       * whether to abort or RAZ/WI the transaction.
80       */
81      IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(s->idau);
82      IDAUInterface *ii = IDAU_INTERFACE(s->idau);
83      bool idau_exempt = false, idau_ns = true, idau_nsc = true;
84      int idau_region = IREGION_NOTVALID;
85  
86      iic->check(ii, addr, &idau_region, &idau_exempt, &idau_ns, &idau_nsc);
87  
88      if (idau_exempt) {
89          /*
90           * Uncheck region -- OK, transaction type depends on
91           * whether bus master is configured as Secure or NonSecure
92           */
93          return s->cfg_nonsec ? MSCAllowNonSecure : MSCAllowSecure;
94      }
95  
96      if (idau_ns) {
97          /* NonSecure region -- always forward as NS transaction */
98          return MSCAllowNonSecure;
99      }
100  
101      if (!s->cfg_nonsec) {
102          /* Access to Secure region by Secure bus master: OK */
103          return MSCAllowSecure;
104      }
105  
106      /* Attempted access to Secure region by NS bus master: block */
107      trace_tz_msc_access_blocked(addr);
108      if (!s->cfg_sec_resp) {
109          return MSCBlockRAZWI;
110      }
111  
112      /*
113       * The TRM isn't clear on behaviour if irq_clear is high when a
114       * transaction is blocked. We assume that the MSC behaves like the
115       * PPC, where holding irq_clear high suppresses the interrupt.
116       */
117      if (!s->irq_clear) {
118          s->irq_status = true;
119          tz_msc_update_irq(s);
120      }
121      return MSCBlockAbort;
122  }
123  
tz_msc_read(void * opaque,hwaddr addr,uint64_t * pdata,unsigned size,MemTxAttrs attrs)124  static MemTxResult tz_msc_read(void *opaque, hwaddr addr, uint64_t *pdata,
125                                 unsigned size, MemTxAttrs attrs)
126  {
127      TZMSC *s = opaque;
128      AddressSpace *as = &s->downstream_as;
129      uint64_t data;
130      MemTxResult res;
131  
132      switch (tz_msc_check(s, addr)) {
133      case MSCBlockAbort:
134          return MEMTX_ERROR;
135      case MSCBlockRAZWI:
136          *pdata = 0;
137          return MEMTX_OK;
138      case MSCAllowSecure:
139          attrs.secure = 1;
140          attrs.unspecified = 0;
141          break;
142      case MSCAllowNonSecure:
143          attrs.secure = 0;
144          attrs.unspecified = 0;
145          break;
146      }
147  
148      switch (size) {
149      case 1:
150          data = address_space_ldub(as, addr, attrs, &res);
151          break;
152      case 2:
153          data = address_space_lduw_le(as, addr, attrs, &res);
154          break;
155      case 4:
156          data = address_space_ldl_le(as, addr, attrs, &res);
157          break;
158      case 8:
159          data = address_space_ldq_le(as, addr, attrs, &res);
160          break;
161      default:
162          g_assert_not_reached();
163      }
164      *pdata = data;
165      return res;
166  }
167  
tz_msc_write(void * opaque,hwaddr addr,uint64_t val,unsigned size,MemTxAttrs attrs)168  static MemTxResult tz_msc_write(void *opaque, hwaddr addr, uint64_t val,
169                                  unsigned size, MemTxAttrs attrs)
170  {
171      TZMSC *s = opaque;
172      AddressSpace *as = &s->downstream_as;
173      MemTxResult res;
174  
175      switch (tz_msc_check(s, addr)) {
176      case MSCBlockAbort:
177          return MEMTX_ERROR;
178      case MSCBlockRAZWI:
179          return MEMTX_OK;
180      case MSCAllowSecure:
181          attrs.secure = 1;
182          attrs.unspecified = 0;
183          break;
184      case MSCAllowNonSecure:
185          attrs.secure = 0;
186          attrs.unspecified = 0;
187          break;
188      }
189  
190      switch (size) {
191      case 1:
192          address_space_stb(as, addr, val, attrs, &res);
193          break;
194      case 2:
195          address_space_stw_le(as, addr, val, attrs, &res);
196          break;
197      case 4:
198          address_space_stl_le(as, addr, val, attrs, &res);
199          break;
200      case 8:
201          address_space_stq_le(as, addr, val, attrs, &res);
202          break;
203      default:
204          g_assert_not_reached();
205      }
206      return res;
207  }
208  
209  static const MemoryRegionOps tz_msc_ops = {
210      .read_with_attrs = tz_msc_read,
211      .write_with_attrs = tz_msc_write,
212      .endianness = DEVICE_LITTLE_ENDIAN,
213  };
214  
tz_msc_reset(DeviceState * dev)215  static void tz_msc_reset(DeviceState *dev)
216  {
217      TZMSC *s = TZ_MSC(dev);
218  
219      trace_tz_msc_reset();
220      s->cfg_sec_resp = false;
221      s->cfg_nonsec = false;
222      s->irq_clear = 0;
223      s->irq_status = 0;
224  }
225  
tz_msc_init(Object * obj)226  static void tz_msc_init(Object *obj)
227  {
228      DeviceState *dev = DEVICE(obj);
229      TZMSC *s = TZ_MSC(obj);
230  
231      qdev_init_gpio_in_named(dev, tz_msc_cfg_nonsec, "cfg_nonsec", 1);
232      qdev_init_gpio_in_named(dev, tz_msc_cfg_sec_resp, "cfg_sec_resp", 1);
233      qdev_init_gpio_in_named(dev, tz_msc_irq_clear, "irq_clear", 1);
234      qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
235  }
236  
tz_msc_realize(DeviceState * dev,Error ** errp)237  static void tz_msc_realize(DeviceState *dev, Error **errp)
238  {
239      Object *obj = OBJECT(dev);
240      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
241      TZMSC *s = TZ_MSC(dev);
242      const char *name = "tz-msc-downstream";
243      uint64_t size;
244  
245      /*
246       * We can't create the upstream end of the port until realize,
247       * as we don't know the size of the MR used as the downstream until then.
248       * We insist on having a downstream, to avoid complicating the
249       * code with handling the "don't know how big this is" case. It's easy
250       * enough for the user to create an unimplemented_device as downstream
251       * if they have nothing else to plug into this.
252       */
253      if (!s->downstream) {
254          error_setg(errp, "MSC 'downstream' link not set");
255          return;
256      }
257      if (!s->idau) {
258          error_setg(errp, "MSC 'idau' link not set");
259          return;
260      }
261  
262      size = memory_region_size(s->downstream);
263      address_space_init(&s->downstream_as, s->downstream, name);
264      memory_region_init_io(&s->upstream, obj, &tz_msc_ops, s, name, size);
265      sysbus_init_mmio(sbd, &s->upstream);
266  }
267  
268  static const VMStateDescription tz_msc_vmstate = {
269      .name = "tz-msc",
270      .version_id = 1,
271      .minimum_version_id = 1,
272      .fields = (const VMStateField[]) {
273          VMSTATE_BOOL(cfg_nonsec, TZMSC),
274          VMSTATE_BOOL(cfg_sec_resp, TZMSC),
275          VMSTATE_BOOL(irq_clear, TZMSC),
276          VMSTATE_BOOL(irq_status, TZMSC),
277          VMSTATE_END_OF_LIST()
278      }
279  };
280  
281  static const Property tz_msc_properties[] = {
282      DEFINE_PROP_LINK("downstream", TZMSC, downstream,
283                       TYPE_MEMORY_REGION, MemoryRegion *),
284      DEFINE_PROP_LINK("idau", TZMSC, idau,
285                       TYPE_IDAU_INTERFACE, IDAUInterface *),
286  };
287  
tz_msc_class_init(ObjectClass * klass,const void * data)288  static void tz_msc_class_init(ObjectClass *klass, const void *data)
289  {
290      DeviceClass *dc = DEVICE_CLASS(klass);
291  
292      dc->realize = tz_msc_realize;
293      dc->vmsd = &tz_msc_vmstate;
294      device_class_set_legacy_reset(dc, tz_msc_reset);
295      device_class_set_props(dc, tz_msc_properties);
296  }
297  
298  static const TypeInfo tz_msc_info = {
299      .name = TYPE_TZ_MSC,
300      .parent = TYPE_SYS_BUS_DEVICE,
301      .instance_size = sizeof(TZMSC),
302      .instance_init = tz_msc_init,
303      .class_init = tz_msc_class_init,
304  };
305  
tz_msc_register_types(void)306  static void tz_msc_register_types(void)
307  {
308      type_register_static(&tz_msc_info);
309  }
310  
311  type_init(tz_msc_register_types);
312