qemu/hw/intc/armv7m_nvic.c
<<
>>
Prefs
   1/*
   2 * ARM Nested Vectored Interrupt Controller
   3 *
   4 * Copyright (c) 2006-2007 CodeSourcery.
   5 * Written by Paul Brook
   6 *
   7 * This code is licensed under the GPL.
   8 *
   9 * The ARMv7M System controller is fairly tightly tied in with the
  10 * NVIC.  Much of that is also implemented here.
  11 */
  12
  13#include "qemu/osdep.h"
  14#include "qapi/error.h"
  15#include "qemu-common.h"
  16#include "cpu.h"
  17#include "hw/sysbus.h"
  18#include "qemu/timer.h"
  19#include "hw/arm/arm.h"
  20#include "exec/address-spaces.h"
  21#include "gic_internal.h"
  22#include "qemu/log.h"
  23
  24typedef struct {
  25    GICState gic;
  26    struct {
  27        uint32_t control;
  28        uint32_t reload;
  29        int64_t tick;
  30        QEMUTimer *timer;
  31    } systick;
  32    MemoryRegion sysregmem;
  33    MemoryRegion gic_iomem_alias;
  34    MemoryRegion container;
  35    uint32_t num_irq;
  36} nvic_state;
  37
  38#define TYPE_NVIC "armv7m_nvic"
  39/**
  40 * NVICClass:
  41 * @parent_reset: the parent class' reset handler.
  42 *
  43 * A model of the v7M NVIC and System Controller
  44 */
  45typedef struct NVICClass {
  46    /*< private >*/
  47    ARMGICClass parent_class;
  48    /*< public >*/
  49    DeviceRealize parent_realize;
  50    void (*parent_reset)(DeviceState *dev);
  51} NVICClass;
  52
  53#define NVIC_CLASS(klass) \
  54    OBJECT_CLASS_CHECK(NVICClass, (klass), TYPE_NVIC)
  55#define NVIC_GET_CLASS(obj) \
  56    OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
  57#define NVIC(obj) \
  58    OBJECT_CHECK(nvic_state, (obj), TYPE_NVIC)
  59
  60static const uint8_t nvic_id[] = {
  61    0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
  62};
  63
  64/* qemu timers run at 1GHz.   We want something closer to 1MHz.  */
  65#define SYSTICK_SCALE 1000ULL
  66
  67#define SYSTICK_ENABLE    (1 << 0)
  68#define SYSTICK_TICKINT   (1 << 1)
  69#define SYSTICK_CLKSOURCE (1 << 2)
  70#define SYSTICK_COUNTFLAG (1 << 16)
  71
  72int system_clock_scale;
  73
  74/* Conversion factor from qemu timer to SysTick frequencies.  */
  75static inline int64_t systick_scale(nvic_state *s)
  76{
  77    if (s->systick.control & SYSTICK_CLKSOURCE)
  78        return system_clock_scale;
  79    else
  80        return 1000;
  81}
  82
  83static void systick_reload(nvic_state *s, int reset)
  84{
  85    if (reset)
  86        s->systick.tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
  87    s->systick.tick += (s->systick.reload + 1) * systick_scale(s);
  88    timer_mod(s->systick.timer, s->systick.tick);
  89}
  90
  91static void systick_timer_tick(void * opaque)
  92{
  93    nvic_state *s = (nvic_state *)opaque;
  94    s->systick.control |= SYSTICK_COUNTFLAG;
  95    if (s->systick.control & SYSTICK_TICKINT) {
  96        /* Trigger the interrupt.  */
  97        armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
  98    }
  99    if (s->systick.reload == 0) {
 100        s->systick.control &= ~SYSTICK_ENABLE;
 101    } else {
 102        systick_reload(s, 0);
 103    }
 104}
 105
 106static void systick_reset(nvic_state *s)
 107{
 108    s->systick.control = 0;
 109    s->systick.reload = 0;
 110    s->systick.tick = 0;
 111    timer_del(s->systick.timer);
 112}
 113
 114/* The external routines use the hardware vector numbering, ie. the first
 115   IRQ is #16.  The internal GIC routines use #32 as the first IRQ.  */
 116void armv7m_nvic_set_pending(void *opaque, int irq)
 117{
 118    nvic_state *s = (nvic_state *)opaque;
 119    if (irq >= 16)
 120        irq += 16;
 121    gic_set_pending_private(&s->gic, 0, irq);
 122}
 123
 124/* Make pending IRQ active.  */
 125int armv7m_nvic_acknowledge_irq(void *opaque)
 126{
 127    nvic_state *s = (nvic_state *)opaque;
 128    uint32_t irq;
 129
 130    irq = gic_acknowledge_irq(&s->gic, 0, false);
 131    if (irq == 1023)
 132        hw_error("Interrupt but no vector\n");
 133    if (irq >= 32)
 134        irq -= 16;
 135    return irq;
 136}
 137
 138void armv7m_nvic_complete_irq(void *opaque, int irq)
 139{
 140    nvic_state *s = (nvic_state *)opaque;
 141    if (irq >= 16)
 142        irq += 16;
 143    gic_complete_irq(&s->gic, 0, irq, false);
 144}
 145
 146static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 147{
 148    ARMCPU *cpu;
 149    uint32_t val;
 150    int irq;
 151
 152    switch (offset) {
 153    case 4: /* Interrupt Control Type.  */
 154        return (s->num_irq / 32) - 1;
 155    case 0x10: /* SysTick Control and Status.  */
 156        val = s->systick.control;
 157        s->systick.control &= ~SYSTICK_COUNTFLAG;
 158        return val;
 159    case 0x14: /* SysTick Reload Value.  */
 160        return s->systick.reload;
 161    case 0x18: /* SysTick Current Value.  */
 162        {
 163            int64_t t;
 164            if ((s->systick.control & SYSTICK_ENABLE) == 0)
 165                return 0;
 166            t = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 167            if (t >= s->systick.tick)
 168                return 0;
 169            val = ((s->systick.tick - (t + 1)) / systick_scale(s)) + 1;
 170            /* The interrupt in triggered when the timer reaches zero.
 171               However the counter is not reloaded until the next clock
 172               tick.  This is a hack to return zero during the first tick.  */
 173            if (val > s->systick.reload)
 174                val = 0;
 175            return val;
 176        }
 177    case 0x1c: /* SysTick Calibration Value.  */
 178        return 10000;
 179    case 0xd00: /* CPUID Base.  */
 180        cpu = ARM_CPU(current_cpu);
 181        return cpu->midr;
 182    case 0xd04: /* Interrupt Control State.  */
 183        /* VECTACTIVE */
 184        val = s->gic.running_irq[0];
 185        if (val == 1023) {
 186            val = 0;
 187        } else if (val >= 32) {
 188            val -= 16;
 189        }
 190        /* RETTOBASE */
 191        if (s->gic.running_irq[0] == 1023
 192                || s->gic.last_active[s->gic.running_irq[0]][0] == 1023) {
 193            val |= (1 << 11);
 194        }
 195        /* VECTPENDING */
 196        if (s->gic.current_pending[0] != 1023)
 197            val |= (s->gic.current_pending[0] << 12);
 198        /* ISRPENDING */
 199        for (irq = 32; irq < s->num_irq; irq++) {
 200            if (s->gic.irq_state[irq].pending) {
 201                val |= (1 << 22);
 202                break;
 203            }
 204        }
 205        /* PENDSTSET */
 206        if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
 207            val |= (1 << 26);
 208        /* PENDSVSET */
 209        if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending)
 210            val |= (1 << 28);
 211        /* NMIPENDSET */
 212        if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending)
 213            val |= (1 << 31);
 214        return val;
 215    case 0xd08: /* Vector Table Offset.  */
 216        cpu = ARM_CPU(current_cpu);
 217        return cpu->env.v7m.vecbase;
 218    case 0xd0c: /* Application Interrupt/Reset Control.  */
 219        return 0xfa050000;
 220    case 0xd10: /* System Control.  */
 221        /* TODO: Implement SLEEPONEXIT.  */
 222        return 0;
 223    case 0xd14: /* Configuration Control.  */
 224        /* TODO: Implement Configuration Control bits.  */
 225        return 0;
 226    case 0xd24: /* System Handler Status.  */
 227        val = 0;
 228        if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
 229        if (s->gic.irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1);
 230        if (s->gic.irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3);
 231        if (s->gic.irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7);
 232        if (s->gic.irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8);
 233        if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10);
 234        if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11);
 235        if (s->gic.irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12);
 236        if (s->gic.irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13);
 237        if (s->gic.irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14);
 238        if (s->gic.irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15);
 239        if (s->gic.irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16);
 240        if (s->gic.irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17);
 241        if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18);
 242        return val;
 243    case 0xd28: /* Configurable Fault Status.  */
 244        /* TODO: Implement Fault Status.  */
 245        qemu_log_mask(LOG_UNIMP, "Configurable Fault Status unimplemented\n");
 246        return 0;
 247    case 0xd2c: /* Hard Fault Status.  */
 248    case 0xd30: /* Debug Fault Status.  */
 249    case 0xd34: /* Mem Manage Address.  */
 250    case 0xd38: /* Bus Fault Address.  */
 251    case 0xd3c: /* Aux Fault Status.  */
 252        /* TODO: Implement fault status registers.  */
 253        qemu_log_mask(LOG_UNIMP, "Fault status registers unimplemented\n");
 254        return 0;
 255    case 0xd40: /* PFR0.  */
 256        return 0x00000030;
 257    case 0xd44: /* PRF1.  */
 258        return 0x00000200;
 259    case 0xd48: /* DFR0.  */
 260        return 0x00100000;
 261    case 0xd4c: /* AFR0.  */
 262        return 0x00000000;
 263    case 0xd50: /* MMFR0.  */
 264        return 0x00000030;
 265    case 0xd54: /* MMFR1.  */
 266        return 0x00000000;
 267    case 0xd58: /* MMFR2.  */
 268        return 0x00000000;
 269    case 0xd5c: /* MMFR3.  */
 270        return 0x00000000;
 271    case 0xd60: /* ISAR0.  */
 272        return 0x01141110;
 273    case 0xd64: /* ISAR1.  */
 274        return 0x02111000;
 275    case 0xd68: /* ISAR2.  */
 276        return 0x21112231;
 277    case 0xd6c: /* ISAR3.  */
 278        return 0x01111110;
 279    case 0xd70: /* ISAR4.  */
 280        return 0x01310102;
 281    /* TODO: Implement debug registers.  */
 282    default:
 283        qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
 284        return 0;
 285    }
 286}
 287
 288static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
 289{
 290    ARMCPU *cpu;
 291    uint32_t oldval;
 292    switch (offset) {
 293    case 0x10: /* SysTick Control and Status.  */
 294        oldval = s->systick.control;
 295        s->systick.control &= 0xfffffff8;
 296        s->systick.control |= value & 7;
 297        if ((oldval ^ value) & SYSTICK_ENABLE) {
 298            int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 299            if (value & SYSTICK_ENABLE) {
 300                if (s->systick.tick) {
 301                    s->systick.tick += now;
 302                    timer_mod(s->systick.timer, s->systick.tick);
 303                } else {
 304                    systick_reload(s, 1);
 305                }
 306            } else {
 307                timer_del(s->systick.timer);
 308                s->systick.tick -= now;
 309                if (s->systick.tick < 0)
 310                  s->systick.tick = 0;
 311            }
 312        } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
 313            /* This is a hack. Force the timer to be reloaded
 314               when the reference clock is changed.  */
 315            systick_reload(s, 1);
 316        }
 317        break;
 318    case 0x14: /* SysTick Reload Value.  */
 319        s->systick.reload = value;
 320        break;
 321    case 0x18: /* SysTick Current Value.  Writes reload the timer.  */
 322        systick_reload(s, 1);
 323        s->systick.control &= ~SYSTICK_COUNTFLAG;
 324        break;
 325    case 0xd04: /* Interrupt Control State.  */
 326        if (value & (1 << 31)) {
 327            armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI);
 328        }
 329        if (value & (1 << 28)) {
 330            armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV);
 331        } else if (value & (1 << 27)) {
 332            s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending = 0;
 333            gic_update(&s->gic);
 334        }
 335        if (value & (1 << 26)) {
 336            armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
 337        } else if (value & (1 << 25)) {
 338            s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending = 0;
 339            gic_update(&s->gic);
 340        }
 341        break;
 342    case 0xd08: /* Vector Table Offset.  */
 343        cpu = ARM_CPU(current_cpu);
 344        cpu->env.v7m.vecbase = value & 0xffffff80;
 345        break;
 346    case 0xd0c: /* Application Interrupt/Reset Control.  */
 347        if ((value >> 16) == 0x05fa) {
 348            if (value & 2) {
 349                qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
 350            }
 351            if (value & 5) {
 352                qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
 353            }
 354            if (value & 0x700) {
 355                qemu_log_mask(LOG_UNIMP, "PRIGROUP unimplemented\n");
 356            }
 357        }
 358        break;
 359    case 0xd10: /* System Control.  */
 360    case 0xd14: /* Configuration Control.  */
 361        /* TODO: Implement control registers.  */
 362        qemu_log_mask(LOG_UNIMP, "NVIC: SCR and CCR unimplemented\n");
 363        break;
 364    case 0xd24: /* System Handler Control.  */
 365        /* TODO: Real hardware allows you to set/clear the active bits
 366           under some circumstances.  We don't implement this.  */
 367        s->gic.irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
 368        s->gic.irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
 369        s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
 370        break;
 371    case 0xd28: /* Configurable Fault Status.  */
 372    case 0xd2c: /* Hard Fault Status.  */
 373    case 0xd30: /* Debug Fault Status.  */
 374    case 0xd34: /* Mem Manage Address.  */
 375    case 0xd38: /* Bus Fault Address.  */
 376    case 0xd3c: /* Aux Fault Status.  */
 377        qemu_log_mask(LOG_UNIMP,
 378                      "NVIC: fault status registers unimplemented\n");
 379        break;
 380    case 0xf00: /* Software Triggered Interrupt Register */
 381        if ((value & 0x1ff) < s->num_irq) {
 382            gic_set_pending_private(&s->gic, 0, value & 0x1ff);
 383        }
 384        break;
 385    default:
 386        qemu_log_mask(LOG_GUEST_ERROR,
 387                      "NVIC: Bad write offset 0x%x\n", offset);
 388    }
 389}
 390
 391static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
 392                                 unsigned size)
 393{
 394    nvic_state *s = (nvic_state *)opaque;
 395    uint32_t offset = addr;
 396    int i;
 397    uint32_t val;
 398
 399    switch (offset) {
 400    case 0xd18 ... 0xd23: /* System Handler Priority.  */
 401        val = 0;
 402        for (i = 0; i < size; i++) {
 403            val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8);
 404        }
 405        return val;
 406    case 0xfe0 ... 0xfff: /* ID.  */
 407        if (offset & 3) {
 408            return 0;
 409        }
 410        return nvic_id[(offset - 0xfe0) >> 2];
 411    }
 412    if (size == 4) {
 413        return nvic_readl(s, offset);
 414    }
 415    qemu_log_mask(LOG_GUEST_ERROR,
 416                  "NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
 417    return 0;
 418}
 419
 420static void nvic_sysreg_write(void *opaque, hwaddr addr,
 421                              uint64_t value, unsigned size)
 422{
 423    nvic_state *s = (nvic_state *)opaque;
 424    uint32_t offset = addr;
 425    int i;
 426
 427    switch (offset) {
 428    case 0xd18 ... 0xd23: /* System Handler Priority.  */
 429        for (i = 0; i < size; i++) {
 430            s->gic.priority1[(offset - 0xd14) + i][0] =
 431                (value >> (i * 8)) & 0xff;
 432        }
 433        gic_update(&s->gic);
 434        return;
 435    }
 436    if (size == 4) {
 437        nvic_writel(s, offset, value);
 438        return;
 439    }
 440    qemu_log_mask(LOG_GUEST_ERROR,
 441                  "NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
 442}
 443
 444static const MemoryRegionOps nvic_sysreg_ops = {
 445    .read = nvic_sysreg_read,
 446    .write = nvic_sysreg_write,
 447    .endianness = DEVICE_NATIVE_ENDIAN,
 448};
 449
 450static const VMStateDescription vmstate_nvic = {
 451    .name = "armv7m_nvic",
 452    .version_id = 1,
 453    .minimum_version_id = 1,
 454    .fields = (VMStateField[]) {
 455        VMSTATE_UINT32(systick.control, nvic_state),
 456        VMSTATE_UINT32(systick.reload, nvic_state),
 457        VMSTATE_INT64(systick.tick, nvic_state),
 458        VMSTATE_TIMER_PTR(systick.timer, nvic_state),
 459        VMSTATE_END_OF_LIST()
 460    }
 461};
 462
 463static void armv7m_nvic_reset(DeviceState *dev)
 464{
 465    nvic_state *s = NVIC(dev);
 466    NVICClass *nc = NVIC_GET_CLASS(s);
 467    nc->parent_reset(dev);
 468    /* Common GIC reset resets to disabled; the NVIC doesn't have
 469     * per-CPU interfaces so mark our non-existent CPU interface
 470     * as enabled by default, and with a priority mask which allows
 471     * all interrupts through.
 472     */
 473    s->gic.ctrl[0] = true;
 474    s->gic.priority_mask[0] = 0x100;
 475    /* The NVIC as a whole is always enabled. */
 476    s->gic.enabled = true;
 477    systick_reset(s);
 478}
 479
 480static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
 481{
 482    nvic_state *s = NVIC(dev);
 483    NVICClass *nc = NVIC_GET_CLASS(s);
 484    Error *local_err = NULL;
 485
 486    /* The NVIC always has only one CPU */
 487    s->gic.num_cpu = 1;
 488    /* Tell the common code we're an NVIC */
 489    s->gic.revision = 0xffffffff;
 490    s->num_irq = s->gic.num_irq;
 491    nc->parent_realize(dev, &local_err);
 492    if (local_err) {
 493        error_propagate(errp, local_err);
 494        return;
 495    }
 496    gic_init_irqs_and_distributor(&s->gic);
 497    /* The NVIC and system controller register area looks like this:
 498     *  0..0xff : system control registers, including systick
 499     *  0x100..0xcff : GIC-like registers
 500     *  0xd00..0xfff : system control registers
 501     * We use overlaying to put the GIC like registers
 502     * over the top of the system control register region.
 503     */
 504    memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
 505    /* The system register region goes at the bottom of the priority
 506     * stack as it covers the whole page.
 507     */
 508    memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
 509                          "nvic_sysregs", 0x1000);
 510    memory_region_add_subregion(&s->container, 0, &s->sysregmem);
 511    /* Alias the GIC region so we can get only the section of it
 512     * we need, and layer it on top of the system register region.
 513     */
 514    memory_region_init_alias(&s->gic_iomem_alias, OBJECT(s),
 515                             "nvic-gic", &s->gic.iomem,
 516                             0x100, 0xc00);
 517    memory_region_add_subregion_overlap(&s->container, 0x100,
 518                                        &s->gic_iomem_alias, 1);
 519    /* Map the whole thing into system memory at the location required
 520     * by the v7M architecture.
 521     */
 522    memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->container);
 523    s->systick.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s);
 524}
 525
 526static void armv7m_nvic_instance_init(Object *obj)
 527{
 528    /* We have a different default value for the num-irq property
 529     * than our superclass. This function runs after qdev init
 530     * has set the defaults from the Property array and before
 531     * any user-specified property setting, so just modify the
 532     * value in the GICState struct.
 533     */
 534    GICState *s = ARM_GIC_COMMON(obj);
 535    /* The ARM v7m may have anything from 0 to 496 external interrupt
 536     * IRQ lines. We default to 64. Other boards may differ and should
 537     * set the num-irq property appropriately.
 538     */
 539    s->num_irq = 64;
 540}
 541
 542static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
 543{
 544    NVICClass *nc = NVIC_CLASS(klass);
 545    DeviceClass *dc = DEVICE_CLASS(klass);
 546
 547    nc->parent_reset = dc->reset;
 548    nc->parent_realize = dc->realize;
 549    dc->vmsd  = &vmstate_nvic;
 550    dc->reset = armv7m_nvic_reset;
 551    dc->realize = armv7m_nvic_realize;
 552}
 553
 554static const TypeInfo armv7m_nvic_info = {
 555    .name          = TYPE_NVIC,
 556    .parent        = TYPE_ARM_GIC_COMMON,
 557    .instance_init = armv7m_nvic_instance_init,
 558    .instance_size = sizeof(nvic_state),
 559    .class_init    = armv7m_nvic_class_init,
 560    .class_size    = sizeof(NVICClass),
 561};
 562
 563static void armv7m_nvic_register_types(void)
 564{
 565    type_register_static(&armv7m_nvic_info);
 566}
 567
 568type_init(armv7m_nvic_register_types)
 569