]> git.proxmox.com Git - qemu.git/blame - hw/slavio_intctl.c
monitor: move include files to include/monitor/
[qemu.git] / hw / slavio_intctl.c
CommitLineData
e80cfcfc
FB
1/*
2 * QEMU Sparc SLAVIO interrupt controller emulation
5fafdf24 3 *
66321a11 4 * Copyright (c) 2003-2005 Fabrice Bellard
5fafdf24 5 *
e80cfcfc
FB
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 */
a1961a4b 24
87ecb68b 25#include "sun4m.h"
83c9089e 26#include "monitor/monitor.h"
a1961a4b 27#include "sysbus.h"
97bf4851 28#include "trace.h"
87ecb68b 29
e80cfcfc
FB
30//#define DEBUG_IRQ_COUNT
31
32/*
33 * Registers of interrupt controller in sun4m.
34 *
35 * This is the interrupt controller part of chip STP2001 (Slave I/O), also
36 * produced as NCR89C105. See
37 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
38 *
39 * There is a system master controller and one for each cpu.
5fafdf24 40 *
e80cfcfc
FB
41 */
42
43#define MAX_CPUS 16
b3a23197 44#define MAX_PILS 16
e80cfcfc 45
a1961a4b
BS
46struct SLAVIO_INTCTLState;
47
48typedef struct SLAVIO_CPUINTCTLState {
8bb5ef33 49 MemoryRegion iomem;
a1961a4b 50 struct SLAVIO_INTCTLState *master;
07dd0035 51 uint32_t intreg_pending;
a1961a4b 52 uint32_t cpu;
462eda24 53 uint32_t irl_out;
a1961a4b 54} SLAVIO_CPUINTCTLState;
a8f48dcc 55
e80cfcfc 56typedef struct SLAVIO_INTCTLState {
a1961a4b 57 SysBusDevice busdev;
13c89a11 58 MemoryRegion iomem;
e80cfcfc
FB
59#ifdef DEBUG_IRQ_COUNT
60 uint64_t irq_count[32];
61#endif
a1961a4b 62 qemu_irq cpu_irqs[MAX_CPUS][MAX_PILS];
a1961a4b 63 SLAVIO_CPUINTCTLState slaves[MAX_CPUS];
07dd0035
BS
64 uint32_t intregm_pending;
65 uint32_t intregm_disabled;
66 uint32_t target_cpu;
e80cfcfc
FB
67} SLAVIO_INTCTLState;
68
69#define INTCTL_MAXADDR 0xf
5aca8c3b 70#define INTCTL_SIZE (INTCTL_MAXADDR + 1)
a8f48dcc 71#define INTCTLM_SIZE 0x14
80be36b8 72#define MASTER_IRQ_MASK ~0x0fa2007f
9a87ce9b 73#define MASTER_DISABLE 0x80000000
6341fdcb 74#define CPU_SOFTIRQ_MASK 0xfffe0000
462eda24
BS
75#define CPU_IRQ_INT15_IN (1 << 15)
76#define CPU_IRQ_TIMER_IN (1 << 14)
9a87ce9b 77
0d0a7e69 78static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs);
e80cfcfc
FB
79
80// per-cpu interrupt controller
a8170e5e 81static uint64_t slavio_intctl_mem_readl(void *opaque, hwaddr addr,
8bb5ef33 82 unsigned size)
e80cfcfc 83{
a8f48dcc 84 SLAVIO_CPUINTCTLState *s = opaque;
dd4131b3 85 uint32_t saddr, ret;
e80cfcfc 86
a8f48dcc 87 saddr = addr >> 2;
e80cfcfc
FB
88 switch (saddr) {
89 case 0:
a8f48dcc 90 ret = s->intreg_pending;
dd4131b3 91 break;
e80cfcfc 92 default:
dd4131b3
BS
93 ret = 0;
94 break;
e80cfcfc 95 }
97bf4851 96 trace_slavio_intctl_mem_readl(s->cpu, addr, ret);
dd4131b3
BS
97
98 return ret;
e80cfcfc
FB
99}
100
a8170e5e 101static void slavio_intctl_mem_writel(void *opaque, hwaddr addr,
8bb5ef33 102 uint64_t val, unsigned size)
e80cfcfc 103{
a8f48dcc 104 SLAVIO_CPUINTCTLState *s = opaque;
e80cfcfc 105 uint32_t saddr;
e80cfcfc 106
a8f48dcc 107 saddr = addr >> 2;
97bf4851 108 trace_slavio_intctl_mem_writel(s->cpu, addr, val);
e80cfcfc
FB
109 switch (saddr) {
110 case 1: // clear pending softints
462eda24 111 val &= CPU_SOFTIRQ_MASK | CPU_IRQ_INT15_IN;
a8f48dcc 112 s->intreg_pending &= ~val;
0d0a7e69 113 slavio_check_interrupts(s->master, 1);
97bf4851 114 trace_slavio_intctl_mem_writel_clear(s->cpu, val, s->intreg_pending);
f930d07e 115 break;
e80cfcfc 116 case 2: // set softint
6341fdcb 117 val &= CPU_SOFTIRQ_MASK;
a8f48dcc 118 s->intreg_pending |= val;
0d0a7e69 119 slavio_check_interrupts(s->master, 1);
97bf4851 120 trace_slavio_intctl_mem_writel_set(s->cpu, val, s->intreg_pending);
f930d07e 121 break;
e80cfcfc 122 default:
f930d07e 123 break;
e80cfcfc
FB
124 }
125}
126
8bb5ef33
BC
127static const MemoryRegionOps slavio_intctl_mem_ops = {
128 .read = slavio_intctl_mem_readl,
129 .write = slavio_intctl_mem_writel,
130 .endianness = DEVICE_NATIVE_ENDIAN,
131 .valid = {
132 .min_access_size = 4,
133 .max_access_size = 4,
134 },
e80cfcfc
FB
135};
136
137// master system interrupt controller
a8170e5e 138static uint64_t slavio_intctlm_mem_readl(void *opaque, hwaddr addr,
13c89a11 139 unsigned size)
e80cfcfc
FB
140{
141 SLAVIO_INTCTLState *s = opaque;
dd4131b3 142 uint32_t saddr, ret;
e80cfcfc 143
a8f48dcc 144 saddr = addr >> 2;
e80cfcfc
FB
145 switch (saddr) {
146 case 0:
9a87ce9b 147 ret = s->intregm_pending & ~MASTER_DISABLE;
dd4131b3 148 break;
e80cfcfc 149 case 1:
80be36b8 150 ret = s->intregm_disabled & MASTER_IRQ_MASK;
dd4131b3 151 break;
e80cfcfc 152 case 4:
dd4131b3
BS
153 ret = s->target_cpu;
154 break;
e80cfcfc 155 default:
dd4131b3
BS
156 ret = 0;
157 break;
e80cfcfc 158 }
97bf4851 159 trace_slavio_intctlm_mem_readl(addr, ret);
dd4131b3
BS
160
161 return ret;
e80cfcfc
FB
162}
163
a8170e5e 164static void slavio_intctlm_mem_writel(void *opaque, hwaddr addr,
13c89a11 165 uint64_t val, unsigned size)
e80cfcfc
FB
166{
167 SLAVIO_INTCTLState *s = opaque;
168 uint32_t saddr;
169
a8f48dcc 170 saddr = addr >> 2;
97bf4851 171 trace_slavio_intctlm_mem_writel(addr, val);
e80cfcfc
FB
172 switch (saddr) {
173 case 2: // clear (enable)
f930d07e 174 // Force clear unused bits
9a87ce9b 175 val &= MASTER_IRQ_MASK;
f930d07e 176 s->intregm_disabled &= ~val;
97bf4851 177 trace_slavio_intctlm_mem_writel_enable(val, s->intregm_disabled);
0d0a7e69 178 slavio_check_interrupts(s, 1);
f930d07e 179 break;
10760f0f 180 case 3: // set (disable; doesn't affect pending)
f930d07e 181 // Force clear unused bits
9a87ce9b 182 val &= MASTER_IRQ_MASK;
f930d07e 183 s->intregm_disabled |= val;
0d0a7e69 184 slavio_check_interrupts(s, 1);
97bf4851 185 trace_slavio_intctlm_mem_writel_disable(val, s->intregm_disabled);
f930d07e 186 break;
e80cfcfc 187 case 4:
f930d07e 188 s->target_cpu = val & (MAX_CPUS - 1);
0d0a7e69 189 slavio_check_interrupts(s, 1);
97bf4851 190 trace_slavio_intctlm_mem_writel_target(s->target_cpu);
f930d07e 191 break;
e80cfcfc 192 default:
f930d07e 193 break;
e80cfcfc
FB
194 }
195}
196
13c89a11
BC
197static const MemoryRegionOps slavio_intctlm_mem_ops = {
198 .read = slavio_intctlm_mem_readl,
199 .write = slavio_intctlm_mem_writel,
200 .endianness = DEVICE_NATIVE_ENDIAN,
201 .valid = {
202 .min_access_size = 4,
203 .max_access_size = 4,
204 },
e80cfcfc
FB
205};
206
d453c2c3 207void slavio_pic_info(Monitor *mon, DeviceState *dev)
e80cfcfc 208{
d453c2c3
BS
209 SysBusDevice *sd;
210 SLAVIO_INTCTLState *s;
e80cfcfc
FB
211 int i;
212
d453c2c3
BS
213 sd = sysbus_from_qdev(dev);
214 s = FROM_SYSBUS(SLAVIO_INTCTLState, sd);
e80cfcfc 215 for (i = 0; i < MAX_CPUS; i++) {
376253ec 216 monitor_printf(mon, "per-cpu %d: pending 0x%08x\n", i,
a1961a4b 217 s->slaves[i].intreg_pending);
e80cfcfc 218 }
376253ec
AL
219 monitor_printf(mon, "master: pending 0x%08x, disabled 0x%08x\n",
220 s->intregm_pending, s->intregm_disabled);
e80cfcfc
FB
221}
222
d453c2c3 223void slavio_irq_info(Monitor *mon, DeviceState *dev)
e80cfcfc
FB
224{
225#ifndef DEBUG_IRQ_COUNT
376253ec 226 monitor_printf(mon, "irq statistic code not compiled.\n");
e80cfcfc 227#else
d453c2c3
BS
228 SysBusDevice *sd;
229 SLAVIO_INTCTLState *s;
e80cfcfc
FB
230 int i;
231 int64_t count;
232
d453c2c3
BS
233 sd = sysbus_from_qdev(dev);
234 s = FROM_SYSBUS(SLAVIO_INTCTLState, sd);
376253ec 235 monitor_printf(mon, "IRQ statistics:\n");
e80cfcfc
FB
236 for (i = 0; i < 32; i++) {
237 count = s->irq_count[i];
238 if (count > 0)
376253ec 239 monitor_printf(mon, "%2d: %" PRId64 "\n", i, count);
e80cfcfc
FB
240 }
241#endif
242}
243
68556e2e 244static const uint32_t intbit_to_level[] = {
462eda24
BS
245 2, 3, 5, 7, 9, 11, 13, 2, 3, 5, 7, 9, 11, 13, 12, 12,
246 6, 13, 4, 10, 8, 9, 11, 0, 0, 0, 0, 15, 15, 15, 15, 0,
68556e2e
BS
247};
248
0d0a7e69 249static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
66321a11 250{
327ac2e7
BS
251 uint32_t pending = s->intregm_pending, pil_pending;
252 unsigned int i, j;
66321a11
FB
253
254 pending &= ~s->intregm_disabled;
255
97bf4851 256 trace_slavio_check_interrupts(pending, s->intregm_disabled);
ba3c64fb 257 for (i = 0; i < MAX_CPUS; i++) {
327ac2e7 258 pil_pending = 0;
462eda24
BS
259
260 /* If we are the current interrupt target, get hard interrupts */
9a87ce9b 261 if (pending && !(s->intregm_disabled & MASTER_DISABLE) &&
b3a23197
BS
262 (i == s->target_cpu)) {
263 for (j = 0; j < 32; j++) {
462eda24 264 if ((pending & (1 << j)) && intbit_to_level[j]) {
68556e2e 265 pil_pending |= 1 << intbit_to_level[j];
462eda24
BS
266 }
267 }
268 }
269
270 /* Calculate current pending hard interrupts for display */
271 s->slaves[i].intreg_pending &= CPU_SOFTIRQ_MASK | CPU_IRQ_INT15_IN |
272 CPU_IRQ_TIMER_IN;
273 if (i == s->target_cpu) {
274 for (j = 0; j < 32; j++) {
275 if ((s->intregm_pending & (1 << j)) && intbit_to_level[j]) {
276 s->slaves[i].intreg_pending |= 1 << intbit_to_level[j];
277 }
b3a23197
BS
278 }
279 }
462eda24 280
94c5f455
AT
281 /* Level 15 and CPU timer interrupts are only masked when
282 the MASTER_DISABLE bit is set */
283 if (!(s->intregm_disabled & MASTER_DISABLE)) {
284 pil_pending |= s->slaves[i].intreg_pending &
285 (CPU_IRQ_INT15_IN | CPU_IRQ_TIMER_IN);
286 }
462eda24
BS
287
288 /* Add soft interrupts */
a1961a4b 289 pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
327ac2e7 290
0d0a7e69 291 if (set_irqs) {
c84a88d8
PM
292 /* Since there is not really an interrupt 0 (and pil_pending
293 * and irl_out bit zero are thus always zero) there is no need
294 * to do anything with cpu_irqs[i][0] and it is OK not to do
295 * the j=0 iteration of this loop.
296 */
297 for (j = MAX_PILS-1; j > 0; j--) {
0d0a7e69 298 if (pil_pending & (1 << j)) {
462eda24 299 if (!(s->slaves[i].irl_out & (1 << j))) {
0d0a7e69
BS
300 qemu_irq_raise(s->cpu_irqs[i][j]);
301 }
302 } else {
462eda24 303 if (s->slaves[i].irl_out & (1 << j)) {
0d0a7e69
BS
304 qemu_irq_lower(s->cpu_irqs[i][j]);
305 }
306 }
ba3c64fb
FB
307 }
308 }
462eda24 309 s->slaves[i].irl_out = pil_pending;
ba3c64fb 310 }
66321a11
FB
311}
312
e80cfcfc
FB
313/*
314 * "irq" here is the bit number in the system interrupt register to
315 * separate serial and keyboard interrupts sharing a level.
316 */
d7edfd27 317static void slavio_set_irq(void *opaque, int irq, int level)
e80cfcfc
FB
318{
319 SLAVIO_INTCTLState *s = opaque;
b3a23197 320 uint32_t mask = 1 << irq;
68556e2e 321 uint32_t pil = intbit_to_level[irq];
462eda24 322 unsigned int i;
b3a23197 323
97bf4851 324 trace_slavio_set_irq(s->target_cpu, irq, pil, level);
b3a23197
BS
325 if (pil > 0) {
326 if (level) {
327ac2e7
BS
327#ifdef DEBUG_IRQ_COUNT
328 s->irq_count[pil]++;
329#endif
b3a23197 330 s->intregm_pending |= mask;
462eda24
BS
331 if (pil == 15) {
332 for (i = 0; i < MAX_CPUS; i++) {
333 s->slaves[i].intreg_pending |= 1 << pil;
334 }
335 }
b3a23197
BS
336 } else {
337 s->intregm_pending &= ~mask;
462eda24
BS
338 if (pil == 15) {
339 for (i = 0; i < MAX_CPUS; i++) {
340 s->slaves[i].intreg_pending &= ~(1 << pil);
341 }
342 }
b3a23197 343 }
0d0a7e69 344 slavio_check_interrupts(s, 1);
e80cfcfc
FB
345 }
346}
347
d7edfd27 348static void slavio_set_timer_irq_cpu(void *opaque, int cpu, int level)
ba3c64fb
FB
349{
350 SLAVIO_INTCTLState *s = opaque;
351
97bf4851 352 trace_slavio_set_timer_irq_cpu(cpu, level);
d7edfd27 353
e3a79bca 354 if (level) {
462eda24 355 s->slaves[cpu].intreg_pending |= CPU_IRQ_TIMER_IN;
e3a79bca 356 } else {
462eda24 357 s->slaves[cpu].intreg_pending &= ~CPU_IRQ_TIMER_IN;
e3a79bca 358 }
d7edfd27 359
0d0a7e69 360 slavio_check_interrupts(s, 1);
ba3c64fb
FB
361}
362
a1961a4b
BS
363static void slavio_set_irq_all(void *opaque, int irq, int level)
364{
365 if (irq < 32) {
366 slavio_set_irq(opaque, irq, level);
367 } else {
368 slavio_set_timer_irq_cpu(opaque, irq - 32, level);
369 }
370}
371
e59fb374 372static int vmstate_intctl_post_load(void *opaque, int version_id)
e80cfcfc
FB
373{
374 SLAVIO_INTCTLState *s = opaque;
3b46e624 375
c9e95029
BS
376 slavio_check_interrupts(s, 0);
377 return 0;
e80cfcfc
FB
378}
379
c9e95029
BS
380static const VMStateDescription vmstate_intctl_cpu = {
381 .name ="slavio_intctl_cpu",
382 .version_id = 1,
383 .minimum_version_id = 1,
384 .minimum_version_id_old = 1,
385 .fields = (VMStateField []) {
386 VMSTATE_UINT32(intreg_pending, SLAVIO_CPUINTCTLState),
387 VMSTATE_END_OF_LIST()
388 }
389};
e80cfcfc 390
c9e95029
BS
391static const VMStateDescription vmstate_intctl = {
392 .name ="slavio_intctl",
393 .version_id = 1,
394 .minimum_version_id = 1,
395 .minimum_version_id_old = 1,
752ff2fa 396 .post_load = vmstate_intctl_post_load,
c9e95029
BS
397 .fields = (VMStateField []) {
398 VMSTATE_STRUCT_ARRAY(slaves, SLAVIO_INTCTLState, MAX_CPUS, 1,
399 vmstate_intctl_cpu, SLAVIO_CPUINTCTLState),
400 VMSTATE_UINT32(intregm_pending, SLAVIO_INTCTLState),
401 VMSTATE_UINT32(intregm_disabled, SLAVIO_INTCTLState),
402 VMSTATE_UINT32(target_cpu, SLAVIO_INTCTLState),
403 VMSTATE_END_OF_LIST()
e80cfcfc 404 }
c9e95029 405};
e80cfcfc 406
78971d57 407static void slavio_intctl_reset(DeviceState *d)
e80cfcfc 408{
78971d57 409 SLAVIO_INTCTLState *s = container_of(d, SLAVIO_INTCTLState, busdev.qdev);
e80cfcfc
FB
410 int i;
411
412 for (i = 0; i < MAX_CPUS; i++) {
a1961a4b 413 s->slaves[i].intreg_pending = 0;
462eda24 414 s->slaves[i].irl_out = 0;
e80cfcfc 415 }
9a87ce9b 416 s->intregm_disabled = ~MASTER_IRQ_MASK;
e80cfcfc
FB
417 s->intregm_pending = 0;
418 s->target_cpu = 0;
0d0a7e69 419 slavio_check_interrupts(s, 0);
e80cfcfc
FB
420}
421
81a322d4 422static int slavio_intctl_init1(SysBusDevice *dev)
e80cfcfc 423{
a1961a4b 424 SLAVIO_INTCTLState *s = FROM_SYSBUS(SLAVIO_INTCTLState, dev);
a1961a4b 425 unsigned int i, j;
8bb5ef33 426 char slave_name[45];
e80cfcfc 427
a1961a4b 428 qdev_init_gpio_in(&dev->qdev, slavio_set_irq_all, 32 + MAX_CPUS);
13c89a11
BC
429 memory_region_init_io(&s->iomem, &slavio_intctlm_mem_ops, s,
430 "master-interrupt-controller", INTCTLM_SIZE);
750ecd44 431 sysbus_init_mmio(dev, &s->iomem);
e80cfcfc
FB
432
433 for (i = 0; i < MAX_CPUS; i++) {
8bb5ef33
BC
434 snprintf(slave_name, sizeof(slave_name),
435 "slave-interrupt-controller-%i", i);
a1961a4b
BS
436 for (j = 0; j < MAX_PILS; j++) {
437 sysbus_init_irq(dev, &s->cpu_irqs[i][j]);
438 }
8bb5ef33
BC
439 memory_region_init_io(&s->slaves[i].iomem, &slavio_intctl_mem_ops,
440 &s->slaves[i], slave_name, INTCTL_SIZE);
750ecd44 441 sysbus_init_mmio(dev, &s->slaves[i].iomem);
a1961a4b
BS
442 s->slaves[i].cpu = i;
443 s->slaves[i].master = s;
444 }
78971d57 445
81a322d4 446 return 0;
a1961a4b
BS
447}
448
999e12bb
AL
449static void slavio_intctl_class_init(ObjectClass *klass, void *data)
450{
39bffca2 451 DeviceClass *dc = DEVICE_CLASS(klass);
999e12bb
AL
452 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
453
454 k->init = slavio_intctl_init1;
39bffca2
AL
455 dc->reset = slavio_intctl_reset;
456 dc->vmsd = &vmstate_intctl;
999e12bb
AL
457}
458
39bffca2
AL
459static TypeInfo slavio_intctl_info = {
460 .name = "slavio_intctl",
461 .parent = TYPE_SYS_BUS_DEVICE,
462 .instance_size = sizeof(SLAVIO_INTCTLState),
463 .class_init = slavio_intctl_class_init,
a1961a4b 464};
d7edfd27 465
83f7d43a 466static void slavio_intctl_register_types(void)
a1961a4b 467{
39bffca2 468 type_register_static(&slavio_intctl_info);
e80cfcfc 469}
a1961a4b 470
83f7d43a 471type_init(slavio_intctl_register_types)