Annotation of qemu/hw/arm_gic.c, revision 1.1.1.5

1.1.1.2   root        1: /*
                      2:  * ARM Generic/Distributed Interrupt Controller
1.1       root        3:  *
1.1.1.2   root        4:  * Copyright (c) 2006-2007 CodeSourcery.
1.1       root        5:  * Written by Paul Brook
                      6:  *
                      7:  * This code is licenced under the GPL.
                      8:  */
                      9: 
1.1.1.2   root       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.  */
1.1       root       13: 
                     14: //#define DEBUG_GIC
                     15: 
                     16: #ifdef DEBUG_GIC
1.1.1.4   root       17: #define DPRINTF(fmt, ...) \
                     18: do { printf("arm_gic: " fmt , ## __VA_ARGS__); } while (0)
1.1       root       19: #else
1.1.1.4   root       20: #define DPRINTF(fmt, ...) do {} while(0)
1.1       root       21: #endif
                     22: 
1.1.1.2   root       23: #ifdef NVIC
                     24: static const uint8_t gic_id[] =
                     25: { 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1 };
                     26: /* The NVIC has 16 internal vectors.  However these are not exposed
                     27:    through the normal GIC interface.  */
                     28: #define GIC_BASE_IRQ    32
                     29: #else
1.1       root       30: static const uint8_t gic_id[] =
                     31: { 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
1.1.1.2   root       32: #define GIC_BASE_IRQ    0
                     33: #endif
1.1       root       34: 
1.1.1.4   root       35: #define FROM_SYSBUSGIC(type, dev) \
                     36:     DO_UPCAST(type, gic, FROM_SYSBUS(gic_state, dev))
                     37: 
1.1       root       38: typedef struct gic_irq_state
                     39: {
1.1.1.2   root       40:     /* ??? The documentation seems to imply the enable bits are global, even
                     41:        for per-cpu interrupts.  This seems strange.  */
1.1       root       42:     unsigned enabled:1;
1.1.1.2   root       43:     unsigned pending:NCPU;
                     44:     unsigned active:NCPU;
1.1.1.4   root       45:     unsigned level:NCPU;
1.1.1.2   root       46:     unsigned model:1; /* 0 = N:N, 1 = 1:N */
1.1       root       47:     unsigned trigger:1; /* nonzero = edge triggered.  */
                     48: } gic_irq_state;
                     49: 
1.1.1.2   root       50: #define ALL_CPU_MASK ((1 << NCPU) - 1)
1.1.1.5 ! root       51: #if NCPU > 1
        !            52: #define NUM_CPU(s) ((s)->num_cpu)
        !            53: #else
        !            54: #define NUM_CPU(s) 1
        !            55: #endif
1.1.1.2   root       56: 
1.1       root       57: #define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1
                     58: #define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0
                     59: #define GIC_TEST_ENABLED(irq) s->irq_state[irq].enabled
1.1.1.2   root       60: #define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
                     61: #define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
                     62: #define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
                     63: #define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
                     64: #define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
                     65: #define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
1.1       root       66: #define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
                     67: #define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
                     68: #define GIC_TEST_MODEL(irq) s->irq_state[irq].model
1.1.1.2   root       69: #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
                     70: #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
1.1.1.3   root       71: #define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
1.1       root       72: #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
                     73: #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
                     74: #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
1.1.1.2   root       75: #define GIC_GET_PRIORITY(irq, cpu) \
                     76:   (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
                     77: #ifdef NVIC
                     78: #define GIC_TARGET(irq) 1
                     79: #else
                     80: #define GIC_TARGET(irq) s->irq_target[irq]
                     81: #endif
1.1       root       82: 
                     83: typedef struct gic_state
                     84: {
1.1.1.4   root       85:     SysBusDevice busdev;
1.1.1.2   root       86:     qemu_irq parent_irq[NCPU];
1.1       root       87:     int enabled;
1.1.1.2   root       88:     int cpu_enabled[NCPU];
1.1       root       89: 
                     90:     gic_irq_state irq_state[GIC_NIRQ];
1.1.1.2   root       91: #ifndef NVIC
1.1       root       92:     int irq_target[GIC_NIRQ];
1.1.1.2   root       93: #endif
                     94:     int priority1[32][NCPU];
                     95:     int priority2[GIC_NIRQ - 32];
                     96:     int last_active[GIC_NIRQ][NCPU];
                     97: 
                     98:     int priority_mask[NCPU];
                     99:     int running_irq[NCPU];
                    100:     int running_priority[NCPU];
                    101:     int current_pending[NCPU];
                    102: 
1.1.1.5 ! root      103: #if NCPU > 1
        !           104:     int num_cpu;
        !           105: #endif
        !           106: 
1.1.1.4   root      107:     int iomemtype;
1.1       root      108: } gic_state;
                    109: 
                    110: /* TODO: Many places that call this routine could be optimized.  */
                    111: /* Update interrupt status after enabled or pending bits have been changed.  */
                    112: static void gic_update(gic_state *s)
                    113: {
                    114:     int best_irq;
                    115:     int best_prio;
                    116:     int irq;
1.1.1.2   root      117:     int level;
                    118:     int cpu;
                    119:     int cm;
1.1       root      120: 
1.1.1.5 ! root      121:     for (cpu = 0; cpu < NUM_CPU(s); cpu++) {
1.1.1.2   root      122:         cm = 1 << cpu;
                    123:         s->current_pending[cpu] = 1023;
                    124:         if (!s->enabled || !s->cpu_enabled[cpu]) {
                    125:            qemu_irq_lower(s->parent_irq[cpu]);
                    126:             return;
                    127:         }
                    128:         best_prio = 0x100;
                    129:         best_irq = 1023;
                    130:         for (irq = 0; irq < GIC_NIRQ; irq++) {
                    131:             if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq, cm)) {
                    132:                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                    133:                     best_prio = GIC_GET_PRIORITY(irq, cpu);
                    134:                     best_irq = irq;
                    135:                 }
1.1       root      136:             }
                    137:         }
1.1.1.2   root      138:         level = 0;
                    139:         if (best_prio <= s->priority_mask[cpu]) {
                    140:             s->current_pending[cpu] = best_irq;
                    141:             if (best_prio < s->running_priority[cpu]) {
                    142:                 DPRINTF("Raised pending IRQ %d\n", best_irq);
                    143:                 level = 1;
                    144:             }
1.1       root      145:         }
1.1.1.2   root      146:         qemu_set_irq(s->parent_irq[cpu], level);
1.1       root      147:     }
                    148: }
                    149: 
1.1.1.2   root      150: static void __attribute__((unused))
                    151: gic_set_pending_private(gic_state *s, int cpu, int irq)
                    152: {
                    153:     int cm = 1 << cpu;
                    154: 
                    155:     if (GIC_TEST_PENDING(irq, cm))
                    156:         return;
                    157: 
                    158:     DPRINTF("Set %d pending cpu %d\n", irq, cpu);
                    159:     GIC_SET_PENDING(irq, cm);
                    160:     gic_update(s);
                    161: }
                    162: 
                    163: /* Process a change in an external IRQ input.  */
1.1       root      164: static void gic_set_irq(void *opaque, int irq, int level)
                    165: {
                    166:     gic_state *s = (gic_state *)opaque;
                    167:     /* The first external input line is internal interrupt 32.  */
                    168:     irq += 32;
1.1.1.2   root      169:     if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
1.1       root      170:         return;
                    171: 
                    172:     if (level) {
1.1.1.2   root      173:         GIC_SET_LEVEL(irq, ALL_CPU_MASK);
1.1       root      174:         if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
1.1.1.2   root      175:             DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
                    176:             GIC_SET_PENDING(irq, GIC_TARGET(irq));
1.1       root      177:         }
                    178:     } else {
1.1.1.2   root      179:         GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
1.1       root      180:     }
                    181:     gic_update(s);
                    182: }
                    183: 
