]> Git Repo - qemu.git/blame - hw/arm_gic.c
arm: make the number of GIC interrupts configurable
[qemu.git] / hw / arm_gic.c
CommitLineData
5fafdf24 1/*
9ee6e8bb 2 * ARM Generic/Distributed Interrupt Controller
e69954b9 3 *
9ee6e8bb 4 * Copyright (c) 2006-2007 CodeSourcery.
e69954b9
PB
5 * Written by Paul Brook
6 *
8e31bf38 7 * This code is licensed under the GPL.
e69954b9
PB
8 */
9
9ee6e8bb
PB
10/* This file contains implementation code for the RealView EB interrupt
11 controller, MPCore distributed interrupt controller and ARMv7-M
12 Nested Vectored Interrupt Controller. */
e69954b9 13
a32134aa
ML
14/* Maximum number of possible interrupts, determined by the GIC architecture */
15#define GIC_MAXIRQ 1020
e69954b9
PB
16//#define DEBUG_GIC
17
18#ifdef DEBUG_GIC
001faf32
BS
19#define DPRINTF(fmt, ...) \
20do { printf("arm_gic: " fmt , ## __VA_ARGS__); } while (0)
e69954b9 21#else
001faf32 22#define DPRINTF(fmt, ...) do {} while(0)
e69954b9
PB
23#endif
24
9ee6e8bb
PB
25#ifdef NVIC
26static const uint8_t gic_id[] =
27{ 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1 };
9ee6e8bb
PB
28/* The NVIC has 16 internal vectors. However these are not exposed
29 through the normal GIC interface. */
30#define GIC_BASE_IRQ 32
31#else
e69954b9
PB
32static const uint8_t gic_id[] =
33{ 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
9ee6e8bb
PB
34#define GIC_BASE_IRQ 0
35#endif
e69954b9 36
fe7e8758
PB
37#define FROM_SYSBUSGIC(type, dev) \
38 DO_UPCAST(type, gic, FROM_SYSBUS(gic_state, dev))
39
e69954b9
PB
40typedef struct gic_irq_state
41{
41bf234d
RV
42 /* The enable bits are only banked for per-cpu interrupts. */
43 unsigned enabled:NCPU;
9ee6e8bb
PB
44 unsigned pending:NCPU;
45 unsigned active:NCPU;
a45db6c6 46 unsigned level:NCPU;
9ee6e8bb 47 unsigned model:1; /* 0 = N:N, 1 = 1:N */
e69954b9
PB
48 unsigned trigger:1; /* nonzero = edge triggered. */
49} gic_irq_state;
50
9ee6e8bb 51#define ALL_CPU_MASK ((1 << NCPU) - 1)
c988bfad
PB
52#if NCPU > 1
53#define NUM_CPU(s) ((s)->num_cpu)
54#else
55#define NUM_CPU(s) 1
56#endif
9ee6e8bb 57
41bf234d
RV
58#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
59#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
60#define GIC_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
9ee6e8bb
PB
61#define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
62#define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
63#define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
64#define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
65#define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
66#define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
e69954b9
PB
67#define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
68#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
69#define GIC_TEST_MODEL(irq) s->irq_state[irq].model
9ee6e8bb
PB
70#define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
71#define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
57d69a91 72#define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
e69954b9
PB
73#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
74#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
75#define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
9ee6e8bb
PB
76#define GIC_GET_PRIORITY(irq, cpu) \
77 (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
78#ifdef NVIC
79#define GIC_TARGET(irq) 1
80#else
81#define GIC_TARGET(irq) s->irq_target[irq]
82#endif
e69954b9
PB
83
84typedef struct gic_state
85{
fe7e8758 86 SysBusDevice busdev;
9ee6e8bb 87 qemu_irq parent_irq[NCPU];
e69954b9 88 int enabled;
9ee6e8bb 89 int cpu_enabled[NCPU];
e69954b9 90
a32134aa 91 gic_irq_state irq_state[GIC_MAXIRQ];
9ee6e8bb 92#ifndef NVIC
a32134aa 93 int irq_target[GIC_MAXIRQ];
9ee6e8bb
PB
94#endif
95 int priority1[32][NCPU];
a32134aa
ML
96 int priority2[GIC_MAXIRQ - 32];
97 int last_active[GIC_MAXIRQ][NCPU];
9ee6e8bb
PB
98
99 int priority_mask[NCPU];
100 int running_irq[NCPU];
101 int running_priority[NCPU];
102 int current_pending[NCPU];
103
c988bfad
PB
104#if NCPU > 1
105 int num_cpu;
106#endif
107
e2c56465
PM
108 MemoryRegion iomem; /* Distributor */
109#ifndef NVIC
110 /* This is just so we can have an opaque pointer which identifies
111 * both this GIC and which CPU interface we should be accessing.
112 */
113 struct gic_state *backref[NCPU];
114 MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
115#endif
a32134aa 116 uint32_t num_irq;
e69954b9
PB
117} gic_state;
118
119/* TODO: Many places that call this routine could be optimized. */
120/* Update interrupt status after enabled or pending bits have been changed. */
121static void gic_update(gic_state *s)
122{
123 int best_irq;
124 int best_prio;
125 int irq;
9ee6e8bb
PB
126 int level;
127 int cpu;
128 int cm;
129
c988bfad 130 for (cpu = 0; cpu < NUM_CPU(s); cpu++) {
9ee6e8bb
PB
131 cm = 1 << cpu;
132 s->current_pending[cpu] = 1023;
133 if (!s->enabled || !s->cpu_enabled[cpu]) {
134 qemu_irq_lower(s->parent_irq[cpu]);
135 return;
136 }
137 best_prio = 0x100;
138 best_irq = 1023;
a32134aa 139 for (irq = 0; irq < s->num_irq; irq++) {
41bf234d 140 if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
9ee6e8bb
PB
141 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
142 best_prio = GIC_GET_PRIORITY(irq, cpu);
143 best_irq = irq;
144 }
e69954b9
PB
145 }
146 }
9ee6e8bb
PB
147 level = 0;
148 if (best_prio <= s->priority_mask[cpu]) {
149 s->current_pending[cpu] = best_irq;
150 if (best_prio < s->running_priority[cpu]) {
151 DPRINTF("Raised pending IRQ %d\n", best_irq);
152 level = 1;
153 }
e69954b9 154 }
9ee6e8bb 155 qemu_set_irq(s->parent_irq[cpu], level);
e69954b9
PB
156 }
157}
158
9ee6e8bb
PB
159static void __attribute__((unused))
160gic_set_pending_private(gic_state *s, int cpu, int irq)
161{
162 int cm = 1 << cpu;
163
164 if (GIC_TEST_PENDING(irq, cm))
165 return;
166
167 DPRINTF("Set %d pending cpu %d\n", irq, cpu);
168 GIC_SET_PENDING(irq, cm);
169 gic_update(s);
170}
171
172/* Process a change in an external IRQ input. */
e69954b9
PB
173static void gic_set_irq(void *opaque, int irq, int level)
174{
175 gic_state *s = (gic_state *)opaque;
176 /* The first external input line is internal interrupt 32. */
177 irq += 32;
9ee6e8bb 178 if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
e69954b9
PB
179 return;
180
181 if (level) {
9ee6e8bb 182 GIC_SET_LEVEL(irq, ALL_CPU_MASK);
41bf234d 183 if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, ALL_CPU_MASK)) {
9ee6e8bb
PB
184 DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
185 GIC_SET_PENDING(irq, GIC_TARGET(irq));
e69954b9
PB
186 }
187 } else {
9ee6e8bb 188 GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
e69954b9
PB
189 }
190 gic_update(s);
191}
192
9ee6e8bb 193static void gic_set_running_irq(gic_state *s, int cpu, int irq)
e69954b9 194{
9ee6e8bb
PB
195 s->running_irq[cpu] = irq;
196 if (irq == 1023) {
197 s->running_priority[cpu] = 0x100;
198 } else {
199 s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu);
200 }
e69954b9
PB
201 gic_update(s);
202}
203
9ee6e8bb 204static uint32_t gic_acknowledge_irq(gic_state *s, int cpu)
e69954b9
PB
205{
206 int new_irq;
9ee6e8bb
PB
207 int cm = 1 << cpu;
208 new_irq = s->current_pending[cpu];
209 if (new_irq == 1023
210 || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) {
e69954b9
PB
211 DPRINTF("ACK no pending IRQ\n");
212 return 1023;
213 }
9ee6e8bb
PB
214 s->last_active[new_irq][cpu] = s->running_irq[cpu];
215 /* Clear pending flags for both level and edge triggered interrupts.
216 Level triggered IRQs will be reasserted once they become inactive. */
217 GIC_CLEAR_PENDING(new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm);
218 gic_set_running_irq(s, cpu, new_irq);
e69954b9
PB
219 DPRINTF("ACK %d\n", new_irq);
220 return new_irq;
221}
222
9ee6e8bb 223static void gic_complete_irq(gic_state * s, int cpu, int irq)
e69954b9
PB
224{
225 int update = 0;
9ee6e8bb 226 int cm = 1 << cpu;
df628ff1 227 DPRINTF("EOI %d\n", irq);
a32134aa 228 if (irq >= s->num_irq) {
217bfb44
PM
229 /* This handles two cases:
230 * 1. If software writes the ID of a spurious interrupt [ie 1023]
231 * to the GICC_EOIR, the GIC ignores that write.
232 * 2. If software writes the number of a non-existent interrupt
233 * this must be a subcase of "value written does not match the last
234 * valid interrupt value read from the Interrupt Acknowledge
235 * register" and so this is UNPREDICTABLE. We choose to ignore it.
236 */
237 return;
238 }
9ee6e8bb 239 if (s->running_irq[cpu] == 1023)
e69954b9 240 return; /* No active IRQ. */
217bfb44
PM
241 /* Mark level triggered interrupts as pending if they are still
242 raised. */
243 if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
244 && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
245 DPRINTF("Set %d pending mask %x\n", irq, cm);
246 GIC_SET_PENDING(irq, cm);
247 update = 1;
e69954b9 248 }
9ee6e8bb 249 if (irq != s->running_irq[cpu]) {
e69954b9 250 /* Complete an IRQ that is not currently running. */
9ee6e8bb
PB
251 int tmp = s->running_irq[cpu];
252 while (s->last_active[tmp][cpu] != 1023) {
253 if (s->last_active[tmp][cpu] == irq) {
254 s->last_active[tmp][cpu] = s->last_active[irq][cpu];
e69954b9
PB
255 break;
256 }
9ee6e8bb 257 tmp = s->last_active[tmp][cpu];
e69954b9
PB
258 }
259 if (update) {
260 gic_update(s);
261 }
262 } else {
263 /* Complete the current running IRQ. */
9ee6e8bb 264 gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]);
e69954b9
PB
265 }
266}
267
c227f099 268static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
e69954b9
PB
269{
270 gic_state *s = (gic_state *)opaque;
271 uint32_t res;
272 int irq;
273 int i;
9ee6e8bb
PB
274 int cpu;
275 int cm;
276 int mask;
e69954b9 277
9ee6e8bb
PB
278 cpu = gic_get_current_cpu();
279 cm = 1 << cpu;
e69954b9 280 if (offset < 0x100) {
9ee6e8bb 281#ifndef NVIC
e69954b9
PB
282 if (offset == 0)
283 return s->enabled;
284 if (offset == 4)
a32134aa 285 return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
e69954b9
PB
286 if (offset < 0x08)
287 return 0;
b79f2265
RH
288 if (offset >= 0x80) {
289 /* Interrupt Security , RAZ/WI */
290 return 0;
291 }
9ee6e8bb 292#endif
e69954b9
PB
293 goto bad_reg;
294 } else if (offset < 0x200) {
295 /* Interrupt Set/Clear Enable. */
296 if (offset < 0x180)
297 irq = (offset - 0x100) * 8;
298 else
299 irq = (offset - 0x180) * 8;
9ee6e8bb 300 irq += GIC_BASE_IRQ;
a32134aa 301 if (irq >= s->num_irq)
e69954b9
PB
302 goto bad_reg;
303 res = 0;
304 for (i = 0; i < 8; i++) {
41bf234d 305 if (GIC_TEST_ENABLED(irq + i, cm)) {
e69954b9
PB
306 res |= (1 << i);
307 }
308 }
309 } else if (offset < 0x300) {
310 /* Interrupt Set/Clear Pending. */
311 if (offset < 0x280)
312 irq = (offset - 0x200) * 8;
313 else
314 irq = (offset - 0x280) * 8;
9ee6e8bb 315 irq += GIC_BASE_IRQ;
a32134aa 316 if (irq >= s->num_irq)
e69954b9
PB
317 goto bad_reg;
318 res = 0;
9ee6e8bb 319 mask = (irq < 32) ? cm : ALL_CPU_MASK;
e69954b9 320 for (i = 0; i < 8; i++) {
9ee6e8bb 321 if (GIC_TEST_PENDING(irq + i, mask)) {
e69954b9
PB
322 res |= (1 << i);
323 }
324 }
325 } else if (offset < 0x400) {
326 /* Interrupt Active. */
9ee6e8bb 327 irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
a32134aa 328 if (irq >= s->num_irq)
e69954b9
PB
329 goto bad_reg;
330 res = 0;
9ee6e8bb 331 mask = (irq < 32) ? cm : ALL_CPU_MASK;
e69954b9 332 for (i = 0; i < 8; i++) {
9ee6e8bb 333 if (GIC_TEST_ACTIVE(irq + i, mask)) {
e69954b9
PB
334 res |= (1 << i);
335 }
336 }
337 } else if (offset < 0x800) {
338 /* Interrupt Priority. */
9ee6e8bb 339 irq = (offset - 0x400) + GIC_BASE_IRQ;
a32134aa 340 if (irq >= s->num_irq)
e69954b9 341 goto bad_reg;
9ee6e8bb
PB
342 res = GIC_GET_PRIORITY(irq, cpu);
343#ifndef NVIC
e69954b9
PB
344 } else if (offset < 0xc00) {
345 /* Interrupt CPU Target. */
9ee6e8bb 346 irq = (offset - 0x800) + GIC_BASE_IRQ;
a32134aa 347 if (irq >= s->num_irq)
e69954b9 348 goto bad_reg;
9ee6e8bb
PB
349 if (irq >= 29 && irq <= 31) {
350 res = cm;
351 } else {
352 res = GIC_TARGET(irq);
353 }
e69954b9
PB
354 } else if (offset < 0xf00) {
355 /* Interrupt Configuration. */
9ee6e8bb 356 irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
a32134aa 357 if (irq >= s->num_irq)
e69954b9
PB
358 goto bad_reg;
359 res = 0;
360 for (i = 0; i < 4; i++) {
361 if (GIC_TEST_MODEL(irq + i))
362 res |= (1 << (i * 2));
363 if (GIC_TEST_TRIGGER(irq + i))
364 res |= (2 << (i * 2));
365 }
9ee6e8bb 366#endif
e69954b9
PB
367 } else if (offset < 0xfe0) {
368 goto bad_reg;
369 } else /* offset >= 0xfe0 */ {
370 if (offset & 3) {
371 res = 0;
372 } else {
373 res = gic_id[(offset - 0xfe0) >> 2];
374 }
375 }
376 return res;
377bad_reg:
2ac71179 378 hw_error("gic_dist_readb: Bad offset %x\n", (int)offset);
e69954b9
PB
379 return 0;
380}
381
c227f099 382static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset)
e69954b9
PB
383{
384 uint32_t val;
385 val = gic_dist_readb(opaque, offset);
386 val |= gic_dist_readb(opaque, offset + 1) << 8;
387 return val;
388}
389
c227f099 390static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
e69954b9
PB
391{
392 uint32_t val;
9ee6e8bb
PB
393#ifdef NVIC
394 gic_state *s = (gic_state *)opaque;
395 uint32_t addr;
8da3ff18 396 addr = offset;
9ee6e8bb 397 if (addr < 0x100 || addr > 0xd00)
fe7e8758 398 return nvic_readl(s, addr);
9ee6e8bb 399#endif
e69954b9
PB
400 val = gic_dist_readw(opaque, offset);
401 val |= gic_dist_readw(opaque, offset + 2) << 16;
402 return val;
403}
404
c227f099 405static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
e69954b9
PB
406 uint32_t value)
407{
408 gic_state *s = (gic_state *)opaque;
409 int irq;
410 int i;
9ee6e8bb 411 int cpu;
e69954b9 412
9ee6e8bb 413 cpu = gic_get_current_cpu();
e69954b9 414 if (offset < 0x100) {
9ee6e8bb
PB
415#ifdef NVIC
416 goto bad_reg;
417#else
e69954b9
PB
418 if (offset == 0) {
419 s->enabled = (value & 1);
420 DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
421 } else if (offset < 4) {
422 /* ignored. */
b79f2265
RH
423 } else if (offset >= 0x80) {
424 /* Interrupt Security Registers, RAZ/WI */
e69954b9
PB
425 } else {
426 goto bad_reg;
427 }
9ee6e8bb 428#endif
e69954b9
PB
429 } else if (offset < 0x180) {
430 /* Interrupt Set Enable. */
9ee6e8bb 431 irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
a32134aa 432 if (irq >= s->num_irq)
e69954b9 433 goto bad_reg;
9ee6e8bb
PB
434 if (irq < 16)
435 value = 0xff;
e69954b9
PB
436 for (i = 0; i < 8; i++) {
437 if (value & (1 << i)) {
9ee6e8bb 438 int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
41bf234d
RV
439 int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
440
441 if (!GIC_TEST_ENABLED(irq + i, cm)) {
e69954b9 442 DPRINTF("Enabled IRQ %d\n", irq + i);
41bf234d
RV
443 }
444 GIC_SET_ENABLED(irq + i, cm);
e69954b9
PB
445 /* If a raised level triggered IRQ enabled then mark
446 is as pending. */
9ee6e8bb
PB
447 if (GIC_TEST_LEVEL(irq + i, mask)
448 && !GIC_TEST_TRIGGER(irq + i)) {
449 DPRINTF("Set %d pending mask %x\n", irq + i, mask);
450 GIC_SET_PENDING(irq + i, mask);
451 }
e69954b9
PB
452 }
453 }
454 } else if (offset < 0x200) {
455 /* Interrupt Clear Enable. */
9ee6e8bb 456 irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
a32134aa 457 if (irq >= s->num_irq)
e69954b9 458 goto bad_reg;
9ee6e8bb
PB
459 if (irq < 16)
460 value = 0;
e69954b9
PB
461 for (i = 0; i < 8; i++) {
462 if (value & (1 << i)) {
41bf234d
RV
463 int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
464
465 if (GIC_TEST_ENABLED(irq + i, cm)) {
e69954b9 466 DPRINTF("Disabled IRQ %d\n", irq + i);
41bf234d
RV
467 }
468 GIC_CLEAR_ENABLED(irq + i, cm);
e69954b9
PB
469 }
470 }
471 } else if (offset < 0x280) {
472 /* Interrupt Set Pending. */
9ee6e8bb 473 irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
a32134aa 474 if (irq >= s->num_irq)
e69954b9 475 goto bad_reg;
9ee6e8bb
PB
476 if (irq < 16)
477 irq = 0;
478
e69954b9
PB
479 for (i = 0; i < 8; i++) {
480 if (value & (1 << i)) {
9ee6e8bb 481 GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
e69954b9
PB
482 }
483 }
484 } else if (offset < 0x300) {
485 /* Interrupt Clear Pending. */
9ee6e8bb 486 irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
a32134aa 487 if (irq >= s->num_irq)
e69954b9
PB
488 goto bad_reg;
489 for (i = 0; i < 8; i++) {
9ee6e8bb
PB
490 /* ??? This currently clears the pending bit for all CPUs, even
491 for per-CPU interrupts. It's unclear whether this is the
492 corect behavior. */
e69954b9 493 if (value & (1 << i)) {
9ee6e8bb 494 GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
e69954b9
PB
495 }
496 }
497 } else if (offset < 0x400) {
498 /* Interrupt Active. */
499 goto bad_reg;
500 } else if (offset < 0x800) {
501 /* Interrupt Priority. */
9ee6e8bb 502 irq = (offset - 0x400) + GIC_BASE_IRQ;
a32134aa 503 if (irq >= s->num_irq)
e69954b9 504 goto bad_reg;
9ee6e8bb
PB
505 if (irq < 32) {
506 s->priority1[irq][cpu] = value;
507 } else {
508 s->priority2[irq - 32] = value;
509 }
510#ifndef NVIC
e69954b9
PB
511 } else if (offset < 0xc00) {
512 /* Interrupt CPU Target. */
9ee6e8bb 513 irq = (offset - 0x800) + GIC_BASE_IRQ;
a32134aa 514 if (irq >= s->num_irq)
e69954b9 515 goto bad_reg;
9ee6e8bb
PB
516 if (irq < 29)
517 value = 0;
518 else if (irq < 32)
519 value = ALL_CPU_MASK;
520 s->irq_target[irq] = value & ALL_CPU_MASK;
e69954b9
PB
521 } else if (offset < 0xf00) {
522 /* Interrupt Configuration. */
9ee6e8bb 523 irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
a32134aa 524 if (irq >= s->num_irq)
e69954b9 525 goto bad_reg;
9ee6e8bb
PB
526 if (irq < 32)
527 value |= 0xaa;
e69954b9
PB
528 for (i = 0; i < 4; i++) {
529 if (value & (1 << (i * 2))) {
530 GIC_SET_MODEL(irq + i);
531 } else {
532 GIC_CLEAR_MODEL(irq + i);
533 }
534 if (value & (2 << (i * 2))) {
535 GIC_SET_TRIGGER(irq + i);
536 } else {
537 GIC_CLEAR_TRIGGER(irq + i);
538 }
539 }
9ee6e8bb 540#endif
e69954b9 541 } else {
9ee6e8bb 542 /* 0xf00 is only handled for 32-bit writes. */
e69954b9
PB
543 goto bad_reg;
544 }
545 gic_update(s);
546 return;
547bad_reg:
2ac71179 548 hw_error("gic_dist_writeb: Bad offset %x\n", (int)offset);
e69954b9
PB
549}
550
c227f099 551static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
e69954b9
PB
552 uint32_t value)
553{
e69954b9
PB
554 gic_dist_writeb(opaque, offset, value & 0xff);
555 gic_dist_writeb(opaque, offset + 1, value >> 8);
556}
557
c227f099 558static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
e69954b9
PB
559 uint32_t value)
560{
9ee6e8bb
PB
561 gic_state *s = (gic_state *)opaque;
562#ifdef NVIC
563 uint32_t addr;
8da3ff18 564 addr = offset;
9ee6e8bb 565 if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) {
fe7e8758 566 nvic_writel(s, addr, value);
9ee6e8bb
PB
567 return;
568 }
569#endif
8da3ff18 570 if (offset == 0xf00) {
9ee6e8bb
PB
571 int cpu;
572 int irq;
573 int mask;
574
575 cpu = gic_get_current_cpu();
576 irq = value & 0x3ff;
577 switch ((value >> 24) & 3) {
578 case 0:
579 mask = (value >> 16) & ALL_CPU_MASK;
580 break;
581 case 1:
fa250144 582 mask = ALL_CPU_MASK ^ (1 << cpu);
9ee6e8bb
PB
583 break;
584 case 2:
fa250144 585 mask = 1 << cpu;
9ee6e8bb
PB
586 break;
587 default:
588 DPRINTF("Bad Soft Int target filter\n");
589 mask = ALL_CPU_MASK;
590 break;
591 }
592 GIC_SET_PENDING(irq, mask);
593 gic_update(s);
594 return;
595 }
e69954b9
PB
596 gic_dist_writew(opaque, offset, value & 0xffff);
597 gic_dist_writew(opaque, offset + 2, value >> 16);
598}
599
755c0802
AK
600static const MemoryRegionOps gic_dist_ops = {
601 .old_mmio = {
602 .read = { gic_dist_readb, gic_dist_readw, gic_dist_readl, },
603 .write = { gic_dist_writeb, gic_dist_writew, gic_dist_writel, },
604 },
605 .endianness = DEVICE_NATIVE_ENDIAN,
e69954b9
PB
606};
607
9ee6e8bb
PB
608#ifndef NVIC
609static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset)
e69954b9 610{
e69954b9
PB
611 switch (offset) {
612 case 0x00: /* Control */
9ee6e8bb 613 return s->cpu_enabled[cpu];
e69954b9 614 case 0x04: /* Priority mask */
9ee6e8bb 615 return s->priority_mask[cpu];
e69954b9
PB
616 case 0x08: /* Binary Point */
617 /* ??? Not implemented. */
618 return 0;
619 case 0x0c: /* Acknowledge */
9ee6e8bb 620 return gic_acknowledge_irq(s, cpu);
66a0a2cb 621 case 0x14: /* Running Priority */
9ee6e8bb 622 return s->running_priority[cpu];
e69954b9 623 case 0x18: /* Highest Pending Interrupt */
9ee6e8bb 624 return s->current_pending[cpu];
e69954b9 625 default:
2ac71179 626 hw_error("gic_cpu_read: Bad offset %x\n", (int)offset);
e69954b9
PB
627 return 0;
628 }
629}
630
9ee6e8bb 631static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
e69954b9 632{
e69954b9
PB
633 switch (offset) {
634 case 0x00: /* Control */
9ee6e8bb 635 s->cpu_enabled[cpu] = (value & 1);
f7c70325 636 DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled ? "En" : "Dis");
e69954b9
PB
637 break;
638 case 0x04: /* Priority mask */
9ee6e8bb 639 s->priority_mask[cpu] = (value & 0xff);
e69954b9
PB
640 break;
641 case 0x08: /* Binary Point */
642 /* ??? Not implemented. */
643 break;
644 case 0x10: /* End Of Interrupt */
9ee6e8bb 645 return gic_complete_irq(s, cpu, value & 0x3ff);
e69954b9 646 default:
2ac71179 647 hw_error("gic_cpu_write: Bad offset %x\n", (int)offset);
e69954b9
PB
648 return;
649 }
650 gic_update(s);
651}
e2c56465
PM
652
653/* Wrappers to read/write the GIC CPU interface for the current CPU */
654static uint64_t gic_thiscpu_read(void *opaque, target_phys_addr_t addr,
655 unsigned size)
656{
657 gic_state *s = (gic_state *)opaque;
658 return gic_cpu_read(s, gic_get_current_cpu(), addr & 0xff);
659}
660
661static void gic_thiscpu_write(void *opaque, target_phys_addr_t addr,
662 uint64_t value, unsigned size)
663{
664 gic_state *s = (gic_state *)opaque;
665 gic_cpu_write(s, gic_get_current_cpu(), addr & 0xff, value);
666}
667
668/* Wrappers to read/write the GIC CPU interface for a specific CPU.
669 * These just decode the opaque pointer into gic_state* + cpu id.
670 */
671static uint64_t gic_do_cpu_read(void *opaque, target_phys_addr_t addr,
672 unsigned size)
673{
674 gic_state **backref = (gic_state **)opaque;
675 gic_state *s = *backref;
676 int id = (backref - s->backref);
677 return gic_cpu_read(s, id, addr & 0xff);
678}
679
680static void gic_do_cpu_write(void *opaque, target_phys_addr_t addr,
681 uint64_t value, unsigned size)
682{
683 gic_state **backref = (gic_state **)opaque;
684 gic_state *s = *backref;
685 int id = (backref - s->backref);
686 gic_cpu_write(s, id, addr & 0xff, value);
687}
688
689static const MemoryRegionOps gic_thiscpu_ops = {
690 .read = gic_thiscpu_read,
691 .write = gic_thiscpu_write,
692 .endianness = DEVICE_NATIVE_ENDIAN,
693};
694
695static const MemoryRegionOps gic_cpu_ops = {
696 .read = gic_do_cpu_read,
697 .write = gic_do_cpu_write,
698 .endianness = DEVICE_NATIVE_ENDIAN,
699};
9ee6e8bb 700#endif
e69954b9
PB
701
702static void gic_reset(gic_state *s)
703{
704 int i;
a32134aa 705 memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
c988bfad 706 for (i = 0 ; i < NUM_CPU(s); i++) {
9ee6e8bb
PB
707 s->priority_mask[i] = 0xf0;
708 s->current_pending[i] = 1023;
709 s->running_irq[i] = 1023;
710 s->running_priority[i] = 0x100;
711#ifdef NVIC
712 /* The NVIC doesn't have per-cpu interfaces, so enable by default. */
713 s->cpu_enabled[i] = 1;
714#else
715 s->cpu_enabled[i] = 0;
716#endif
717 }
e57ec016 718 for (i = 0; i < 16; i++) {
41bf234d 719 GIC_SET_ENABLED(i, ALL_CPU_MASK);
e69954b9
PB
720 GIC_SET_TRIGGER(i);
721 }
9ee6e8bb
PB
722#ifdef NVIC
723 /* The NVIC is always enabled. */
724 s->enabled = 1;
725#else
e69954b9 726 s->enabled = 0;
9ee6e8bb 727#endif
e69954b9
PB
728}
729
23e39294
PB
730static void gic_save(QEMUFile *f, void *opaque)
731{
732 gic_state *s = (gic_state *)opaque;
733 int i;
734 int j;
735
736 qemu_put_be32(f, s->enabled);
c988bfad 737 for (i = 0; i < NUM_CPU(s); i++) {
23e39294 738 qemu_put_be32(f, s->cpu_enabled[i]);
23e39294
PB
739 for (j = 0; j < 32; j++)
740 qemu_put_be32(f, s->priority1[j][i]);
a32134aa 741 for (j = 0; j < s->num_irq; j++)
23e39294
PB
742 qemu_put_be32(f, s->last_active[j][i]);
743 qemu_put_be32(f, s->priority_mask[i]);
744 qemu_put_be32(f, s->running_irq[i]);
745 qemu_put_be32(f, s->running_priority[i]);
746 qemu_put_be32(f, s->current_pending[i]);
747 }
a32134aa 748 for (i = 0; i < s->num_irq - 32; i++) {
23e39294
PB
749 qemu_put_be32(f, s->priority2[i]);
750 }
a32134aa 751 for (i = 0; i < s->num_irq; i++) {
c2e2343e
DK
752#ifndef NVIC
753 qemu_put_be32(f, s->irq_target[i]);
754#endif
23e39294
PB
755 qemu_put_byte(f, s->irq_state[i].enabled);
756 qemu_put_byte(f, s->irq_state[i].pending);
757 qemu_put_byte(f, s->irq_state[i].active);
758 qemu_put_byte(f, s->irq_state[i].level);
759 qemu_put_byte(f, s->irq_state[i].model);
760 qemu_put_byte(f, s->irq_state[i].trigger);
761 }
762}
763
764static int gic_load(QEMUFile *f, void *opaque, int version_id)
765{
766 gic_state *s = (gic_state *)opaque;
767 int i;
768 int j;
769
c2e2343e 770 if (version_id != 2)
23e39294
PB
771 return -EINVAL;
772
773 s->enabled = qemu_get_be32(f);
c988bfad 774 for (i = 0; i < NUM_CPU(s); i++) {
23e39294 775 s->cpu_enabled[i] = qemu_get_be32(f);
23e39294
PB
776 for (j = 0; j < 32; j++)
777 s->priority1[j][i] = qemu_get_be32(f);
a32134aa 778 for (j = 0; j < s->num_irq; j++)
23e39294
PB
779 s->last_active[j][i] = qemu_get_be32(f);
780 s->priority_mask[i] = qemu_get_be32(f);
781 s->running_irq[i] = qemu_get_be32(f);
782 s->running_priority[i] = qemu_get_be32(f);
783 s->current_pending[i] = qemu_get_be32(f);
784 }
a32134aa 785 for (i = 0; i < s->num_irq - 32; i++) {
23e39294
PB
786 s->priority2[i] = qemu_get_be32(f);
787 }
a32134aa 788 for (i = 0; i < s->num_irq; i++) {
c2e2343e
DK
789#ifndef NVIC
790 s->irq_target[i] = qemu_get_be32(f);
791#endif
23e39294
PB
792 s->irq_state[i].enabled = qemu_get_byte(f);
793 s->irq_state[i].pending = qemu_get_byte(f);
794 s->irq_state[i].active = qemu_get_byte(f);
795 s->irq_state[i].level = qemu_get_byte(f);
796 s->irq_state[i].model = qemu_get_byte(f);
797 s->irq_state[i].trigger = qemu_get_byte(f);
798 }
799
800 return 0;
801}
802
c988bfad 803#if NCPU > 1
a32134aa 804static void gic_init(gic_state *s, int num_cpu, int num_irq)
c988bfad 805#else
a32134aa 806static void gic_init(gic_state *s, int num_irq)
c988bfad 807#endif
e69954b9 808{
9ee6e8bb 809 int i;
e69954b9 810
c988bfad
PB
811#if NCPU > 1
812 s->num_cpu = num_cpu;
813#endif
a32134aa
ML
814 s->num_irq = num_irq + GIC_BASE_IRQ;
815 if (s->num_irq > GIC_MAXIRQ) {
816 hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
817 num_irq, GIC_MAXIRQ);
818 }
819 qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
c988bfad 820 for (i = 0; i < NUM_CPU(s); i++) {
fe7e8758 821 sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
e69954b9 822 }
755c0802 823 memory_region_init_io(&s->iomem, &gic_dist_ops, s, "gic_dist", 0x1000);
e2c56465
PM
824#ifndef NVIC
825 /* Memory regions for the CPU interfaces (NVIC doesn't have these):
826 * a region for "CPU interface for this core", then a region for
827 * "CPU interface for core 0", "for core 1", ...
828 * NB that the memory region size of 0x100 applies for the 11MPCore
829 * and also cores following the GIC v1 spec (ie A9).
830 * GIC v2 defines a larger memory region (0x1000) so this will need
831 * to be extended when we implement A15.
832 */
833 memory_region_init_io(&s->cpuiomem[0], &gic_thiscpu_ops, s,
834 "gic_cpu", 0x100);
835 for (i = 0; i < NUM_CPU(s); i++) {
836 s->backref[i] = s;
837 memory_region_init_io(&s->cpuiomem[i+1], &gic_cpu_ops, &s->backref[i],
838 "gic_cpu", 0x100);
839 }
840#endif
841
e69954b9 842 gic_reset(s);
c2e2343e 843 register_savevm(NULL, "arm_gic", -1, 2, gic_save, gic_load, s);
e69954b9 844}
This page took 0.599209 seconds and 4 git commands to generate.