Statistics
| Branch: | Revision:

root / hw / armv7m_nvic.c @ bf3bc4c4

History | View | Annotate | Download (17.9 kB)

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