1.1.1.2   root      184: static void gic_set_running_irq(gic_state *s, int cpu, int irq)
1.1       root      185: {
1.1.1.2   root      186:     s->running_irq[cpu] = irq;
                    187:     if (irq == 1023) {
                    188:         s->running_priority[cpu] = 0x100;
                    189:     } else {
                    190:         s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu);
                    191:     }
1.1       root      192:     gic_update(s);
                    193: }
                    194: 
1.1.1.2   root      195: static uint32_t gic_acknowledge_irq(gic_state *s, int cpu)
1.1       root      196: {
                    197:     int new_irq;
1.1.1.2   root      198:     int cm = 1 << cpu;
                    199:     new_irq = s->current_pending[cpu];
                    200:     if (new_irq == 1023
                    201:             || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) {
1.1       root      202:         DPRINTF("ACK no pending IRQ\n");
                    203:         return 1023;
                    204:     }
1.1.1.2   root      205:     s->last_active[new_irq][cpu] = s->running_irq[cpu];
                    206:     /* Clear pending flags for both level and edge triggered interrupts.
                    207:        Level triggered IRQs will be reasserted once they become inactive.  */
                    208:     GIC_CLEAR_PENDING(new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm);
                    209:     gic_set_running_irq(s, cpu, new_irq);
1.1       root      210:     DPRINTF("ACK %d\n", new_irq);
                    211:     return new_irq;
                    212: }
                    213: 
