Fix interrupt controller address masking
[qemu] / hw / slavio_intctl.c
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 #include "vl.h"
25 //#define DEBUG_IRQ_COUNT
26 //#define DEBUG_IRQ
27
28 #ifdef DEBUG_IRQ
29 #define DPRINTF(fmt, args...) \
30 do { printf("IRQ: " fmt , ##args); } while (0)
31 #else
32 #define DPRINTF(fmt, args...)
33 #endif
34
35 /*
36  * Registers of interrupt controller in sun4m.
37  *
38  * This is the interrupt controller part of chip STP2001 (Slave I/O), also
39  * produced as NCR89C105. See
40  * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
41  *
42  * There is a system master controller and one for each cpu.
43  * 
44  */
45
46 #define MAX_CPUS 16
47
48 typedef struct SLAVIO_INTCTLState {
49     uint32_t intreg_pending[MAX_CPUS];
50     uint32_t intregm_pending;
51     uint32_t intregm_disabled;
52     uint32_t target_cpu;
53 #ifdef DEBUG_IRQ_COUNT
54     uint64_t irq_count[32];
55 #endif
56     CPUState *cpu_envs[MAX_CPUS];
57     const uint32_t *intbit_to_level;
58 } SLAVIO_INTCTLState;
59
60 #define INTCTL_MAXADDR 0xf
61 #define INTCTLM_MAXADDR 0x13
62 #define INTCTLM_MASK 0x1f
63 static void slavio_check_interrupts(void *opaque);
64
65 // per-cpu interrupt controller
66 static uint32_t slavio_intctl_mem_readl(void *opaque, target_phys_addr_t addr)
67 {
68     SLAVIO_INTCTLState *s = opaque;
69     uint32_t saddr;
70     int cpu;
71
72     cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
73     saddr = (addr & INTCTL_MAXADDR) >> 2;
74     switch (saddr) {
75     case 0:
76         return s->intreg_pending[cpu];
77     default:
78         break;
79     }
80     return 0;
81 }
82
83 static void slavio_intctl_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
84 {
85     SLAVIO_INTCTLState *s = opaque;
86     uint32_t saddr;
87     int cpu;
88
89     cpu = (addr & (MAX_CPUS - 1) * TARGET_PAGE_SIZE) >> 12;
90     saddr = (addr & INTCTL_MAXADDR) >> 2;
91     switch (saddr) {
92     case 1: // clear pending softints
93         if (val & 0x4000)
94             val |= 80000000;
95         val &= 0xfffe0000;
96         s->intreg_pending[cpu] &= ~val;
97         DPRINTF("Cleared cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
98         break;
99     case 2: // set softint
100         val &= 0xfffe0000;
101         s->intreg_pending[cpu] |= val;
102         slavio_check_interrupts(s);
103         DPRINTF("Set cpu %d irq mask %x, curmask %x\n", cpu, val, s->intreg_pending[cpu]);
104         break;
105     default:
106         break;
107     }
108 }
109
110 static CPUReadMemoryFunc *slavio_intctl_mem_read[3] = {
111     slavio_intctl_mem_readl,
112     slavio_intctl_mem_readl,
113     slavio_intctl_mem_readl,
114 };
115
116 static CPUWriteMemoryFunc *slavio_intctl_mem_write[3] = {
117     slavio_intctl_mem_writel,
118     slavio_intctl_mem_writel,
119     slavio_intctl_mem_writel,
120 };
121
122 // master system interrupt controller
123 static uint32_t slavio_intctlm_mem_readl(void *opaque, target_phys_addr_t addr)
124 {
125     SLAVIO_INTCTLState *s = opaque;
126     uint32_t saddr;
127
128     saddr = (addr & INTCTLM_MAXADDR) >> 2;
129     switch (saddr) {
130     case 0:
131         return s->intregm_pending & 0x7fffffff;
132     case 1:
133         return s->intregm_disabled;
134     case 4:
135         return s->target_cpu;
136     default:
137         break;
138     }
139     return 0;
140 }
141
142 static void slavio_intctlm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
143 {
144     SLAVIO_INTCTLState *s = opaque;
145     uint32_t saddr;
146
147     saddr = (addr & INTCTLM_MASK) >> 2;
148     switch (saddr) {
149     case 2: // clear (enable)
150         // Force clear unused bits
151         val &= ~0x4fb2007f;
152         s->intregm_disabled &= ~val;
153         DPRINTF("Enabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
154         slavio_check_interrupts(s);
155         break;
156     case 3: // set (disable, clear pending)
157         // Force clear unused bits
158         val &= ~0x4fb2007f;
159         s->intregm_disabled |= val;
160         s->intregm_pending &= ~val;
161         DPRINTF("Disabled master irq mask %x, curmask %x\n", val, s->intregm_disabled);
162         break;
163     case 4:
164         s->target_cpu = val & (MAX_CPUS - 1);
165         DPRINTF("Set master irq cpu %d\n", s->target_cpu);
166         break;
167     default:
168         break;
169     }
170 }
171
172 static CPUReadMemoryFunc *slavio_intctlm_mem_read[3] = {
173     slavio_intctlm_mem_readl,
174     slavio_intctlm_mem_readl,
175     slavio_intctlm_mem_readl,
176 };
177
178 static CPUWriteMemoryFunc *slavio_intctlm_mem_write[3] = {
179     slavio_intctlm_mem_writel,
180     slavio_intctlm_mem_writel,
181     slavio_intctlm_mem_writel,
182 };
183
184 void slavio_pic_info(void *opaque)
185 {
186     SLAVIO_INTCTLState *s = opaque;
187     int i;
188
189     for (i = 0; i < MAX_CPUS; i++) {
190         term_printf("per-cpu %d: pending 0x%08x\n", i, s->intreg_pending[i]);
191     }
192     term_printf("master: pending 0x%08x, disabled 0x%08x\n", s->intregm_pending, s->intregm_disabled);
193 }
194
195 void slavio_irq_info(void *opaque)
196 {
197 #ifndef DEBUG_IRQ_COUNT
198     term_printf("irq statistic code not compiled.\n");
199 #else
200     SLAVIO_INTCTLState *s = opaque;
201     int i;
202     int64_t count;
203
204     term_printf("IRQ statistics:\n");
205     for (i = 0; i < 32; i++) {
206         count = s->irq_count[i];
207         if (count > 0)
208             term_printf("%2d: %" PRId64 "\n", i, count);
209     }
210 #endif
211 }
212
213 static void slavio_check_interrupts(void *opaque)
214 {
215     CPUState *env;
216     SLAVIO_INTCTLState *s = opaque;
217     uint32_t pending = s->intregm_pending;
218     unsigned int i, j, max = 0;
219
220     pending &= ~s->intregm_disabled;
221
222     if (pending && !(s->intregm_disabled & 0x80000000)) {
223         for (i = 0; i < 32; i++) {
224             if (pending & (1 << i)) {
225                 if (max < s->intbit_to_level[i])
226                     max = s->intbit_to_level[i];
227             }
228         }
229         env = s->cpu_envs[s->target_cpu];
230         if (!env) {
231             DPRINTF("No CPU %d, not triggered (pending %x)\n", s->target_cpu, pending);
232         }
233         else {
234             if (env->halted)
235                 env->halted = 0;
236             if (env->interrupt_index == 0) {
237                 DPRINTF("Triggered CPU %d pil %d\n", s->target_cpu, max);
238 #ifdef DEBUG_IRQ_COUNT
239                 s->irq_count[max]++;
240 #endif
241                 env->interrupt_index = TT_EXTINT | max;
242                 cpu_interrupt(env, CPU_INTERRUPT_HARD);
243             }
244             else
245                 DPRINTF("Not triggered (pending %x), pending exception %x\n", pending, env->interrupt_index);
246         }
247     }
248     else
249         DPRINTF("Not triggered (pending %x), disabled %x\n", pending, s->intregm_disabled);
250     
251     for (i = 0; i < MAX_CPUS; i++) {
252         max = 0;
253         env = s->cpu_envs[i];
254         if (!env)
255             continue;
256         for (j = 17; j < 32; j++) {
257             if (s->intreg_pending[i] & (1 << j)) {
258                 if (max < j - 16)
259                     max = j - 16;
260             }
261         }
262         if (max > 0) {
263             if (env->halted)
264                 env->halted = 0;
265             if (env->interrupt_index == 0) {
266                 DPRINTF("Triggered softint %d for cpu %d (pending %x)\n", max, i, pending);
267 #ifdef DEBUG_IRQ_COUNT
268                 s->irq_count[max]++;
269 #endif
270                 env->interrupt_index = TT_EXTINT | max;
271                 cpu_interrupt(env, CPU_INTERRUPT_HARD);
272             }
273         }
274     }
275 }
276
277 /*
278  * "irq" here is the bit number in the system interrupt register to
279  * separate serial and keyboard interrupts sharing a level.
280  */
281 void slavio_set_irq(void *opaque, int irq, int level)
282 {
283     SLAVIO_INTCTLState *s = opaque;
284
285     DPRINTF("Set cpu %d irq %d level %d\n", s->target_cpu, irq, level);
286     if (irq < 32) {
287         uint32_t mask = 1 << irq;
288         uint32_t pil = s->intbit_to_level[irq];
289         if (pil > 0) {
290             if (level) {
291                 s->intregm_pending |= mask;
292                 s->intreg_pending[s->target_cpu] |= 1 << pil;
293                 slavio_check_interrupts(s);
294             }
295             else {
296                 s->intregm_pending &= ~mask;
297                 s->intreg_pending[s->target_cpu] &= ~(1 << pil);
298             }
299         }
300     }
301 }
302
303 void pic_set_irq_cpu(void *opaque, int irq, int level, unsigned int cpu)
304 {
305     SLAVIO_INTCTLState *s = opaque;
306
307     DPRINTF("Set cpu %d local irq %d level %d\n", cpu, irq, level);
308     if (cpu == (unsigned int)-1) {
309         slavio_set_irq(opaque, irq, level);
310         return;
311     }
312     if (irq < 32) {
313         uint32_t pil = s->intbit_to_level[irq];
314         if (pil > 0) {
315             if (level) {
316                 s->intreg_pending[cpu] |= 1 << pil;
317             }
318             else {
319                 s->intreg_pending[cpu] &= ~(1 << pil);
320             }
321         }
322     }
323     slavio_check_interrupts(s);
324 }
325
326 static void slavio_intctl_save(QEMUFile *f, void *opaque)
327 {
328     SLAVIO_INTCTLState *s = opaque;
329     int i;
330     
331     for (i = 0; i < MAX_CPUS; i++) {
332         qemu_put_be32s(f, &s->intreg_pending[i]);
333     }
334     qemu_put_be32s(f, &s->intregm_pending);
335     qemu_put_be32s(f, &s->intregm_disabled);
336     qemu_put_be32s(f, &s->target_cpu);
337 }
338
339 static int slavio_intctl_load(QEMUFile *f, void *opaque, int version_id)
340 {
341     SLAVIO_INTCTLState *s = opaque;
342     int i;
343
344     if (version_id != 1)
345         return -EINVAL;
346
347     for (i = 0; i < MAX_CPUS; i++) {
348         qemu_get_be32s(f, &s->intreg_pending[i]);
349     }
350     qemu_get_be32s(f, &s->intregm_pending);
351     qemu_get_be32s(f, &s->intregm_disabled);
352     qemu_get_be32s(f, &s->target_cpu);
353     return 0;
354 }
355
356 static void slavio_intctl_reset(void *opaque)
357 {
358     SLAVIO_INTCTLState *s = opaque;
359     int i;
360
361     for (i = 0; i < MAX_CPUS; i++) {
362         s->intreg_pending[i] = 0;
363     }
364     s->intregm_disabled = ~0xffb2007f;
365     s->intregm_pending = 0;
366     s->target_cpu = 0;
367 }
368
369 void slavio_intctl_set_cpu(void *opaque, unsigned int cpu, CPUState *env)
370 {
371     SLAVIO_INTCTLState *s = opaque;
372     s->cpu_envs[cpu] = env;
373 }
374
375 void *slavio_intctl_init(target_phys_addr_t addr, target_phys_addr_t addrg,
376                          const uint32_t *intbit_to_level,
377                          qemu_irq **irq)
378 {
379     int slavio_intctl_io_memory, slavio_intctlm_io_memory, i;
380     SLAVIO_INTCTLState *s;
381
382     s = qemu_mallocz(sizeof(SLAVIO_INTCTLState));
383     if (!s)
384         return NULL;
385
386     s->intbit_to_level = intbit_to_level;
387     for (i = 0; i < MAX_CPUS; i++) {
388         slavio_intctl_io_memory = cpu_register_io_memory(0, slavio_intctl_mem_read, slavio_intctl_mem_write, s);
389         cpu_register_physical_memory(addr + i * TARGET_PAGE_SIZE, INTCTL_MAXADDR, slavio_intctl_io_memory);
390     }
391
392     slavio_intctlm_io_memory = cpu_register_io_memory(0, slavio_intctlm_mem_read, slavio_intctlm_mem_write, s);
393     cpu_register_physical_memory(addrg, INTCTLM_MAXADDR, slavio_intctlm_io_memory);
394
395     register_savevm("slavio_intctl", addr, 1, slavio_intctl_save, slavio_intctl_load, s);
396     qemu_register_reset(slavio_intctl_reset, s);
397     *irq = qemu_allocate_irqs(slavio_set_irq, s, 32);
398     slavio_intctl_reset(s);
399     return s;
400 }
401