xref: /openbmc/qemu/hw/intc/slavio_intctl.c (revision 28ae3179fc52d2e4d870b635c4a412aab99759e7)
1  /*
2   * QEMU Sparc SLAVIO interrupt controller emulation
3   *
4   * Copyright (c) 2003-2005 Fabrice Bellard
5   *
6   * Permission is hereby granted, free of charge, to any person obtaining a copy
7   * of this software and associated documentation files (the "Software"), to deal
8   * in the Software without restriction, including without limitation the rights
9   * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10   * copies of the Software, and to permit persons to whom the Software is
11   * furnished to do so, subject to the following conditions:
12   *
13   * The above copyright notice and this permission notice shall be included in
14   * all copies or substantial portions of the Software.
15   *
16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19   * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22   * THE SOFTWARE.
23   */
24  
25  #include "qemu/osdep.h"
26  #include "migration/vmstate.h"
27  #include "qemu/module.h"
28  #include "hw/sysbus.h"
29  #include "hw/intc/intc.h"
30  #include "hw/irq.h"
31  #include "trace.h"
32  #include "qom/object.h"
33  
34  //#define DEBUG_IRQ_COUNT
35  
36  /*
37   * Registers of interrupt controller in sun4m.
38   *
39   * This is the interrupt controller part of chip STP2001 (Slave I/O), also
40   * produced as NCR89C105. See
41   * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
42   *
43   * There is a system master controller and one for each cpu.
44   *
45   */
46  
47  #define MAX_CPUS 16
48  #define MAX_PILS 16
49  
50  struct SLAVIO_INTCTLState;
51  
52  typedef struct SLAVIO_CPUINTCTLState {
53      MemoryRegion iomem;
54      struct SLAVIO_INTCTLState *master;
55      uint32_t intreg_pending;
56      uint32_t cpu;
57      uint32_t irl_out;
58  } SLAVIO_CPUINTCTLState;
59  
60  #define TYPE_SLAVIO_INTCTL "slavio_intctl"
61  OBJECT_DECLARE_SIMPLE_TYPE(SLAVIO_INTCTLState, SLAVIO_INTCTL)
62  
63  struct SLAVIO_INTCTLState {
64      SysBusDevice parent_obj;
65  
66      MemoryRegion iomem;
67  #ifdef DEBUG_IRQ_COUNT
68      uint64_t irq_count[32];
69  #endif
70      qemu_irq cpu_irqs[MAX_CPUS][MAX_PILS];
71      SLAVIO_CPUINTCTLState slaves[MAX_CPUS];
72      uint32_t intregm_pending;
73      uint32_t intregm_disabled;
74      uint32_t target_cpu;
75  };
76  
77  #define INTCTL_MAXADDR 0xf
78  #define INTCTL_SIZE (INTCTL_MAXADDR + 1)
79  #define INTCTLM_SIZE 0x14
80  #define MASTER_IRQ_MASK ~0x0fa2007f
81  #define MASTER_DISABLE 0x80000000
82  #define CPU_SOFTIRQ_MASK 0xfffe0000
83  #define CPU_IRQ_INT15_IN (1 << 15)
84  #define CPU_IRQ_TIMER_IN (1 << 14)
85  
86  static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs);
87  
88  // per-cpu interrupt controller
slavio_intctl_mem_readl(void * opaque,hwaddr addr,unsigned size)89  static uint64_t slavio_intctl_mem_readl(void *opaque, hwaddr addr,
90                                          unsigned size)
91  {
92      SLAVIO_CPUINTCTLState *s = opaque;
93      uint32_t saddr, ret;
94  
95      saddr = addr >> 2;
96      switch (saddr) {
97      case 0:
98          ret = s->intreg_pending;
99          break;
100      default:
101          ret = 0;
102          break;
103      }
104      trace_slavio_intctl_mem_readl(s->cpu, addr, ret);
105  
106      return ret;
107  }
108  
slavio_intctl_mem_writel(void * opaque,hwaddr addr,uint64_t val,unsigned size)109  static void slavio_intctl_mem_writel(void *opaque, hwaddr addr,
110                                       uint64_t val, unsigned size)
111  {
112      SLAVIO_CPUINTCTLState *s = opaque;
113      uint32_t saddr;
114  
115      saddr = addr >> 2;
116      trace_slavio_intctl_mem_writel(s->cpu, addr, val);
117      switch (saddr) {
118      case 1: // clear pending softints
119          val &= CPU_SOFTIRQ_MASK | CPU_IRQ_INT15_IN;
120          s->intreg_pending &= ~val;
121          slavio_check_interrupts(s->master, 1);
122          trace_slavio_intctl_mem_writel_clear(s->cpu, val, s->intreg_pending);
123          break;
124      case 2: // set softint
125          val &= CPU_SOFTIRQ_MASK;
126          s->intreg_pending |= val;
127          slavio_check_interrupts(s->master, 1);
128          trace_slavio_intctl_mem_writel_set(s->cpu, val, s->intreg_pending);
129          break;
130      default:
131          break;
132      }
133  }
134  
135  static const MemoryRegionOps slavio_intctl_mem_ops = {
136      .read = slavio_intctl_mem_readl,
137      .write = slavio_intctl_mem_writel,
138      .endianness = DEVICE_NATIVE_ENDIAN,
139      .valid = {
140          .min_access_size = 4,
141          .max_access_size = 4,
142      },
143  };
144  
145  // master system interrupt controller
slavio_intctlm_mem_readl(void * opaque,hwaddr addr,unsigned size)146  static uint64_t slavio_intctlm_mem_readl(void *opaque, hwaddr addr,
147                                           unsigned size)
148  {
149      SLAVIO_INTCTLState *s = opaque;
150      uint32_t saddr, ret;
151  
152      saddr = addr >> 2;
153      switch (saddr) {
154      case 0:
155          ret = s->intregm_pending & ~MASTER_DISABLE;
156          break;
157      case 1:
158          ret = s->intregm_disabled & MASTER_IRQ_MASK;
159          break;
160      case 4:
161          ret = s->target_cpu;
162          break;
163      default:
164          ret = 0;
165          break;
166      }
167      trace_slavio_intctlm_mem_readl(addr, ret);
168  
169      return ret;
170  }
171  
slavio_intctlm_mem_writel(void * opaque,hwaddr addr,uint64_t val,unsigned size)172  static void slavio_intctlm_mem_writel(void *opaque, hwaddr addr,
173                                        uint64_t val, unsigned size)
174  {
175      SLAVIO_INTCTLState *s = opaque;
176      uint32_t saddr;
177  
178      saddr = addr >> 2;
179      trace_slavio_intctlm_mem_writel(addr, val);
180      switch (saddr) {
181      case 2: // clear (enable)
182          // Force clear unused bits
183          val &= MASTER_IRQ_MASK;
184          s->intregm_disabled &= ~val;
185          trace_slavio_intctlm_mem_writel_enable(val, s->intregm_disabled);
186          slavio_check_interrupts(s, 1);
187          break;
188      case 3: // set (disable; doesn't affect pending)
189          // Force clear unused bits
190          val &= MASTER_IRQ_MASK;
191          s->intregm_disabled |= val;
192          slavio_check_interrupts(s, 1);
193          trace_slavio_intctlm_mem_writel_disable(val, s->intregm_disabled);
194          break;
195      case 4:
196          s->target_cpu = val & (MAX_CPUS - 1);
197          slavio_check_interrupts(s, 1);
198          trace_slavio_intctlm_mem_writel_target(s->target_cpu);
199          break;
200      default:
201          break;
202      }
203  }
204  
205  static const MemoryRegionOps slavio_intctlm_mem_ops = {
206      .read = slavio_intctlm_mem_readl,
207      .write = slavio_intctlm_mem_writel,
208      .endianness = DEVICE_NATIVE_ENDIAN,
209      .valid = {
210          .min_access_size = 4,
211          .max_access_size = 4,
212      },
213  };
214  
215  static const uint32_t intbit_to_level[] = {
216      2, 3, 5, 7, 9, 11, 13, 2,   3, 5, 7, 9, 11, 13, 12, 12,
217      6, 13, 4, 10, 8, 9, 11, 0,  0, 0, 0, 15, 15, 15, 15, 0,
218  };
219  
slavio_check_interrupts(SLAVIO_INTCTLState * s,int set_irqs)220  static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
221  {
222      uint32_t pending = s->intregm_pending, pil_pending;
223      unsigned int i, j;
224  
225      pending &= ~s->intregm_disabled;
226  
227      trace_slavio_check_interrupts(pending, s->intregm_disabled);
228      for (i = 0; i < MAX_CPUS; i++) {
229          pil_pending = 0;
230  
231          /* If we are the current interrupt target, get hard interrupts */
232          if (pending && !(s->intregm_disabled & MASTER_DISABLE) &&
233              (i == s->target_cpu)) {
234              for (j = 0; j < 32; j++) {
235                  if ((pending & (1 << j)) && intbit_to_level[j]) {
236                      pil_pending |= 1 << intbit_to_level[j];
237                  }
238              }
239          }
240  
241          /* Calculate current pending hard interrupts for display */
242          s->slaves[i].intreg_pending &= CPU_SOFTIRQ_MASK | CPU_IRQ_INT15_IN |
243              CPU_IRQ_TIMER_IN;
244          if (i == s->target_cpu) {
245              for (j = 0; j < 32; j++) {
246                  if ((s->intregm_pending & (1U << j)) && intbit_to_level[j]) {
247                      s->slaves[i].intreg_pending |= 1 << intbit_to_level[j];
248                  }
249              }
250          }
251  
252          /* Level 15 and CPU timer interrupts are only masked when
253             the MASTER_DISABLE bit is set */
254          if (!(s->intregm_disabled & MASTER_DISABLE)) {
255              pil_pending |= s->slaves[i].intreg_pending &
256                  (CPU_IRQ_INT15_IN | CPU_IRQ_TIMER_IN);
257          }
258  
259          /* Add soft interrupts */
260          pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
261  
262          if (set_irqs) {
263              /* Since there is not really an interrupt 0 (and pil_pending
264               * and irl_out bit zero are thus always zero) there is no need
265               * to do anything with cpu_irqs[i][0] and it is OK not to do
266               * the j=0 iteration of this loop.
267               */
268              for (j = MAX_PILS-1; j > 0; j--) {
269                  if (pil_pending & (1 << j)) {
270                      if (!(s->slaves[i].irl_out & (1 << j))) {
271                          qemu_irq_raise(s->cpu_irqs[i][j]);
272                      }
273                  } else {
274                      if (s->slaves[i].irl_out & (1 << j)) {
275                          qemu_irq_lower(s->cpu_irqs[i][j]);
276                      }
277                  }
278              }
279          }
280          s->slaves[i].irl_out = pil_pending;
281      }
282  }
283  
284  /*
285   * "irq" here is the bit number in the system interrupt register to
286   * separate serial and keyboard interrupts sharing a level.
287   */
slavio_set_irq(void * opaque,int irq,int level)288  static void slavio_set_irq(void *opaque, int irq, int level)
289  {
290      SLAVIO_INTCTLState *s = opaque;
291      uint32_t mask = 1 << irq;
292      uint32_t pil = intbit_to_level[irq];
293      unsigned int i;
294  
295      trace_slavio_set_irq(s->target_cpu, irq, pil, level);
296      if (pil > 0) {
297          if (level) {
298  #ifdef DEBUG_IRQ_COUNT
299              s->irq_count[pil]++;
300  #endif
301              s->intregm_pending |= mask;
302              if (pil == 15) {
303                  for (i = 0; i < MAX_CPUS; i++) {
304                      s->slaves[i].intreg_pending |= 1 << pil;
305                  }
306              }
307          } else {
308              s->intregm_pending &= ~mask;
309              if (pil == 15) {
310                  for (i = 0; i < MAX_CPUS; i++) {
311                      s->slaves[i].intreg_pending &= ~(1 << pil);
312                  }
313              }
314          }
315          slavio_check_interrupts(s, 1);
316      }
317  }
318  
slavio_set_timer_irq_cpu(void * opaque,int cpu,int level)319  static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
320  {
321      SLAVIO_INTCTLState *s = opaque;
322  
323      trace_slavio_set_timer_irq_cpu(cpu, level);
324  
325      if (level) {
326          s->slaves[cpu].intreg_pending |= CPU_IRQ_TIMER_IN;
327      } else {
328          s->slaves[cpu].intreg_pending &= ~CPU_IRQ_TIMER_IN;
329      }
330  
331      slavio_check_interrupts(s, 1);
332  }
333  
slavio_set_irq_all(void * opaque,int irq,int level)334  static void slavio_set_irq_all(void *opaque, int irq, int level)
335  {
336      if (irq < 32) {
337          slavio_set_irq(opaque, irq, level);
338      } else {
339          slavio_set_timer_irq_cpu(opaque, irq - 32, level);
340      }
341  }
342  
vmstate_intctl_post_load(void * opaque,int version_id)343  static int vmstate_intctl_post_load(void *opaque, int version_id)
344  {
345      SLAVIO_INTCTLState *s = opaque;
346  
347      slavio_check_interrupts(s, 0);
348      return 0;
349  }
350  
351  static const VMStateDescription vmstate_intctl_cpu = {
352      .name ="slavio_intctl_cpu",
353      .version_id = 1,
354      .minimum_version_id = 1,
355      .fields = (const VMStateField[]) {
356          VMSTATE_UINT32(intreg_pending, SLAVIO_CPUINTCTLState),
357          VMSTATE_END_OF_LIST()
358      }
359  };
360  
361  static const VMStateDescription vmstate_intctl = {
362      .name ="slavio_intctl",
363      .version_id = 1,
364      .minimum_version_id = 1,
365      .post_load = vmstate_intctl_post_load,
366      .fields = (const VMStateField[]) {
367          VMSTATE_STRUCT_ARRAY(slaves, SLAVIO_INTCTLState, MAX_CPUS, 1,
368                               vmstate_intctl_cpu, SLAVIO_CPUINTCTLState),
369          VMSTATE_UINT32(intregm_pending, SLAVIO_INTCTLState),
370          VMSTATE_UINT32(intregm_disabled, SLAVIO_INTCTLState),
371          VMSTATE_UINT32(target_cpu, SLAVIO_INTCTLState),
372          VMSTATE_END_OF_LIST()
373      }
374  };
375  
slavio_intctl_reset(DeviceState * d)376  static void slavio_intctl_reset(DeviceState *d)
377  {
378      SLAVIO_INTCTLState *s = SLAVIO_INTCTL(d);
379      int i;
380  
381      for (i = 0; i < MAX_CPUS; i++) {
382          s->slaves[i].intreg_pending = 0;
383          s->slaves[i].irl_out = 0;
384      }
385      s->intregm_disabled = ~MASTER_IRQ_MASK;
386      s->intregm_pending = 0;
387      s->target_cpu = 0;
388      slavio_check_interrupts(s, 0);
389  }
390  
391  #ifdef DEBUG_IRQ_COUNT
slavio_intctl_get_statistics(InterruptStatsProvider * obj,uint64_t ** irq_counts,unsigned int * nb_irqs)392  static bool slavio_intctl_get_statistics(InterruptStatsProvider *obj,
393                                           uint64_t **irq_counts,
394                                           unsigned int *nb_irqs)
395  {
396      SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj);
397      *irq_counts = s->irq_count;
398      *nb_irqs = ARRAY_SIZE(s->irq_count);
399      return true;
400  }
401  #endif
402  
slavio_intctl_print_info(InterruptStatsProvider * obj,GString * buf)403  static void slavio_intctl_print_info(InterruptStatsProvider *obj, GString *buf)
404  {
405      SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj);
406      int i;
407  
408      for (i = 0; i < MAX_CPUS; i++) {
409          g_string_append_printf(buf, "per-cpu %d: pending 0x%08x\n", i,
410                                 s->slaves[i].intreg_pending);
411      }
412      g_string_append_printf(buf, "master: pending 0x%08x, disabled 0x%08x\n",
413                             s->intregm_pending, s->intregm_disabled);
414  }
415  
slavio_intctl_init(Object * obj)416  static void slavio_intctl_init(Object *obj)
417  {
418      DeviceState *dev = DEVICE(obj);
419      SLAVIO_INTCTLState *s = SLAVIO_INTCTL(obj);
420      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
421      unsigned int i, j;
422      char slave_name[45];
423  
424      qdev_init_gpio_in(dev, slavio_set_irq_all, 32 + MAX_CPUS);
425      memory_region_init_io(&s->iomem, obj, &slavio_intctlm_mem_ops, s,
426                            "master-interrupt-controller", INTCTLM_SIZE);
427      sysbus_init_mmio(sbd, &s->iomem);
428  
429      for (i = 0; i < MAX_CPUS; i++) {
430          snprintf(slave_name, sizeof(slave_name),
431                   "slave-interrupt-controller-%i", i);
432          for (j = 0; j < MAX_PILS; j++) {
433              sysbus_init_irq(sbd, &s->cpu_irqs[i][j]);
434          }
435          memory_region_init_io(&s->slaves[i].iomem, OBJECT(s),
436                                &slavio_intctl_mem_ops,
437                                &s->slaves[i], slave_name, INTCTL_SIZE);
438          sysbus_init_mmio(sbd, &s->slaves[i].iomem);
439          s->slaves[i].cpu = i;
440          s->slaves[i].master = s;
441      }
442  }
443  
slavio_intctl_class_init(ObjectClass * klass,void * data)444  static void slavio_intctl_class_init(ObjectClass *klass, void *data)
445  {
446      DeviceClass *dc = DEVICE_CLASS(klass);
447      InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(klass);
448  
449      device_class_set_legacy_reset(dc, slavio_intctl_reset);
450      dc->vmsd = &vmstate_intctl;
451  #ifdef DEBUG_IRQ_COUNT
452      ic->get_statistics = slavio_intctl_get_statistics;
453  #endif
454      ic->print_info = slavio_intctl_print_info;
455  }
456  
457  static const TypeInfo slavio_intctl_info = {
458      .name          = TYPE_SLAVIO_INTCTL,
459      .parent        = TYPE_SYS_BUS_DEVICE,
460      .instance_size = sizeof(SLAVIO_INTCTLState),
461      .instance_init = slavio_intctl_init,
462      .class_init    = slavio_intctl_class_init,
463      .interfaces = (InterfaceInfo[]) {
464          { TYPE_INTERRUPT_STATS_PROVIDER },
465          { }
466      },
467  };
468  
slavio_intctl_register_types(void)469  static void slavio_intctl_register_types(void)
470  {
471      type_register_static(&slavio_intctl_info);
472  }
473  
474  type_init(slavio_intctl_register_types)
475