1.1.1.2   root      214: static void gic_complete_irq(gic_state * s, int cpu, int irq)
1.1       root      215: {
                    216:     int update = 0;
1.1.1.2   root      217:     int cm = 1 << cpu;
1.1       root      218:     DPRINTF("EOI %d\n", irq);
1.1.1.2   root      219:     if (s->running_irq[cpu] == 1023)
1.1       root      220:         return; /* No active IRQ.  */
                    221:     if (irq != 1023) {
                    222:         /* Mark level triggered interrupts as pending if they are still
                    223:            raised.  */
                    224:         if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq)
1.1.1.2   root      225:                 && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
                    226:             DPRINTF("Set %d pending mask %x\n", irq, cm);
                    227:             GIC_SET_PENDING(irq, cm);
1.1       root      228:             update = 1;
                    229:         }
                    230:     }
1.1.1.2   root      231:     if (irq != s->running_irq[cpu]) {
1.1       root      232:         /* Complete an IRQ that is not currently running.  */
1.1.1.2   root      233:         int tmp = s->running_irq[cpu];
                    234:         while (s->last_active[tmp][cpu] != 1023) {
                    235:             if (s->last_active[tmp][cpu] == irq) {
                    236:                 s->last_active[tmp][cpu] = s->last_active[irq][cpu];
1.1       root      237:                 break;
                    238:             }
1.1.1.2   root      239:             tmp = s->last_active[tmp][cpu];
1.1       root      240:         }
                    241:         if (update) {
                    242:             gic_update(s);
                    243:         }
                    244:     } else {
                    245:         /* Complete the current running IRQ.  */
1.1.1.2   root      246:         gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]);
1.1       root      247:     }
                    248: }
                    249: 
                    250: static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
                    251: {
                    252:     gic_state *s = (gic_state *)opaque;
                    253:     uint32_t res;
                    254:     int irq;
                    255:     int i;
1.1.1.2   root      256:     int cpu;
                    257:     int cm;
                    258:     int mask;
                    259: 
                    260:     cpu = gic_get_current_cpu();
                    261:     cm = 1 << cpu;
1.1       root      262:     if (offset < 0x100) {
1.1.1.2   root      263: #ifndef NVIC
1.1       root      264:         if (offset == 0)
                    265:             return s->enabled;
                    266:         if (offset == 4)
1.1.1.5 ! root      267:             return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
1.1       root      268:         if (offset < 0x08)
                    269:             return 0;
1.1.1.2   root      270: #endif
1.1       root      271:         goto bad_reg;
                    272:     } else if (offset < 0x200) {
                    273:         /* Interrupt Set/Clear Enable.  */
                    274:         if (offset < 0x180)
                    275:             irq = (offset - 0x100) * 8;
                    276:         else
                    277:             irq = (offset - 0x180) * 8;
1.1.1.2   root      278:         irq += GIC_BASE_IRQ;
1.1       root      279:         if (irq >= GIC_NIRQ)
                    280:             goto bad_reg;
                    281:         res = 0;
                    282:         for (i = 0; i < 8; i++) {
                    283:             if (GIC_TEST_ENABLED(irq + i)) {
                    284:                 res |= (1 << i);
                    285:             }
                    286:         }
                    287:     } else if (offset < 0x300) {
                    288:         /* Interrupt Set/Clear Pending.  */
                    289:         if (offset < 0x280)
                    290:             irq = (offset - 0x200) * 8;
                    291:         else
                    292:             irq = (offset - 0x280) * 8;
1.1.1.2   root      293:         irq += GIC_BASE_IRQ;
1.1       root      294:         if (irq >= GIC_NIRQ)
                    295:             goto bad_reg;
                    296:         res = 0;
1.1.1.2   root      297:         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
1.1       root      298:         for (i = 0; i < 8; i++) {
1.1.1.2   root      299:             if (GIC_TEST_PENDING(irq + i, mask)) {
1.1       root      300:                 res |= (1 << i);
                    301:             }
                    302:         }
                    303:     } else if (offset < 0x400) {
                    304:         /* Interrupt Active.  */
1.1.1.2   root      305:         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
1.1       root      306:         if (irq >= GIC_NIRQ)
                    307:             goto bad_reg;
                    308:         res = 0;
1.1.1.2   root      309:         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
1.1       root      310:         for (i = 0; i < 8; i++) {
1.1.1.2   root      311:             if (GIC_TEST_ACTIVE(irq + i, mask)) {
1.1       root      312:                 res |= (1 << i);
                    313:             }
                    314:         }
                    315:     } else if (offset < 0x800) {
                    316:         /* Interrupt Priority.  */
1.1.1.2   root      317:         irq = (offset - 0x400) + GIC_BASE_IRQ;
1.1       root      318:         if (irq >= GIC_NIRQ)
                    319:             goto bad_reg;
1.1.1.2   root      320:         res = GIC_GET_PRIORITY(irq, cpu);
                    321: #ifndef NVIC
1.1       root      322:     } else if (offset < 0xc00) {
                    323:         /* Interrupt CPU Target.  */
1.1.1.2   root      324:         irq = (offset - 0x800) + GIC_BASE_IRQ;
1.1       root      325:         if (irq >= GIC_NIRQ)
                    326:             goto bad_reg;
1.1.1.2   root      327:         if (irq >= 29 && irq <= 31) {
                    328:             res = cm;
                    329:         } else {
                    330:             res = GIC_TARGET(irq);
                    331:         }
1.1       root      332:     } else if (offset < 0xf00) {
                    333:         /* Interrupt Configuration.  */
1.1.1.2   root      334:         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
1.1       root      335:         if (irq >= GIC_NIRQ)
                    336:             goto bad_reg;
                    337:         res = 0;
                    338:         for (i = 0; i < 4; i++) {
                    339:             if (GIC_TEST_MODEL(irq + i))
                    340:                 res |= (1 << (i * 2));
                    341:             if (GIC_TEST_TRIGGER(irq + i))
                    342:                 res |= (2 << (i * 2));
                    343:         }
1.1.1.2   root      344: #endif
1.1       root      345:     } else if (offset < 0xfe0) {
                    346:         goto bad_reg;
                    347:     } else /* offset >= 0xfe0 */ {
                    348:         if (offset & 3) {
                    349:             res = 0;
                    350:         } else {
                    351:             res = gic_id[(offset - 0xfe0) >> 2];
                    352:         }
                    353:     }
                    354:     return res;
                    355: bad_reg:
1.1.1.4   root      356:     hw_error("gic_dist_readb: Bad offset %x\n", (int)offset);
1.1       root      357:     return 0;
                    358: }
                    359: 
                    360: static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset)
                    361: {
                    362:     uint32_t val;
                    363:     val = gic_dist_readb(opaque, offset);
                    364:     val |= gic_dist_readb(opaque, offset + 1) << 8;
                    365:     return val;
                    366: }
                    367: 
                    368: static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
                    369: {
                    370:     uint32_t val;
1.1.1.2   root      371: #ifdef NVIC
                    372:     gic_state *s = (gic_state *)opaque;
                    373:     uint32_t addr;
1.1.1.3   root      374:     addr = offset;
1.1.1.2   root      375:     if (addr < 0x100 || addr > 0xd00)
1.1.1.4   root      376:         return nvic_readl(s, addr);
1.1.1.2   root      377: #endif
1.1       root      378:     val = gic_dist_readw(opaque, offset);
                    379:     val |= gic_dist_readw(opaque, offset + 2) << 16;
                    380:     return val;
                    381: }
                    382: 
                    383: static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
                    384:                             uint32_t value)
                    385: {
                    386:     gic_state *s = (gic_state *)opaque;
                    387:     int irq;
                    388:     int i;
1.1.1.2   root      389:     int cpu;
1.1       root      390: 
1.1.1.2   root      391:     cpu = gic_get_current_cpu();
1.1       root      392:     if (offset < 0x100) {
1.1.1.2   root      393: #ifdef NVIC
                    394:         goto bad_reg;
                    395: #else
1.1       root      396:         if (offset == 0) {
                    397:             s->enabled = (value & 1);
                    398:             DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
                    399:         } else if (offset < 4) {
                    400:             /* ignored.  */
                    401:         } else {
                    402:             goto bad_reg;
                    403:         }
1.1.1.2   root      404: #endif
1.1       root      405:     } else if (offset < 0x180) {
                    406:         /* Interrupt Set Enable.  */
1.1.1.2   root      407:         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
1.1       root      408:         if (irq >= GIC_NIRQ)
                    409:             goto bad_reg;
1.1.1.2   root      410:         if (irq < 16)
                    411:           value = 0xff;
1.1       root      412:         for (i = 0; i < 8; i++) {
                    413:             if (value & (1 << i)) {
1.1.1.2   root      414:                 int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
1.1       root      415:                 if (!GIC_TEST_ENABLED(irq + i))
                    416:                     DPRINTF("Enabled IRQ %d\n", irq + i);
                    417:                 GIC_SET_ENABLED(irq + i);
                    418:                 /* If a raised level triggered IRQ enabled then mark
                    419:                    is as pending.  */
1.1.1.2   root      420:                 if (GIC_TEST_LEVEL(irq + i, mask)
                    421:                         && !GIC_TEST_TRIGGER(irq + i)) {
                    422:                     DPRINTF("Set %d pending mask %x\n", irq + i, mask);
                    423:                     GIC_SET_PENDING(irq + i, mask);
                    424:                 }
1.1       root      425:             }
                    426:         }
                    427:     } else if (offset < 0x200) {
                    428:         /* Interrupt Clear Enable.  */
1.1.1.2   root      429:         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
1.1       root      430:         if (irq >= GIC_NIRQ)
                    431:             goto bad_reg;
1.1.1.2   root      432:         if (irq < 16)
                    433:           value = 0;
1.1       root      434:         for (i = 0; i < 8; i++) {
                    435:             if (value & (1 << i)) {
                    436:                 if (GIC_TEST_ENABLED(irq + i))
                    437:                     DPRINTF("Disabled IRQ %d\n", irq + i);
                    438:                 GIC_CLEAR_ENABLED(irq + i);
                    439:             }
                    440:         }
                    441:     } else if (offset < 0x280) {
                    442:         /* Interrupt Set Pending.  */
1.1.1.2   root      443:         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
1.1       root      444:         if (irq >= GIC_NIRQ)
                    445:             goto bad_reg;
1.1.1.2   root      446:         if (irq < 16)
                    447:           irq = 0;
                    448: 
1.1       root      449:         for (i = 0; i < 8; i++) {
                    450:             if (value & (1 << i)) {
1.1.1.2   root      451:                 GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
1.1       root      452:             }
                    453:         }
                    454:     } else if (offset < 0x300) {
                    455:         /* Interrupt Clear Pending.  */
1.1.1.2   root      456:         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
1.1       root      457:         if (irq >= GIC_NIRQ)
                    458:             goto bad_reg;
                    459:         for (i = 0; i < 8; i++) {
1.1.1.2   root      460:             /* ??? This currently clears the pending bit for all CPUs, even
                    461:                for per-CPU interrupts.  It's unclear whether this is the
                    462:                corect behavior.  */
1.1       root      463:             if (value & (1 << i)) {
1.1.1.2   root      464:                 GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
1.1       root      465:             }
                    466:         }
                    467:     } else if (offset < 0x400) {
                    468:         /* Interrupt Active.  */
                    469:         goto bad_reg;
                    470:     } else if (offset < 0x800) {
                    471:         /* Interrupt Priority.  */
1.1.1.2   root      472:         irq = (offset - 0x400) + GIC_BASE_IRQ;
1.1       root      473:         if (irq >= GIC_NIRQ)
                    474:             goto bad_reg;
1.1.1.2   root      475:         if (irq < 32) {
                    476:             s->priority1[irq][cpu] = value;
                    477:         } else {
                    478:             s->priority2[irq - 32] = value;
                    479:         }
                    480: #ifndef NVIC
1.1       root      481:     } else if (offset < 0xc00) {
                    482:         /* Interrupt CPU Target.  */
1.1.1.2   root      483:         irq = (offset - 0x800) + GIC_BASE_IRQ;
1.1       root      484:         if (irq >= GIC_NIRQ)
                    485:             goto bad_reg;
1.1.1.2   root      486:         if (irq < 29)
                    487:             value = 0;
                    488:         else if (irq < 32)
                    489:             value = ALL_CPU_MASK;
                    490:         s->irq_target[irq] = value & ALL_CPU_MASK;
1.1       root      491:     } else if (offset < 0xf00) {
                    492:         /* Interrupt Configuration.  */
1.1.1.2   root      493:         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
1.1       root      494:         if (irq >= GIC_NIRQ)
                    495:             goto bad_reg;
1.1.1.2   root      496:         if (irq < 32)
                    497:             value |= 0xaa;
1.1       root      498:         for (i = 0; i < 4; i++) {
                    499:             if (value & (1 << (i * 2))) {
                    500:                 GIC_SET_MODEL(irq + i);
                    501:             } else {
                    502:                 GIC_CLEAR_MODEL(irq + i);
                    503:             }
                    504:             if (value & (2 << (i * 2))) {
                    505:                 GIC_SET_TRIGGER(irq + i);
                    506:             } else {
                    507:                 GIC_CLEAR_TRIGGER(irq + i);
                    508:             }
                    509:         }
1.1.1.2   root      510: #endif
1.1       root      511:     } else {
1.1.1.2   root      512:         /* 0xf00 is only handled for 32-bit writes.  */
1.1       root      513:         goto bad_reg;
                    514:     }
                    515:     gic_update(s);
                    516:     return;
                    517: bad_reg:
1.1.1.4   root      518:     hw_error("gic_dist_writeb: Bad offset %x\n", (int)offset);
1.1       root      519: }
                    520: 
                    521: static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
                    522:                             uint32_t value)
                    523: {
                    524:     gic_dist_writeb(opaque, offset, value & 0xff);
                    525:     gic_dist_writeb(opaque, offset + 1, value >> 8);
                    526: }
                    527: 
                    528: static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
                    529:                             uint32_t value)
                    530: {
1.1.1.2   root      531:     gic_state *s = (gic_state *)opaque;
                    532: #ifdef NVIC
                    533:     uint32_t addr;
1.1.1.3   root      534:     addr = offset;
1.1.1.2   root      535:     if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) {
1.1.1.4   root      536:         nvic_writel(s, addr, value);
1.1.1.2   root      537:         return;
                    538:     }
                    539: #endif
