1
2
3
4
5
6
7
8
9
10
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
41
42
43
44
45typedef struct NVICClass {
46
47 ARMGICClass parent_class;
48
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
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
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
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
115
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
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:
154 return (s->num_irq / 32) - 1;
155 case 0x10:
156 val = s->systick.control;
157 s->systick.control &= ~SYSTICK_COUNTFLAG;
158 return val;
159 case 0x14:
160 return s->systick.reload;
161 case 0x18:
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
171
172
173 if (val > s->systick.reload)
174 val = 0;
175 return val;
176 }
177 case 0x1c:
178 return 10000;
179 case 0xd00:
180 cpu = ARM_CPU(current_cpu);
181 return cpu->midr;
182 case 0xd04:
183
184 val = s->gic.running_irq[0];
185 if (val == 1023) {
186 val = 0;
187 } else if (val >= 32) {
188 val -= 16;
189 }
190
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
196 if (s->gic.current_pending[0] != 1023)
197 val |= (s->gic.current_pending[0] << 12);
198
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
206 if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
207 val |= (1 << 26);
208
209 if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending)
210 val |= (1 << 28);
211
212 if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending)
213 val |= (1 << 31);
214 return val;
215 case 0xd08:
216 cpu = ARM_CPU(current_cpu);
217 return cpu->env.v7m.vecbase;
218 case 0xd0c:
219 return 0xfa050000;
220 case 0xd10:
221
222 return 0;
223 case 0xd14:
224
225 return 0;
226 case 0xd24:
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:
244
245 qemu_log_mask(LOG_UNIMP, "Configurable Fault Status unimplemented\n");
246 return 0;
247 case 0xd2c:
248 case 0xd30:
249 case 0xd34:
250 case 0xd38:
251 case 0xd3c:
252
253 qemu_log_mask(LOG_UNIMP, "Fault status registers unimplemented\n");
254 return 0;
255 case 0xd40:
256 return 0x00000030;
257 case 0xd44:
258 return 0x00000200;
259 case 0xd48:
260 return 0x00100000;
261 case 0xd4c:
262 return 0x00000000;
263 case 0xd50:
264 return 0x00000030;
265 case 0xd54:
266 return 0x00000000;
267 case 0xd58:
268 return 0x00000000;
269 case 0xd5c:
270 return 0x00000000;
271 case 0xd60:
272 return 0x01141110;
273 case 0xd64:
274 return 0x02111000;
275 case 0xd68:
276 return 0x21112231;
277 case 0xd6c:
278 return 0x01111110;
279 case 0xd70:
280 return 0x01310102;
281
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:
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
314
315 systick_reload(s, 1);
316 }
317 break;
318 case 0x14:
319 s->systick.reload = value;
320 break;
321 case 0x18:
322 systick_reload(s, 1);
323 s->systick.control &= ~SYSTICK_COUNTFLAG;
324 break;
325 case 0xd04:
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:
343 cpu = ARM_CPU(current_cpu);
344 cpu->env.v7m.vecbase = value & 0xffffff80;
345 break;
346 case 0xd0c:
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:
360 case 0xd14:
361
362 qemu_log_mask(LOG_UNIMP, "NVIC: SCR and CCR unimplemented\n");
363 break;
364 case 0xd24:
365
366
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:
372 case 0xd2c:
373 case 0xd30:
374 case 0xd34:
375 case 0xd38:
376 case 0xd3c:
377 qemu_log_mask(LOG_UNIMP,
378 "NVIC: fault status registers unimplemented\n");
379 break;
380 case 0xf00:
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:
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:
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:
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
469
470
471
472
473 s->gic.ctrl[0] = true;
474 s->gic.priority_mask[0] = 0x100;
475
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
487 s->gic.num_cpu = 1;
488
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
498
499
500
501
502
503
504 memory_region_init(&s->container, OBJECT(s), "nvic", 0x1000);
505
506
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
512
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
520
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
529
530
531
532
533
534 GICState *s = ARM_GIC_COMMON(obj);
535
536
537
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