(linenum→info "unix/slp.c:2238")

qemu/0.9.1/hw/arm_gic.c

    1: /*
    2:  * ARM Generic/Distributed Interrupt Controller
    3:  *
    4:  * Copyright (c) 2006-2007 CodeSourcery.
    5:  * Written by Paul Brook
    6:  *
    7:  * This code is licenced under the GPL.
    8:  */
    9: 
   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.  */
   13: 
   14: //#define DEBUG_GIC
   15: 
   16: #ifdef DEBUG_GIC
   17: #define DPRINTF(fmt, args...) \
   18: do { printf("arm_gic: " fmt , ##args); } while (0)
   19: #else
   20: #define DPRINTF(fmt, args...) do {} while(0)
   21: #endif
   22: 
   23: #ifdef NVIC
   24: static const uint8_t gic_id[] =
   25: { 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1 };
   26: #define GIC_DIST_OFFSET 0
   27: /* The NVIC has 16 internal vectors.  However these are not exposed
   28:    through the normal GIC interface.  */
   29: #define GIC_BASE_IRQ    32
   30: #else
   31: static const uint8_t gic_id[] =
   32: { 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
   33: #define GIC_DIST_OFFSET 0x1000
   34: #define GIC_BASE_IRQ    0
   35: #endif
   36: 
   37: typedef struct gic_irq_state
   38: {
   39:     /* ??? The documentation seems to imply the enable bits are global, even
   40:        for per-cpu interrupts.  This seems strange.  */
   41:     unsigned enabled:1;
   42:     unsigned pending:NCPU;
   43:     unsigned active:NCPU;
   44:     unsigned level:1;
   45:     unsigned model:1; /* 0 = N:N, 1 = 1:N */
   46:     unsigned trigger:1; /* nonzero = edge triggered.  */
   47: } gic_irq_state;
   48: 
   49: #define ALL_CPU_MASK ((1 << NCPU) - 1)
   50: 
   51: #define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1
   52: #define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0
   53: #define GIC_TEST_ENABLED(irq) s->irq_state[irq].enabled
   54: #define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
   55: #define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
   56: #define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
   57: #define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm)
   58: #define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm)
   59: #define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0)
   60: #define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1
   61: #define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0
   62: #define GIC_TEST_MODEL(irq) s->irq_state[irq].model
   63: #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm)
   64: #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm)
   65: #define GIC_TEST_LEVEL(irq, cm) (s->irq_state[irq].level & (cm)) != 0
   66: #define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1
   67: #define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0
   68: #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger
   69: #define GIC_GET_PRIORITY(irq, cpu) \
   70:   (((irq) < 32) ? s->priority1[irq][cpu] : s->priority2[(irq) - 32])
   71: #ifdef NVIC
   72: #define GIC_TARGET(irq) 1
   73: #else
   74: #define GIC_TARGET(irq) s->irq_target[irq]
   75: #endif
   76: 
   77: typedef struct gic_state
   78: {
   79:     uint32_t base;
   80:     qemu_irq parent_irq[NCPU];
   81:     int enabled;
   82:     int cpu_enabled[NCPU];
   83: 
   84:     gic_irq_state irq_state[GIC_NIRQ];
   85: #ifndef NVIC
   86:     int irq_target[GIC_NIRQ];
   87: #endif
   88:     int priority1[32][NCPU];
   89:     int priority2[GIC_NIRQ - 32];
   90:     int last_active[GIC_NIRQ][NCPU];
   91: 
   92:     int priority_mask[NCPU];
   93:     int running_irq[NCPU];
   94:     int running_priority[NCPU];
   95:     int current_pending[NCPU];
   96: 
   97:     qemu_irq *in;
   98: #ifdef NVIC
   99:     void *nvic;
  100: #endif
  101: } gic_state;
  102: 
  103: /* TODO: Many places that call this routine could be optimized.  */
  104: /* Update interrupt status after enabled or pending bits have been changed.  */
  105: static void gic_update(gic_state *s)
  106: {
  107:     int best_irq;
  108:     int best_prio;
  109:     int irq;
  110:     int level;
  111:     int cpu;
  112:     int cm;
  113: 
  114:     for (cpu = 0; cpu < NCPU; cpu++) {
  115:         cm = 1 << cpu;
  116:         s->current_pending[cpu] = 1023;
  117:         if (!s->enabled || !s->cpu_enabled[cpu]) {
  118:             qemu_irq_lower(s->parent_irq[cpu]);
  119:             return;
  120:         }
  121:         best_prio = 0x100;
  122:         best_irq = 1023;
  123:         for (irq = 0; irq < GIC_NIRQ; irq++) {
  124:             if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq, cm)) {
  125:                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
  126:                     best_prio = GIC_GET_PRIORITY(irq, cpu);
  127:                     best_irq = irq;
  128:                 }
  129:             }
  130:         }
  131:         level = 0;
  132:         if (best_prio <= s->priority_mask[cpu]) {
  133:             s->current_pending[cpu] = best_irq;
  134:             if (best_prio < s->running_priority[cpu]) {
  135:                 DPRINTF("Raised pending IRQ %d\n", best_irq);
  136:                 level = 1;
  137:             }
  138:         }
  139:         qemu_set_irq(s->parent_irq[cpu], level);
  140:     }
  141: }
  142: 
  143: static void __attribute__((unused))
  144: gic_set_pending_private(gic_state *s, int cpu, int irq)
  145: {
  146:     int cm = 1 << cpu;
  147: 
  148:     if (GIC_TEST_PENDING(irq, cm))
  149:         return;
  150: 
  151:     DPRINTF("Set %d pending cpu %d\n", irq, cpu);
  152:     GIC_SET_PENDING(irq, cm);
  153:     gic_update(s);
  154: }
  155: 
  156: /* Process a change in an external IRQ input.  */
  157: static void gic_set_irq(void *opaque, int irq, int level)
  158: {
  159:     gic_state *s = (gic_state *)opaque;
  160:     /* The first external input line is internal interrupt 32.  */
  161:     irq += 32;
  162:     if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
  163:         return;
  164: 
  165:     if (level) {
  166:         GIC_SET_LEVEL(irq, ALL_CPU_MASK);
  167:         if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
  168:             DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
  169:             GIC_SET_PENDING(irq, GIC_TARGET(irq));
  170:         }
  171:     } else {
  172:         GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
  173:     }
  174:     gic_update(s);
  175: }
  176: 
  177: static void gic_set_running_irq(gic_state *s, int cpu, int irq)
  178: {
  179:     s->running_irq[cpu] = irq;
  180:     if (irq == 1023) {
  181:         s->running_priority[cpu] = 0x100;
  182:     } else {
  183:         s->running_priority[cpu] = GIC_GET_PRIORITY(irq, cpu);
  184:     }
  185:     gic_update(s);
  186: }
  187: 
  188: static uint32_t gic_acknowledge_irq(gic_state *s, int cpu)
  189: {
  190:     int new_irq;
  191:     int cm = 1 << cpu;
  192:     new_irq = s->current_pending[cpu];
  193:     if (new_irq == 1023
  194:             || GIC_GET_PRIORITY(new_irq, cpu) >= s->running_priority[cpu]) {
  195:         DPRINTF("ACK no pending IRQ\n");
  196:         return 1023;
  197:     }
  198:     s->last_active[new_irq][cpu] = s->running_irq[cpu];
  199:     /* Clear pending flags for both level and edge triggered interrupts.
  200:        Level triggered IRQs will be reasserted once they become inactive.  */
  201:     GIC_CLEAR_PENDING(new_irq, GIC_TEST_MODEL(new_irq) ? ALL_CPU_MASK : cm);
  202:     gic_set_running_irq(s, cpu, new_irq);
  203:     DPRINTF("ACK %d\n", new_irq);
  204:     return new_irq;
  205: }
  206: 
  207: static void gic_complete_irq(gic_state * s, int cpu, int irq)
  208: {
  209:     int update = 0;
  210:     int cm = 1 << cpu;
  211:     DPRINTF("EOI %d\n", irq);
  212:     if (s->running_irq[cpu] == 1023)
  213:         return; /* No active IRQ.  */
  214:     if (irq != 1023) {
  215:         /* Mark level triggered interrupts as pending if they are still
  216:            raised.  */
  217:         if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq)
  218:                 && GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
  219:             DPRINTF("Set %d pending mask %x\n", irq, cm);
  220:             GIC_SET_PENDING(irq, cm);
  221:             update = 1;
  222:         }
  223:     }
  224:     if (irq != s->running_irq[cpu]) {
  225:         /* Complete an IRQ that is not currently running.  */
  226:         int tmp = s->running_irq[cpu];
  227:         while (s->last_active[tmp][cpu] != 1023) {
  228:             if (s->last_active[tmp][cpu] == irq) {
  229:                 s->last_active[tmp][cpu] = s->last_active[irq][cpu];
  230:                 break;
  231:             }
  232:             tmp = s->last_active[tmp][cpu];
  233:         }
  234:         if (update) {
  235:             gic_update(s);
  236:         }
  237:     } else {
  238:         /* Complete the current running IRQ.  */
  239:         gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]);
  240:     }
  241: }
  242: 
  243: static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
  244: {
  245:     gic_state *s = (gic_state *)opaque;
  246:     uint32_t res;
  247:     int irq;
  248:     int i;
  249:     int cpu;
  250:     int cm;
  251:     int mask;
  252: 
  253:     cpu = gic_get_current_cpu();
  254:     cm = 1 << cpu;
  255:     offset -= s->base + GIC_DIST_OFFSET;
  256:     if (offset < 0x100) {
  257: #ifndef NVIC
  258:         if (offset == 0)
  259:             return s->enabled;
  260:         if (offset == 4)
  261:             return ((GIC_NIRQ / 32) - 1) | ((NCPU - 1) << 5);
  262:         if (offset < 0x08)
  263:             return 0;
  264: #endif
  265:         goto bad_reg;
  266:     } else if (offset < 0x200) {
  267:         /* Interrupt Set/Clear Enable.  */
  268:         if (offset < 0x180)
  269:             irq = (offset - 0x100) * 8;
  270:         else
  271:             irq = (offset - 0x180) * 8;
  272:         irq += GIC_BASE_IRQ;
  273:         if (irq >= GIC_NIRQ)
  274:             goto bad_reg;
  275:         res = 0;
  276:         for (i = 0; i < 8; i++) {
  277:             if (GIC_TEST_ENABLED(irq + i)) {
  278:                 res |= (1 << i);
  279:             }
  280:         }
  281:     } else if (offset < 0x300) {
  282:         /* Interrupt Set/Clear Pending.  */
  283:         if (offset < 0x280)
  284:             irq = (offset - 0x200) * 8;
  285:         else
  286:             irq = (offset - 0x280) * 8;
  287:         irq += GIC_BASE_IRQ;
  288:         if (irq >= GIC_NIRQ)
  289:             goto bad_reg;
  290:         res = 0;
  291:         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
  292:         for (i = 0; i < 8; i++) {
  293:             if (GIC_TEST_PENDING(irq + i, mask)) {
  294:                 res |= (1 << i);
  295:             }
  296:         }
  297:     } else if (offset < 0x400) {
  298:         /* Interrupt Active.  */
  299:         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
  300:         if (irq >= GIC_NIRQ)
  301:             goto bad_reg;
  302:         res = 0;
  303:         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
  304:         for (i = 0; i < 8; i++) {
  305:             if (GIC_TEST_ACTIVE(irq + i, mask)) {
  306:                 res |= (1 << i);
  307:             }
  308:         }
  309:     } else if (offset < 0x800) {
  310:         /* Interrupt Priority.  */
  311:         irq = (offset - 0x400) + GIC_BASE_IRQ;
  312:         if (irq >= GIC_NIRQ)
  313:             goto bad_reg;
  314:         res = GIC_GET_PRIORITY(irq, cpu);
  315: #ifndef NVIC
  316:     } else if (offset < 0xc00) {
  317:         /* Interrupt CPU Target.  */
  318:         irq = (offset - 0x800) + GIC_BASE_IRQ;
  319:         if (irq >= GIC_NIRQ)
  320:             goto bad_reg;
  321:         if (irq >= 29 && irq <= 31) {
  322:             res = cm;
  323:         } else {
  324:             res = GIC_TARGET(irq);
  325:         }
  326:     } else if (offset < 0xf00) {
  327:         /* Interrupt Configuration.  */
  328:         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
  329:         if (irq >= GIC_NIRQ)
  330:             goto bad_reg;
  331:         res = 0;
  332:         for (i = 0; i < 4; i++) {
  333:             if (GIC_TEST_MODEL(irq + i))
  334:                 res |= (1 << (i * 2));
  335:             if (GIC_TEST_TRIGGER(irq + i))
  336:                 res |= (2 << (i * 2));
  337:         }
  338: #endif
  339:     } else if (offset < 0xfe0) {
  340:         goto bad_reg;
  341:     } else /* offset >= 0xfe0 */ {
  342:         if (offset & 3) {
  343:             res = 0;
  344:         } else {
  345:             res = gic_id[(offset - 0xfe0) >> 2];
  346:         }
  347:     }
  348:     return res;
  349: bad_reg:
  350:     cpu_abort(cpu_single_env, "gic_dist_readb: Bad offset %x\n", (int)offset);
  351:     return 0;
  352: }
  353: 
  354: static uint32_t gic_dist_readw(void *opaque, target_phys_addr_t offset)
  355: {
  356:     uint32_t val;
  357:     val = gic_dist_readb(opaque, offset);
  358:     val |= gic_dist_readb(opaque, offset + 1) << 8;
  359:     return val;
  360: }
  361: 
  362: static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
  363: {
  364:     uint32_t val;
  365: #ifdef NVIC
  366:     gic_state *s = (gic_state *)opaque;
  367:     uint32_t addr;
  368:     addr = offset - s->base;
  369:     if (addr < 0x100 || addr > 0xd00)
  370:         return nvic_readl(s->nvic, addr);
  371: #endif
  372:     val = gic_dist_readw(opaque, offset);
  373:     val |= gic_dist_readw(opaque, offset + 2) << 16;
  374:     return val;
  375: }
  376: 
  377: static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
  378:                             uint32_t value)
  379: {
  380:     gic_state *s = (gic_state *)opaque;
  381:     int irq;
  382:     int i;
  383:     int cpu;
  384: 
  385:     cpu = gic_get_current_cpu();
  386:     offset -= s->base + GIC_DIST_OFFSET;
  387:     if (offset < 0x100) {
  388: #ifdef NVIC
  389:         goto bad_reg;
  390: #else
  391:         if (offset == 0) {
  392:             s->enabled = (value & 1);
  393:             DPRINTF("Distribution %sabled\n", s->enabled ? "En" : "Dis");
  394:         } else if (offset < 4) {
  395:             /* ignored.  */
  396:         } else {
  397:             goto bad_reg;
  398:         }
  399: #endif
  400:     } else if (offset < 0x180) {
  401:         /* Interrupt Set Enable.  */
  402:         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
  403:         if (irq >= GIC_NIRQ)
  404:             goto bad_reg;
  405:         if (irq < 16)
  406:           value = 0xff;
  407:         for (i = 0; i < 8; i++) {
  408:             if (value & (1 << i)) {
  409:                 int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
  410:                 if (!GIC_TEST_ENABLED(irq + i))
  411:                     DPRINTF("Enabled IRQ %d\n", irq + i);
  412:                 GIC_SET_ENABLED(irq + i);
  413:                 /* If a raised level triggered IRQ enabled then mark
  414:                    is as pending.  */
  415:                 if (GIC_TEST_LEVEL(irq + i, mask)
  416:                         && !GIC_TEST_TRIGGER(irq + i)) {
  417:                     DPRINTF("Set %d pending mask %x\n", irq + i, mask);
  418:                     GIC_SET_PENDING(irq + i, mask);
  419:                 }
  420:             }
  421:         }
  422:     } else if (offset < 0x200) {
  423:         /* Interrupt Clear Enable.  */
  424:         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
  425:         if (irq >= GIC_NIRQ)
  426:             goto bad_reg;
  427:         if (irq < 16)
  428:           value = 0;
  429:         for (i = 0; i < 8; i++) {
  430:             if (value & (1 << i)) {
  431:                 if (GIC_TEST_ENABLED(irq + i))
  432:                     DPRINTF("Disabled IRQ %d\n", irq + i);
  433:                 GIC_CLEAR_ENABLED(irq + i);
  434:             }
  435:         }
  436:     } else if (offset < 0x280) {
  437:         /* Interrupt Set Pending.  */
  438:         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
  439:         if (irq >= GIC_NIRQ)
  440:             goto bad_reg;
  441:         if (irq < 16)
  442:           irq = 0;
  443: 
  444:         for (i = 0; i < 8; i++) {
  445:             if (value & (1 << i)) {
  446:                 GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
  447:             }
  448:         }
  449:     } else if (offset < 0x300) {
  450:         /* Interrupt Clear Pending.  */
  451:         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
  452:         if (irq >= GIC_NIRQ)
  453:             goto bad_reg;
  454:         for (i = 0; i < 8; i++) {
  455:             /* ??? This currently clears the pending bit for all CPUs, even
  456:                for per-CPU interrupts.  It's unclear whether this is the
  457:                corect behavior.  */
  458:             if (value & (1 << i)) {
  459:                 GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
  460:             }
  461:         }
  462:     } else if (offset < 0x400) {
  463:         /* Interrupt Active.  */
  464:         goto bad_reg;
  465:     } else if (offset < 0x800) {
  466:         /* Interrupt Priority.  */
  467:         irq = (offset - 0x400) + GIC_BASE_IRQ;
  468:         if (irq >= GIC_NIRQ)
  469:             goto bad_reg;
  470:         if (irq < 32) {
  471:             s->priority1[irq][cpu] = value;
  472:         } else {
  473:             s->priority2[irq - 32] = value;
  474:         }
  475: #ifndef NVIC
  476:     } else if (offset < 0xc00) {
  477:         /* Interrupt CPU Target.  */
  478:         irq = (offset - 0x800) + GIC_BASE_IRQ;
  479:         if (irq >= GIC_NIRQ)
  480:             goto bad_reg;
  481:         if (irq < 29)
  482:             value = 0;
  483:         else if (irq < 32)
  484:             value = ALL_CPU_MASK;
  485:         s->irq_target[irq] = value & ALL_CPU_MASK;
  486:     } else if (offset < 0xf00) {
  487:         /* Interrupt Configuration.  */
  488:         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
  489:         if (irq >= GIC_NIRQ)
  490:             goto bad_reg;
  491:         if (irq < 32)
  492:             value |= 0xaa;
  493:         for (i = 0; i < 4; i++) {
  494:             if (value & (1 << (i * 2))) {
  495:                 GIC_SET_MODEL(irq + i);
  496:             } else {
  497:                 GIC_CLEAR_MODEL(irq + i);
  498:             }
  499:             if (value & (2 << (i * 2))) {
  500:                 GIC_SET_TRIGGER(irq + i);
  501:             } else {
  502:                 GIC_CLEAR_TRIGGER(irq + i);
  503:             }
  504:         }
  505: #endif
  506:     } else {
  507:         /* 0xf00 is only handled for 32-bit writes.  */
  508:         goto bad_reg;
  509:     }
  510:     gic_update(s);
  511:     return;
  512: bad_reg:
  513:     cpu_abort(cpu_single_env, "gic_dist_writeb: Bad offset %x\n", (int)offset);
  514: }
  515: 
  516: static void gic_dist_writew(void *opaque, target_phys_addr_t offset,
  517:                             uint32_t value)
  518: {
  519:     gic_dist_writeb(opaque, offset, value & 0xff);
  520:     gic_dist_writeb(opaque, offset + 1, value >> 8);
  521: }
  522: 
  523: static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
  524:                             uint32_t value)
  525: {
  526:     gic_state *s = (gic_state *)opaque;
  527: #ifdef NVIC
  528:     uint32_t addr;
  529:     addr = offset - s->base;
  530:     if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) {
  531:         nvic_writel(s->nvic, addr, value);