1.1.1.3   root      540:     if (offset == 0xf00) {
1.1.1.2   root      541:         int cpu;
                    542:         int irq;
                    543:         int mask;
                    544: 
                    545:         cpu = gic_get_current_cpu();
                    546:         irq = value & 0x3ff;
                    547:         switch ((value >> 24) & 3) {
                    548:         case 0:
                    549:             mask = (value >> 16) & ALL_CPU_MASK;
                    550:             break;
                    551:         case 1:
                    552:             mask = 1 << cpu;
                    553:             break;
                    554:         case 2:
                    555:             mask = ALL_CPU_MASK ^ (1 << cpu);
                    556:             break;
                    557:         default:
                    558:             DPRINTF("Bad Soft Int target filter\n");
                    559:             mask = ALL_CPU_MASK;
                    560:             break;
                    561:         }
                    562:         GIC_SET_PENDING(irq, mask);
                    563:         gic_update(s);
                    564:         return;
                    565:     }
1.1       root      566:     gic_dist_writew(opaque, offset, value & 0xffff);
                    567:     gic_dist_writew(opaque, offset + 2, value >> 16);
                    568: }
                    569: 
1.1.1.5 ! root      570: static CPUReadMemoryFunc * const gic_dist_readfn[] = {
1.1       root      571:    gic_dist_readb,
                    572:    gic_dist_readw,
                    573:    gic_dist_readl
                    574: };
                    575: 
