qemu/hw/arm_gic.c
<<
>>
Prefs
   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, ...) \
  18do { printf("arm_gic: " fmt , ## __VA_ARGS__); } while (0)
  19#else
  20#define DPRINTF(fmt, ...) do {} while(0)
  21#endif
  22
  23#ifdef NVIC
  24static 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
  30static const uint8_t gic_id[] =
  31{ 0x90, 0x13, 0x04, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
  32#define GIC_BASE_IRQ    0
  33#endif
  34
  35#define FROM_SYSBUSGIC(type, dev) \
  36    DO_UPCAST(type, gic, FROM_SYSBUS(gic_state, dev))
  37
  38typedef struct gic_irq_state
  39{
  40    /* ??? The documentation seems to imply the enable bits are global, even
  41       for per-cpu interrupts.  This seems strange.  */
  42    unsigned enabled:1;
  43    unsigned pending:NCPU;
  44    unsigned active:NCPU;
  45    unsigned level:NCPU;
  46    unsigned model:1; /* 0 = N:N, 1 = 1:N */
  47    unsigned trigger:1; /* nonzero = edge triggered.  */
  48} gic_irq_state;
  49
  50#define ALL_CPU_MASK ((1 << NCPU) - 1)
  51#if NCPU > 1
  52#define NUM_CPU(s) ((s)->num_cpu)
  53#else
  54#define NUM_CPU(s) 1
  55#endif
  56
  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
  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)
  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
  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)
  71#define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0)
  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
  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
  82
  83typedef struct gic_state
  84{
  85    SysBusDevice busdev;
  86    qemu_irq parent_irq[NCPU];
  87    int enabled;
  88    int cpu_enabled[NCPU];
  89
  90    gic_irq_state irq_state[GIC_NIRQ];
  91#ifndef NVIC
  92    int irq_target[GIC_NIRQ];
  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
 103#if NCPU > 1
 104    int num_cpu;
 105#endif
 106
 107    int iomemtype;
 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.  */
 112static void gic_update(gic_state *s)
 113{
 114    int best_irq;
 115    int best_prio;
 116    int irq;
 117    int level;
 118    int cpu;
 119    int cm;
 120
 121    for (cpu = 0; cpu < NUM_CPU(s); cpu++) {
 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                }
 136            }
 137        }
 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            }
 145        }
 146        qemu_set_irq(s->parent_irq[cpu], level);
 147    }
 148}
 149
 150static void __attribute__((unused))
 151gic_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.  */
 164static 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;
 169    if (level == GIC_TEST_LEVEL(irq, ALL_CPU_MASK))
 170        return;
 171
 172    if (level) {
 173        GIC_SET_LEVEL(irq, ALL_CPU_MASK);
 174        if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
 175            DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
 176            GIC_SET_PENDING(irq, GIC_TARGET(irq));
 177        }
 178    } else {
 179        GIC_CLEAR_LEVEL(irq, ALL_CPU_MASK);
 180    }
 181    gic_update(s);
 182}
 183
 184static void gic_set_running_irq(gic_state *s, int cpu, int irq)
 185{
 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    }
 192    gic_update(s);
 193}
 194
 195static uint32_t gic_acknowledge_irq(gic_state *s, int cpu)
 196{
 197    int new_irq;
 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]) {
 202        DPRINTF("ACK no pending IRQ\n");
 203        return 1023;
 204    }
 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);
 210    DPRINTF("ACK %d\n", new_irq);
 211    return new_irq;
 212}
 213
 214static void gic_complete_irq(gic_state * s, int cpu, int irq)
 215{
 216    int update = 0;
 217    int cm = 1 << cpu;
 218    DPRINTF("EOI %d\n", irq);
 219    if (s->running_irq[cpu] == 1023)
 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)
 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);
 228            update = 1;
 229        }
 230    }
 231    if (irq != s->running_irq[cpu]) {
 232        /* Complete an IRQ that is not currently running.  */
 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];
 237                break;
 238            }
 239            tmp = s->last_active[tmp][cpu];
 240        }
 241        if (update) {
 242            gic_update(s);
 243        }
 244    } else {
 245        /* Complete the current running IRQ.  */
 246        gic_set_running_irq(s, cpu, s->last_active[s->running_irq[cpu]][cpu]);
 247    }
 248}
 249
 250static 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;
 256    int cpu;
 257    int cm;
 258    int mask;
 259
 260    cpu = gic_get_current_cpu();
 261    cm = 1 << cpu;
 262    if (offset < 0x100) {
 263#ifndef NVIC
 264        if (offset == 0)
 265            return s->enabled;
 266        if (offset == 4)
 267            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
 268        if (offset < 0x08)
 269            return 0;
 270#endif
 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;
 278        irq += GIC_BASE_IRQ;
 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;
 293        irq += GIC_BASE_IRQ;
 294        if (irq >= GIC_NIRQ)
 295            goto bad_reg;
 296        res = 0;
 297        mask = (irq < 32) ?  cm : ALL_CPU_MASK;
 298        for (i = 0; i < 8; i++) {
 299            if (GIC_TEST_PENDING(irq + i, mask)) {
 300                res |= (1 << i);
 301            }
 302        }
 303    } else if (offset < 0x400) {
 304        /* Interrupt Active.  */
 305        irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
 306        if (irq >= GIC_NIRQ)
 307            goto bad_reg;
 308        res = 0;
 309        mask = (irq < 32) ?  cm : ALL_CPU_MASK;
 310        for (i = 0; i < 8; i++) {
 311            if (GIC_TEST_ACTIVE(irq + i, mask)) {
 312                res |= (1 << i);
 313            }
 314        }
 315    } else if (offset < 0x800) {
 316        /* Interrupt Priority.  */
 317        irq = (offset - 0x400) + GIC_BASE_IRQ;
 318        if (irq >= GIC_NIRQ)
 319            goto bad_reg;
 320        res = GIC_GET_PRIORITY(irq, cpu);
 321#ifndef NVIC
 322    } else if (offset < 0xc00) {
 323        /* Interrupt CPU Target.  */
 324        irq = (offset - 0x800) + GIC_BASE_IRQ;
 325        if (irq >= GIC_NIRQ)
 326            goto bad_reg;
 327        if (irq >= 29 && irq <= 31) {
 328            res = cm;
 329        } else {
 330            res = GIC_TARGET(irq);
 331        }
 332    } else if (offset < 0xf00) {
 333        /* Interrupt Configuration.  */
 334        irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
 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        }
 344#endif
 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;
 355bad_reg:
 356    hw_error("gic_dist_readb: Bad offset %x\n", (int)offset);
 357    return 0;
 358}
 359
 360static 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
 368static uint32_t gic_dist_readl(void *opaque, target_phys_addr_t offset)
 369{
 370    uint32_t val;
 371#ifdef NVIC
 372    gic_state *s = (gic_state *)opaque;
 373    uint32_t addr;
 374    addr = offset;
 375    if (addr < 0x100 || addr > 0xd00)
 376        return nvic_readl(s, addr);
 377#endif
 378    val = gic_dist_readw(opaque, offset);
 379    val |= gic_dist_readw(opaque, offset + 2) << 16;
 380    return val;
 381}
 382
 383static 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;
 389    int cpu;
 390
 391    cpu = gic_get_current_cpu();
 392    if (offset < 0x100) {
 393#ifdef NVIC
 394        goto bad_reg;
 395#else
 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        }
 404#endif
 405    } else if (offset < 0x180) {
 406        /* Interrupt Set Enable.  */
 407        irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
 408        if (irq >= GIC_NIRQ)
 409            goto bad_reg;
 410        if (irq < 16)
 411          value = 0xff;
 412        for (i = 0; i < 8; i++) {
 413            if (value & (1 << i)) {
 414                int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
 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.  */
 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                }
 425            }
 426        }
 427    } else if (offset < 0x200) {
 428        /* Interrupt Clear Enable.  */
 429        irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
 430        if (irq >= GIC_NIRQ)
 431            goto bad_reg;
 432        if (irq < 16)
 433          value = 0;
 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.  */
 443        irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
 444        if (irq >= GIC_NIRQ)
 445            goto bad_reg;
 446        if (irq < 16)
 447          irq = 0;
 448
 449        for (i = 0; i < 8; i++) {
 450            if (value & (1 << i)) {
 451                GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
 452            }
 453        }
 454    } else if (offset < 0x300) {
 455        /* Interrupt Clear Pending.  */
 456        irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
 457        if (irq >= GIC_NIRQ)
 458            goto bad_reg;
 459        for (i = 0; i < 8; i++) {
 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.  */
 463            if (value & (1 << i)) {
 464                GIC_CLEAR_PENDING(irq + i, ALL_CPU_MASK);
 465            }
 466        }
 467    } else if (offset < 0x400) {
 468        /* Interrupt Active.  */
 469        goto bad_reg;
 470    } else if (offset < 0x800) {
 471        /* Interrupt Priority.  */
 472        irq = (offset - 0x400) + GIC_BASE_IRQ;
 473        if (irq >= GIC_NIRQ)
 474            goto bad_reg;
 475        if (irq < 32) {
 476            s->priority1[irq][cpu] = value;
 477        } else {
 478            s->priority2[irq - 32] = value;
 479        }
 480#ifndef NVIC
 481    } else if (offset < 0xc00) {
 482        /* Interrupt CPU Target.  */
 483        irq = (offset - 0x800) + GIC_BASE_IRQ;
 484        if (irq >= GIC_NIRQ)
 485            goto bad_reg;
 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;
 491    } else if (offset < 0xf00) {
 492        /* Interrupt Configuration.  */
 493        irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
 494        if (irq >= GIC_NIRQ)
 495            goto bad_reg;
 496        if (irq < 32)
 497            value |= 0xaa;
 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        }
 510#endif
 511    } else {
 512        /* 0xf00 is only handled for 32-bit writes.  */
 513        goto bad_reg;
 514    }
 515    gic_update(s);
 516    return;
 517bad_reg:
 518    hw_error("gic_dist_writeb: Bad offset %x\n", (int)offset);
 519}
 520
 521static 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
 528static void gic_dist_writel(void *opaque, target_phys_addr_t offset,
 529                            uint32_t value)
 530{
 531    gic_state *s = (gic_state *)opaque;
 532#ifdef NVIC
 533    uint32_t addr;
 534    addr = offset;
 535    if (addr < 0x100 || (addr > 0xd00 && addr != 0xf00)) {
 536        nvic_writel(s, addr, value);
 537        return;
 538    }
 539#endif
 540    if (offset == 0xf00) {
 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    }
 566    gic_dist_writew(opaque, offset, value & 0xffff);
 567    gic_dist_writew(opaque, offset + 2, value >> 16);
 568}
 569
 570static CPUReadMemoryFunc * const gic_dist_readfn[] = {
 571   gic_dist_readb,
 572   gic_dist_readw,
 573   gic_dist_readl
 574};
 575
 576static CPUWriteMemoryFunc * const gic_dist_writefn[] = {
 577   gic_dist_writeb,
 578   gic_dist_writew,
 579   gic_dist_writel
 580};
 581
 582#ifndef NVIC
 583static uint32_t gic_cpu_read(gic_state *s, int cpu, int offset)
 584{
 585    switch (offset) {
 586    case 0x00: /* Control */
 587        return s->cpu_enabled[cpu];
 588    case 0x04: /* Priority mask */
 589        return s->priority_mask[cpu];
 590    case 0x08: /* Binary Point */
 591        /* ??? Not implemented.  */
 592        return 0;
 593    case 0x0c: /* Acknowledge */
 594        return gic_acknowledge_irq(s, cpu);
 595    case 0x14: /* Runing Priority */
 596        return s->running_priority[cpu];
 597    case 0x18: /* Highest Pending Interrupt */
 598        return s->current_pending[cpu];
 599    default:
 600        hw_error("gic_cpu_read: Bad offset %x\n", (int)offset);
 601        return 0;
 602    }
 603}
 604
 605static void gic_cpu_write(gic_state *s, int cpu, int offset, uint32_t value)
 606{
 607    switch (offset) {
 608    case 0x00: /* Control */
 609        s->cpu_enabled[cpu] = (value & 1);
 610        DPRINTF("CPU %d %sabled\n", cpu, s->cpu_enabled ? "En" : "Dis");
 611        break;
 612    case 0x04: /* Priority mask */
 613        s->priority_mask[cpu] = (value & 0xff);
 614        break;
 615    case 0x08: /* Binary Point */
 616        /* ??? Not implemented.  */
 617        break;
 618    case 0x10: /* End Of Interrupt */
 619        return gic_complete_irq(s, cpu, value & 0x3ff);
 620    default:
 621        hw_error("gic_cpu_write: Bad offset %x\n", (int)offset);
 622        return;
 623    }
 624    gic_update(s);
 625}
 626#endif
 627
 628static void gic_reset(gic_state *s)
 629{
 630    int i;
 631    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
 632    for (i = 0 ; i < NUM_CPU(s); i++) {
 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++) {
 645        GIC_SET_ENABLED(i);
 646        GIC_SET_TRIGGER(i);
 647    }
 648#ifdef NVIC
 649    /* The NVIC is always enabled.  */
 650    s->enabled = 1;
 651#else
 652    s->enabled = 0;
 653#endif
 654}
 655
 656static 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);
 663    for (i = 0; i < NUM_CPU(s); i++) {
 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
 690static 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);
 700    for (i = 0; i < NUM_CPU(s); i++) {
 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
 729#if NCPU > 1
 730static void gic_init(gic_state *s, int num_cpu)
 731#else
 732static void gic_init(gic_state *s)
 733#endif
 734{
 735    int i;
 736
 737#if NCPU > 1
 738    s->num_cpu = num_cpu;
 739#endif
 740    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
 741    for (i = 0; i < NUM_CPU(s); i++) {
 742        sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
 743    }
 744    s->iomemtype = cpu_register_io_memory(gic_dist_readfn,
 745                                          gic_dist_writefn, s,
 746                                          DEVICE_NATIVE_ENDIAN);
 747    gic_reset(s);
 748    register_savevm(NULL, "arm_gic", -1, 1, gic_save, gic_load, s);
 749}
 750