xref: /openbmc/qemu/hw/misc/tz-ppc.c (revision 28ae3179fc52d2e4d870b635c4a412aab99759e7)
1  /*
2   * ARM TrustZone peripheral 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 "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-ppc.h"
22  #include "hw/qdev-properties.h"
23  
tz_ppc_update_irq(TZPPC * s)24  static void tz_ppc_update_irq(TZPPC *s)
25  {
26      bool level = s->irq_status && s->irq_enable;
27  
28      trace_tz_ppc_update_irq(level);
29      qemu_set_irq(s->irq, level);
30  }
31  
tz_ppc_cfg_nonsec(void * opaque,int n,int level)32  static void tz_ppc_cfg_nonsec(void *opaque, int n, int level)
33  {
34      TZPPC *s = TZ_PPC(opaque);
35  
36      assert(n < TZ_NUM_PORTS);
37      trace_tz_ppc_cfg_nonsec(n, level);
38      s->cfg_nonsec[n] = level;
39  }
40  
tz_ppc_cfg_ap(void * opaque,int n,int level)41  static void tz_ppc_cfg_ap(void *opaque, int n, int level)
42  {
43      TZPPC *s = TZ_PPC(opaque);
44  
45      assert(n < TZ_NUM_PORTS);
46      trace_tz_ppc_cfg_ap(n, level);
47      s->cfg_ap[n] = level;
48  }
49  
tz_ppc_cfg_sec_resp(void * opaque,int n,int level)50  static void tz_ppc_cfg_sec_resp(void *opaque, int n, int level)
51  {
52      TZPPC *s = TZ_PPC(opaque);
53  
54      trace_tz_ppc_cfg_sec_resp(level);
55      s->cfg_sec_resp = level;
56  }
57  
tz_ppc_irq_enable(void * opaque,int n,int level)58  static void tz_ppc_irq_enable(void *opaque, int n, int level)
59  {
60      TZPPC *s = TZ_PPC(opaque);
61  
62      trace_tz_ppc_irq_enable(level);
63      s->irq_enable = level;
64      tz_ppc_update_irq(s);
65  }
66  
tz_ppc_irq_clear(void * opaque,int n,int level)67  static void tz_ppc_irq_clear(void *opaque, int n, int level)
68  {
69      TZPPC *s = TZ_PPC(opaque);
70  
71      trace_tz_ppc_irq_clear(level);
72  
73      s->irq_clear = level;
74      if (level) {
75          s->irq_status = false;
76          tz_ppc_update_irq(s);
77      }
78  }
79  
tz_ppc_check(TZPPC * s,int n,MemTxAttrs attrs)80  static bool tz_ppc_check(TZPPC *s, int n, MemTxAttrs attrs)
81  {
82      /* Check whether to allow an access to port n; return true if
83       * the check passes, and false if the transaction must be blocked.
84       * If the latter, the caller must check cfg_sec_resp to determine
85       * whether to abort or RAZ/WI the transaction.
86       * The checks are:
87       *  + nonsec_mask suppresses any check of the secure attribute
88       *  + otherwise, block if cfg_nonsec is 1 and transaction is secure,
89       *    or if cfg_nonsec is 0 and transaction is non-secure
90       *  + block if transaction is usermode and cfg_ap is 0
91       */
92      if ((attrs.secure == s->cfg_nonsec[n] && !(s->nonsec_mask & (1 << n))) ||
93          (attrs.user && !s->cfg_ap[n])) {
94          /* Block the transaction. */
95          if (!s->irq_clear) {
96              /* Note that holding irq_clear high suppresses interrupts */
97              s->irq_status = true;
98              tz_ppc_update_irq(s);
99          }
100          return false;
101      }
102      return true;
103  }
104  
tz_ppc_read(void * opaque,hwaddr addr,uint64_t * pdata,unsigned size,MemTxAttrs attrs)105  static MemTxResult tz_ppc_read(void *opaque, hwaddr addr, uint64_t *pdata,
106                                 unsigned size, MemTxAttrs attrs)
107  {
108      TZPPCPort *p = opaque;
109      TZPPC *s = p->ppc;
110      int n = p - s->port;
111      AddressSpace *as = &p->downstream_as;
112      uint64_t data;
113      MemTxResult res;
114  
115      if (!tz_ppc_check(s, n, attrs)) {
116          trace_tz_ppc_read_blocked(n, addr, attrs.secure, attrs.user);
117          if (s->cfg_sec_resp) {
118              return MEMTX_ERROR;
119          } else {
120              *pdata = 0;
121              return MEMTX_OK;
122          }
123      }
124  
125      switch (size) {
126      case 1:
127          data = address_space_ldub(as, addr, attrs, &res);
128          break;
129      case 2:
130          data = address_space_lduw_le(as, addr, attrs, &res);
131          break;
132      case 4:
133          data = address_space_ldl_le(as, addr, attrs, &res);
134          break;
135      case 8:
136          data = address_space_ldq_le(as, addr, attrs, &res);
137          break;
138      default:
139          g_assert_not_reached();
140      }
141      *pdata = data;
142      return res;
143  }
144  
tz_ppc_write(void * opaque,hwaddr addr,uint64_t val,unsigned size,MemTxAttrs attrs)145  static MemTxResult tz_ppc_write(void *opaque, hwaddr addr, uint64_t val,
146                                  unsigned size, MemTxAttrs attrs)
147  {
148      TZPPCPort *p = opaque;
149      TZPPC *s = p->ppc;
150      AddressSpace *as = &p->downstream_as;
151      int n = p - s->port;
152      MemTxResult res;
153  
154      if (!tz_ppc_check(s, n, attrs)) {
155          trace_tz_ppc_write_blocked(n, addr, attrs.secure, attrs.user);
156          if (s->cfg_sec_resp) {
157              return MEMTX_ERROR;
158          } else {
159              return MEMTX_OK;
160          }
161      }
162  
163      switch (size) {
164      case 1:
165          address_space_stb(as, addr, val, attrs, &res);
166          break;
167      case 2:
168          address_space_stw_le(as, addr, val, attrs, &res);
169          break;
170      case 4:
171          address_space_stl_le(as, addr, val, attrs, &res);
172          break;
173      case 8:
174          address_space_stq_le(as, addr, val, attrs, &res);
175          break;
176      default:
177          g_assert_not_reached();
178      }
179      return res;
180  }
181  
182  static const MemoryRegionOps tz_ppc_ops = {
183      .read_with_attrs = tz_ppc_read,
184      .write_with_attrs = tz_ppc_write,
185      .endianness = DEVICE_LITTLE_ENDIAN,
186  };
187  
tz_ppc_dummy_accepts(void * opaque,hwaddr addr,unsigned size,bool is_write,MemTxAttrs attrs)188  static bool tz_ppc_dummy_accepts(void *opaque, hwaddr addr,
189                                   unsigned size, bool is_write,
190                                   MemTxAttrs attrs)
191  {
192      /*
193       * Board code should never map the upstream end of an unused port,
194       * so we should never try to make a memory access to it.
195       */
196      g_assert_not_reached();
197  }
198  
tz_ppc_dummy_read(void * opaque,hwaddr addr,unsigned size)199  static uint64_t tz_ppc_dummy_read(void *opaque, hwaddr addr, unsigned size)
200  {
201      g_assert_not_reached();
202  }
203  
tz_ppc_dummy_write(void * opaque,hwaddr addr,uint64_t data,unsigned size)204  static void tz_ppc_dummy_write(void *opaque, hwaddr addr,
205                                          uint64_t data, unsigned size)
206  {
207      g_assert_not_reached();
208  }
209  
210  static const MemoryRegionOps tz_ppc_dummy_ops = {
211      /* define r/w methods to avoid assert failure in memory_region_init_io */
212      .read = tz_ppc_dummy_read,
213      .write = tz_ppc_dummy_write,
214      .valid.accepts = tz_ppc_dummy_accepts,
215  };
216  
tz_ppc_reset(DeviceState * dev)217  static void tz_ppc_reset(DeviceState *dev)
218  {
219      TZPPC *s = TZ_PPC(dev);
220  
221      trace_tz_ppc_reset();
222      s->cfg_sec_resp = false;
223      memset(s->cfg_nonsec, 0, sizeof(s->cfg_nonsec));
224      memset(s->cfg_ap, 0, sizeof(s->cfg_ap));
225  }
226  
tz_ppc_init(Object * obj)227  static void tz_ppc_init(Object *obj)
228  {
229      DeviceState *dev = DEVICE(obj);
230      TZPPC *s = TZ_PPC(obj);
231  
232      qdev_init_gpio_in_named(dev, tz_ppc_cfg_nonsec, "cfg_nonsec", TZ_NUM_PORTS);
233      qdev_init_gpio_in_named(dev, tz_ppc_cfg_ap, "cfg_ap", TZ_NUM_PORTS);
234      qdev_init_gpio_in_named(dev, tz_ppc_cfg_sec_resp, "cfg_sec_resp", 1);
235      qdev_init_gpio_in_named(dev, tz_ppc_irq_enable, "irq_enable", 1);
236      qdev_init_gpio_in_named(dev, tz_ppc_irq_clear, "irq_clear", 1);
237      qdev_init_gpio_out_named(dev, &s->irq, "irq", 1);
238  }
239  
tz_ppc_realize(DeviceState * dev,Error ** errp)240  static void tz_ppc_realize(DeviceState *dev, Error **errp)
241  {
242      Object *obj = OBJECT(dev);
243      SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
244      TZPPC *s = TZ_PPC(dev);
245      int i;
246      int max_port = 0;
247  
248      /* We can't create the upstream end of the port until realize,
249       * as we don't know the size of the MR used as the downstream until then.
250       */
251      for (i = 0; i < TZ_NUM_PORTS; i++) {
252          if (s->port[i].downstream) {
253              max_port = i;
254          }
255      }
256  
257      for (i = 0; i <= max_port; i++) {
258          TZPPCPort *port = &s->port[i];
259          char *name;
260          uint64_t size;
261  
262          if (!port->downstream) {
263              /*
264               * Create dummy sysbus MMIO region so the sysbus region
265               * numbering doesn't get out of sync with the port numbers.
266               * The size is entirely arbitrary.
267               */
268              name = g_strdup_printf("tz-ppc-dummy-port[%d]", i);
269              memory_region_init_io(&port->upstream, obj, &tz_ppc_dummy_ops,
270                                    port, name, 0x10000);
271              sysbus_init_mmio(sbd, &port->upstream);
272              g_free(name);
273              continue;
274          }
275  
276          name = g_strdup_printf("tz-ppc-port[%d]", i);
277  
278          port->ppc = s;
279          address_space_init(&port->downstream_as, port->downstream, name);
280  
281          size = memory_region_size(port->downstream);
282          memory_region_init_io(&port->upstream, obj, &tz_ppc_ops,
283                                port, name, size);
284          sysbus_init_mmio(sbd, &port->upstream);
285          g_free(name);
286      }
287  }
288  
289  static const VMStateDescription tz_ppc_vmstate = {
290      .name = "tz-ppc",
291      .version_id = 1,
292      .minimum_version_id = 1,
293      .fields = (const VMStateField[]) {
294          VMSTATE_BOOL_ARRAY(cfg_nonsec, TZPPC, 16),
295          VMSTATE_BOOL_ARRAY(cfg_ap, TZPPC, 16),
296          VMSTATE_BOOL(cfg_sec_resp, TZPPC),
297          VMSTATE_BOOL(irq_enable, TZPPC),
298          VMSTATE_BOOL(irq_clear, TZPPC),
299          VMSTATE_BOOL(irq_status, TZPPC),
300          VMSTATE_END_OF_LIST()
301      }
302  };
303  
304  #define DEFINE_PORT(N)                                          \
305      DEFINE_PROP_LINK("port[" #N "]", TZPPC, port[N].downstream, \
306                       TYPE_MEMORY_REGION, MemoryRegion *)
307  
308  static Property tz_ppc_properties[] = {
309      DEFINE_PROP_UINT32("NONSEC_MASK", TZPPC, nonsec_mask, 0),
310      DEFINE_PORT(0),
311      DEFINE_PORT(1),
312      DEFINE_PORT(2),
313      DEFINE_PORT(3),
314      DEFINE_PORT(4),
315      DEFINE_PORT(5),
316      DEFINE_PORT(6),
317      DEFINE_PORT(7),
318      DEFINE_PORT(8),
319      DEFINE_PORT(9),
320      DEFINE_PORT(10),
321      DEFINE_PORT(11),
322      DEFINE_PORT(12),
323      DEFINE_PORT(13),
324      DEFINE_PORT(14),
325      DEFINE_PORT(15),
326      DEFINE_PROP_END_OF_LIST(),
327  };
328  
tz_ppc_class_init(ObjectClass * klass,void * data)329  static void tz_ppc_class_init(ObjectClass *klass, void *data)
330  {
331      DeviceClass *dc = DEVICE_CLASS(klass);
332  
333      dc->realize = tz_ppc_realize;
334      dc->vmsd = &tz_ppc_vmstate;
335      device_class_set_legacy_reset(dc, tz_ppc_reset);
336      device_class_set_props(dc, tz_ppc_properties);
337  }
338  
339  static const TypeInfo tz_ppc_info = {
340      .name = TYPE_TZ_PPC,
341      .parent = TYPE_SYS_BUS_DEVICE,
342      .instance_size = sizeof(TZPPC),
343      .instance_init = tz_ppc_init,
344      .class_init = tz_ppc_class_init,
345  };
346  
tz_ppc_register_types(void)347  static void tz_ppc_register_types(void)
348  {
349      type_register_static(&tz_ppc_info);
350  }
351  
352  type_init(tz_ppc_register_types);
353