1.1.1.5 ! root      576: static CPUWriteMemoryFunc * const gic_dist_writefn[] = {
1.1       root      577:    gic_dist_writeb,
                    578:    gic_dist_writew,
                    579:    gic_dist_writel
                    580: };
                    581: 
1.1.1.2   root      582: #ifndef NVIC
                    583: static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset)
1.1       root      584: {
                    585:     switch (offset) {
                    586:     case 0x00: /* Control */
1.1.1.2   root      587:         return s->cpu_enabled[cpu];
1.1       root      588:     case 0x04: /* Priority mask */
1.1.1.2   root      589:         return s->priority_mask[cpu];
1.1       root      590:     case 0x08: /* Binary Point */
                    591:         /* ??? Not implemented.  */
                    592:         return 0;
                    593:     case 0x0c: /* Acknowledge */
1.1.1.2   root      594:         return gic_acknowledge_irq(s, cpu);
1.1       root      595:     case 0x14: /* Runing Priority */
1.1.1.2   root      596:         return s->running_priority[cpu];
1.1       root      597:     case 0x18: /* Highest Pending Interrupt */
1.1.1.2   root      598:         return s->current_pending[cpu];
1.1       root      599:     default:
1.1.1.4   root      600:         hw_error("gic_cpu_read: Bad offset %x\n", (int)offset);
1.1       root      601:         return 0;
                    602:     }
                    603: }
                    604: 
1.1.1.2   root      605: static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
1.1       root      606: {
                    607:     switch (offset) {
                    608:     case 0x00: /* Control */
1.1.1.2   root      609:         s->cpu_enabled[cpu] = (value & 1);
1.1.1.5 ! root      610:         DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled ? "En" : "Dis");
1.1       root      611:         break;
                    612:     case 0x04: /* Priority mask */
1.1.1.2   root      613:         s->priority_mask[cpu] = (value & 0xff);
1.1       root      614:         break;
                    615:     case 0x08: /* Binary Point */
                    616:         /* ??? Not implemented.  */
                    617:         break;
                    618:     case 0x10: /* End Of Interrupt */
1.1.1.2   root      619:         return gic_complete_irq(s, cpu, value & 0x3ff);
1.1       root      620:     default:
1.1.1.4   root      621:         hw_error("gic_cpu_write: Bad offset %x\n", (int)offset);
1.1       root      622:         return;
                    623:     }
                    624:     gic_update(s);
                    625: }
1.1.1.2   root      626: #endif
1.1       root      627: 
                    628: static void gic_reset(gic_state *s)
                    629: {
                    630:     int i;
                    631:     memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
1.1.1.5 ! root      632:     for (i = 0 ; i < NUM_CPU(s); i++) {
1.1.1.2   root      633:         s->priority_mask[i] = 0xf0;
                    634:         s->current_pending[i] = 1023;
                    635:         s->running_irq[i] = 1023;
                    636:         s->running_priority[i] = 0x100;
                    637: #ifdef NVIC
                    638:         /* The NVIC doesn't have per-cpu interfaces, so enable by default.  */
                    639:         s->cpu_enabled[i] = 1;
                    640: #else
                    641:         s->cpu_enabled[i] = 0;
                    642: #endif
                    643:     }
                    644:     for (i = 0; i < 16; i++) {
1.1       root      645:         GIC_SET_ENABLED(i);
                    646:         GIC_SET_TRIGGER(i);
                    647:     }
1.1.1.2   root      648: #ifdef NVIC
                    649:     /* The NVIC is always enabled.  */
                    650:     s->enabled = 1;
                    651: #else
1.1       root      652:     s->enabled = 0;
1.1.1.2   root      653: #endif
1.1       root      654: }
                    655: 
1.1.1.3   root      656: static void gic_save(QEMUFile *f, void *opaque)
                    657: {
                    658:     gic_state *s = (gic_state *)opaque;
                    659:     int i;
                    660:     int j;
                    661: 
                    662:     qemu_put_be32(f, s->enabled);
1.1.1.5 ! root      663:     for (i = 0; i < NUM_CPU(s); i++) {
1.1.1.3   root      664:         qemu_put_be32(f, s->cpu_enabled[i]);
                    665: #ifndef NVIC
                    666:         qemu_put_be32(f, s->irq_target[i]);
                    667: #endif
                    668:         for (j = 0; j < 32; j++)
                    669:             qemu_put_be32(f, s->priority1[j][i]);
                    670:         for (j = 0; j < GIC_NIRQ; j++)
                    671:             qemu_put_be32(f, s->last_active[j][i]);
                    672:         qemu_put_be32(f, s->priority_mask[i]);
                    673:         qemu_put_be32(f, s->running_irq[i]);
                    674:         qemu_put_be32(f, s->running_priority[i]);
                    675:         qemu_put_be32(f, s->current_pending[i]);
                    676:     }
                    677:     for (i = 0; i < GIC_NIRQ - 32; i++) {
                    678:         qemu_put_be32(f, s->priority2[i]);
                    679:     }
                    680:     for (i = 0; i < GIC_NIRQ; i++) {
                    681:         qemu_put_byte(f, s->irq_state[i].enabled);
                    682:         qemu_put_byte(f, s->irq_state[i].pending);
                    683:         qemu_put_byte(f, s->irq_state[i].active);
                    684:         qemu_put_byte(f, s->irq_state[i].level);
                    685:         qemu_put_byte(f, s->irq_state[i].model);
                    686:         qemu_put_byte(f, s->irq_state[i].trigger);
                    687:     }
                    688: }
                    689: 
                    690: static int gic_load(QEMUFile *f, void *opaque, int version_id)
                    691: {
                    692:     gic_state *s = (gic_state *)opaque;
                    693:     int i;
                    694:     int j;
                    695: 
                    696:     if (version_id != 1)
                    697:         return -EINVAL;
                    698: 
                    699:     s->enabled = qemu_get_be32(f);
1.1.1.5 ! root      700:     for (i = 0; i < NUM_CPU(s); i++) {
1.1.1.3   root      701:         s->cpu_enabled[i] = qemu_get_be32(f);
                    702: #ifndef NVIC
                    703:         s->irq_target[i] = qemu_get_be32(f);
                    704: #endif
                    705:         for (j = 0; j < 32; j++)
                    706:             s->priority1[j][i] = qemu_get_be32(f);
                    707:         for (j = 0; j < GIC_NIRQ; j++)
                    708:             s->last_active[j][i] = qemu_get_be32(f);
                    709:         s->priority_mask[i] = qemu_get_be32(f);
                    710:         s->running_irq[i] = qemu_get_be32(f);
                    711:         s->running_priority[i] = qemu_get_be32(f);
                    712:         s->current_pending[i] = qemu_get_be32(f);
                    713:     }
                    714:     for (i = 0; i < GIC_NIRQ - 32; i++) {
                    715:         s->priority2[i] = qemu_get_be32(f);
                    716:     }
                    717:     for (i = 0; i < GIC_NIRQ; i++) {
                    718:         s->irq_state[i].enabled = qemu_get_byte(f);
                    719:         s->irq_state[i].pending = qemu_get_byte(f);
                    720:         s->irq_state[i].active = qemu_get_byte(f);
                    721:         s->irq_state[i].level = qemu_get_byte(f);
                    722:         s->irq_state[i].model = qemu_get_byte(f);
                    723:         s->irq_state[i].trigger = qemu_get_byte(f);
                    724:     }
                    725: 
                    726:     return 0;
                    727: }
                    728: 
1.1.1.5 ! root      729: #if NCPU > 1
        !           730: static void gic_init(gic_state *s, int num_cpu)
        !           731: #else
1.1.1.4   root      732: static void gic_init(gic_state *s)
1.1.1.5 ! root      733: #endif
1.1       root      734: {
1.1.1.2   root      735:     int i;
1.1       root      736: 
1.1.1.5 ! root      737: #if NCPU > 1
        !           738:     s->num_cpu = num_cpu;
        !           739: #endif
1.1.1.4   root      740:     qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
1.1.1.5 ! root      741:     for (i = 0; i < NUM_CPU(s); i++) {
1.1.1.4   root      742:         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
1.1.1.2   root      743:     }
1.1.1.4   root      744:     s->iomemtype = cpu_register_io_memory(gic_dist_readfn,
                    745:                                           gic_dist_writefn, s);
1.1       root      746:     gic_reset(s);
1.1.1.3   root      747:     register_savevm("arm_gic", -1, 1, gic_save, gic_load, s);
1.1       root      748: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.