1
2
3
4
5
6
7
8
9
10
11
12
13#include "sysbus.h"
14#include "qemu-timer.h"
15#include "arm-misc.h"
16#include "exec-memory.h"
17#include "arm_gic_internal.h"
18
19typedef struct {
20 GICState gic;
21 struct {
22 uint32_t control;
23 uint32_t reload;
24 int64_t tick;
25 QEMUTimer *timer;
26 } systick;
27 MemoryRegion sysregmem;
28 MemoryRegion gic_iomem_alias;
29 MemoryRegion container;
30 uint32_t num_irq;
31} nvic_state;
32
33#define TYPE_NVIC "armv7m_nvic"
34
35
36
37
38
39
40typedef struct NVICClass {
41
42 ARMGICClass parent_class;
43
44 int (*parent_init)(SysBusDevice *dev);
45 void (*parent_reset)(DeviceState *dev);
46} NVICClass;
47
48#define NVIC_CLASS(klass) \
49 OBJECT_CLASS_CHECK(NVICClass, (klass), TYPE_NVIC)
50#define NVIC_GET_CLASS(obj) \
51 OBJECT_GET_CLASS(NVICClass, (obj), TYPE_NVIC)
52#define NVIC(obj) \
53 OBJECT_CHECK(nvic_state, (obj), TYPE_NVIC)
54
55static const uint8_t nvic_id[] = {
56 0x00, 0xb0, 0x1b, 0x00, 0x0d, 0xe0, 0x05, 0xb1
57};
58
59
60#define SYSTICK_SCALE 1000ULL
61
62#define SYSTICK_ENABLE (1 << 0)
63#define SYSTICK_TICKINT (1 << 1)
64#define SYSTICK_CLKSOURCE (1 << 2)
65#define SYSTICK_COUNTFLAG (1 << 16)
66
67int system_clock_scale;
68
69
70static inline int64_t systick_scale(nvic_state *s)
71{
72 if (s->systick.control & SYSTICK_CLKSOURCE)
73 return system_clock_scale;
74 else
75 return 1000;
76}
77
78static void systick_reload(nvic_state *s, int reset)
79{
80 if (reset)
81 s->systick.tick = qemu_get_clock_ns(vm_clock);
82 s->systick.tick += (s->systick.reload + 1) * systick_scale(s);
83 qemu_mod_timer(s->systick.timer, s->systick.tick);
84}
85
86static void systick_timer_tick(void * opaque)
87{
88 nvic_state *s = (nvic_state *)opaque;
89 s->systick.control |= SYSTICK_COUNTFLAG;
90 if (s->systick.control & SYSTICK_TICKINT) {
91
92 armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
93 }
94 if (s->systick.reload == 0) {
95 s->systick.control &= ~SYSTICK_ENABLE;
96 } else {
97 systick_reload(s, 0);
98 }
99}
100
101static void systick_reset(nvic_state *s)
102{
103 s->systick.control = 0;
104 s->systick.reload = 0;
105 s->systick.tick = 0;
106 qemu_del_timer(s->systick.timer);
107}
108
109
110
111void armv7m_nvic_set_pending(void *opaque, int irq)
112{
113 nvic_state *s = (nvic_state *)opaque;
114 if (irq >= 16)
115 irq += 16;
116 gic_set_pending_private(&s->gic, 0, irq);
117}
118
119
120int armv7m_nvic_acknowledge_irq(void *opaque)
121{
122 nvic_state *s = (nvic_state *)opaque;
123 uint32_t irq;
124
125 irq = gic_acknowledge_irq(&s->gic, 0);
126 if (irq == 1023)
127 hw_error("Interrupt but no vector\n");
128 if (irq >= 32)
129 irq -= 16;
130 return irq;
131}
132
133void armv7m_nvic_complete_irq(void *opaque, int irq)
134{
135 nvic_state *s = (nvic_state *)opaque;
136 if (irq >= 16)
137 irq += 16;
138 gic_complete_irq(&s->gic, 0, irq);
139}
140
141static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
142{
143 uint32_t val;
144 int irq;
145
146 switch (offset) {
147 case 4:
148 return (s->num_irq / 32) - 1;
149 case 0x10:
150 val = s->systick.control;
151 s->systick.control &= ~SYSTICK_COUNTFLAG;
152 return val;
153 case 0x14:
154 return s->systick.reload;
155 case 0x18:
156 {
157 int64_t t;
158 if ((s->systick.control & SYSTICK_ENABLE) == 0)
159 return 0;
160 t = qemu_get_clock_ns(vm_clock);
161 if (t >= s->systick.tick)
162 return 0;
163 val = ((s->systick.tick - (t + 1)) / systick_scale(s)) + 1;
164
165
166
167 if (val > s->systick.reload)
168 val = 0;
169 return val;
170 }
171 case 0x1c:
172 return 10000;
173 case 0xd00:
174 return cpu_single_env->cp15.c0_cpuid;
175 case 0xd04:
176
177 val = s->gic.running_irq[0];
178 if (val == 1023) {
179 val = 0;
180 } else if (val >= 32) {
181 val -= 16;
182 }
183
184 if (s->gic.running_irq[0] == 1023
185 || s->gic.last_active[s->gic.running_irq[0]][0] == 1023) {
186 val |= (1 << 11);
187 }
188
189 if (s->gic.current_pending[0] != 1023)
190 val |= (s->gic.current_pending[0] << 12);
191
192 for (irq = 32; irq < s->num_irq; irq++) {
193 if (s->gic.irq_state[irq].pending) {
194 val |= (1 << 22);
195 break;
196 }
197 }
198
199 if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending)
200 val |= (1 << 26);
201
202 if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending)
203 val |= (1 << 28);
204
205 if (s->gic.irq_state[ARMV7M_EXCP_NMI].pending)
206 val |= (1 << 31);
207 return val;
208 case 0xd08:
209 return cpu_single_env->v7m.vecbase;
210 case 0xd0c:
211 return 0xfa05000;
212 case 0xd10:
213
214 return 0;
215 case 0xd14:
216
217 return 0;
218 case 0xd24:
219 val = 0;
220 if (s->gic.irq_state[ARMV7M_EXCP_MEM].active) val |= (1 << 0);
221 if (s->gic.irq_state[ARMV7M_EXCP_BUS].active) val |= (1 << 1);
222 if (s->gic.irq_state[ARMV7M_EXCP_USAGE].active) val |= (1 << 3);
223 if (s->gic.irq_state[ARMV7M_EXCP_SVC].active) val |= (1 << 7);
224 if (s->gic.irq_state[ARMV7M_EXCP_DEBUG].active) val |= (1 << 8);
225 if (s->gic.irq_state[ARMV7M_EXCP_PENDSV].active) val |= (1 << 10);
226 if (s->gic.irq_state[ARMV7M_EXCP_SYSTICK].active) val |= (1 << 11);
227 if (s->gic.irq_state[ARMV7M_EXCP_USAGE].pending) val |= (1 << 12);
228 if (s->gic.irq_state[ARMV7M_EXCP_MEM].pending) val |= (1 << 13);
229 if (s->gic.irq_state[ARMV7M_EXCP_BUS].pending) val |= (1 << 14);
230 if (s->gic.irq_state[ARMV7M_EXCP_SVC].pending) val |= (1 << 15);
231 if (s->gic.irq_state[ARMV7M_EXCP_MEM].enabled) val |= (1 << 16);
232 if (s->gic.irq_state[ARMV7M_EXCP_BUS].enabled) val |= (1 << 17);
233 if (s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled) val |= (1 << 18);
234 return val;
235 case 0xd28:
236
237 qemu_log_mask(LOG_UNIMP, "Configurable Fault Status unimplemented\n");
238 return 0;
239 case 0xd2c:
240 case 0xd30:
241 case 0xd34:
242 case 0xd38:
243 case 0xd3c:
244
245 qemu_log_mask(LOG_UNIMP, "Fault status registers unimplemented\n");
246 return 0;
247 case 0xd40:
248 return 0x00000030;
249 case 0xd44:
250 return 0x00000200;
251 case 0xd48:
252 return 0x00100000;
253 case 0xd4c:
254 return 0x00000000;
255 case 0xd50:
256 return 0x00000030;
257 case 0xd54:
258 return 0x00000000;
259 case 0xd58:
260 return 0x00000000;
261 case 0xd5c:
262 return 0x00000000;
263 case 0xd60:
264 return 0x01141110;
265 case 0xd64:
266 return 0x02111000;
267 case 0xd68:
268 return 0x21112231;
269 case 0xd6c:
270 return 0x01111110;
271 case 0xd70:
272 return 0x01310102;
273
274 default:
275 qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
276 return 0;
277 }
278}
279
280static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)
281{
282 uint32_t oldval;
283 switch (offset) {
284 case 0x10:
285 oldval = s->systick.control;
286 s->systick.control &= 0xfffffff8;
287 s->systick.control |= value & 7;
288 if ((oldval ^ value) & SYSTICK_ENABLE) {
289 int64_t now = qemu_get_clock_ns(vm_clock);
290 if (value & SYSTICK_ENABLE) {
291 if (s->systick.tick) {
292 s->systick.tick += now;
293 qemu_mod_timer(s->systick.timer, s->systick.tick);
294 } else {
295 systick_reload(s, 1);
296 }
297 } else {
298 qemu_del_timer(s->systick.timer);
299 s->systick.tick -= now;
300 if (s->systick.tick < 0)
301 s->systick.tick = 0;
302 }
303 } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
304
305
306 systick_reload(s, 1);
307 }
308 break;
309 case 0x14:
310 s->systick.reload = value;
311 break;
312 case 0x18:
313 systick_reload(s, 1);
314 s->systick.control &= ~SYSTICK_COUNTFLAG;
315 break;
316 case 0xd04:
317 if (value & (1 << 31)) {
318 armv7m_nvic_set_pending(s, ARMV7M_EXCP_NMI);
319 }
320 if (value & (1 << 28)) {
321 armv7m_nvic_set_pending(s, ARMV7M_EXCP_PENDSV);
322 } else if (value & (1 << 27)) {
323 s->gic.irq_state[ARMV7M_EXCP_PENDSV].pending = 0;
324 gic_update(&s->gic);
325 }
326 if (value & (1 << 26)) {
327 armv7m_nvic_set_pending(s, ARMV7M_EXCP_SYSTICK);
328 } else if (value & (1 << 25)) {
329 s->gic.irq_state[ARMV7M_EXCP_SYSTICK].pending = 0;
330 gic_update(&s->gic);
331 }
332 break;
333 case 0xd08:
334 cpu_single_env->v7m.vecbase = value & 0xffffff80;
335 break;
336 case 0xd0c:
337 if ((value >> 16) == 0x05fa) {
338 if (value & 2) {
339 qemu_log_mask(LOG_UNIMP, "VECTCLRACTIVE unimplemented\n");
340 }
341 if (value & 5) {
342 qemu_log_mask(LOG_UNIMP, "AIRCR system reset unimplemented\n");
343 }
344 }
345 break;
346 case 0xd10:
347 case 0xd14:
348
349 qemu_log_mask(LOG_UNIMP, "NVIC: SCR and CCR unimplemented\n");
350 break;
351 case 0xd24:
352
353
354 s->gic.irq_state[ARMV7M_EXCP_MEM].enabled = (value & (1 << 16)) != 0;
355 s->gic.irq_state[ARMV7M_EXCP_BUS].enabled = (value & (1 << 17)) != 0;
356 s->gic.irq_state[ARMV7M_EXCP_USAGE].enabled = (value & (1 << 18)) != 0;
357 break;
358 case 0xd28:
359 case 0xd2c:
360 case 0xd30:
361 case 0xd34:
362 case 0xd38:
363 case 0xd3c:
364 qemu_log_mask(LOG_UNIMP,
365 "NVIC: fault status registers unimplemented\n");
366 break;
367 case 0xf00:
368 if ((value & 0x1ff) < s->num_irq) {
369 gic_set_pending_private(&s->gic, 0, value & 0x1ff);
370 }
371 break;
372 default:
373 qemu_log_mask(LOG_GUEST_ERROR,
374 "NVIC: Bad write offset 0x%x\n", offset);
375 }
376}
377
378static uint64_t nvic_sysreg_read(void *opaque, hwaddr addr,
379 unsigned size)
380{
381 nvic_state *s = (nvic_state *)opaque;
382 uint32_t offset = addr;
383 int i;
384 uint32_t val;
385
386 switch (offset) {
387 case 0xd18 ... 0xd23:
388 val = 0;
389 for (i = 0; i < size; i++) {
390 val |= s->gic.priority1[(offset - 0xd14) + i][0] << (i * 8);
391 }
392 return val;
393 case 0xfe0 ... 0xfff:
394 if (offset & 3) {
395 return 0;
396 }
397 return nvic_id[(offset - 0xfe0) >> 2];
398 }
399 if (size == 4) {
400 return nvic_readl(s, offset);
401 }
402 qemu_log_mask(LOG_GUEST_ERROR,
403 "NVIC: Bad read of size %d at offset 0x%x\n", size, offset);
404 return 0;
405}
406
407static void nvic_sysreg_write(void *opaque, hwaddr addr,
408 uint64_t value, unsigned size)
409{
410 nvic_state *s = (nvic_state *)opaque;
411 uint32_t offset = addr;
412 int i;
413
414 switch (offset) {
415 case 0xd18 ... 0xd23:
416 for (i = 0; i < size; i++) {
417 s->gic.priority1[(offset - 0xd14) + i][0] =
418 (value >> (i * 8)) & 0xff;
419 }
420 gic_update(&s->gic);
421 return;
422 }
423 if (size == 4) {
424 nvic_writel(s, offset, value);
425 return;
426 }
427 qemu_log_mask(LOG_GUEST_ERROR,
428 "NVIC: Bad write of size %d at offset 0x%x\n", size, offset);
429}
430
431static const MemoryRegionOps nvic_sysreg_ops = {
432 .read = nvic_sysreg_read,
433 .write = nvic_sysreg_write,
434 .endianness = DEVICE_NATIVE_ENDIAN,
435};
436
437static const VMStateDescription vmstate_nvic = {
438 .name = "armv7m_nvic",
439 .version_id = 1,
440 .minimum_version_id = 1,
441 .minimum_version_id_old = 1,
442 .fields = (VMStateField[]) {
443 VMSTATE_UINT32(systick.control, nvic_state),
444 VMSTATE_UINT32(systick.reload, nvic_state),
445 VMSTATE_INT64(systick.tick, nvic_state),
446 VMSTATE_TIMER(systick.timer, nvic_state),
447 VMSTATE_END_OF_LIST()
448 }
449};
450
451static void armv7m_nvic_reset(DeviceState *dev)
452{
453 nvic_state *s = NVIC(dev);
454 NVICClass *nc = NVIC_GET_CLASS(s);
455 nc->parent_reset(dev);
456
457
458
459
460 s->gic.cpu_enabled[0] = 1;
461
462 s->gic.enabled = 1;
463 systick_reset(s);
464}
465
466static int armv7m_nvic_init(SysBusDevice *dev)
467{
468 nvic_state *s = NVIC(dev);
469 NVICClass *nc = NVIC_GET_CLASS(s);
470
471
472 s->gic.num_cpu = 1;
473
474 s->gic.revision = 0xffffffff;
475 s->num_irq = s->gic.num_irq;
476 nc->parent_init(dev);
477 gic_init_irqs_and_distributor(&s->gic, s->num_irq);
478
479
480
481
482
483
484
485 memory_region_init(&s->container, "nvic", 0x1000);
486
487
488
489 memory_region_init_io(&s->sysregmem, &nvic_sysreg_ops, s,
490 "nvic_sysregs", 0x1000);
491 memory_region_add_subregion(&s->container, 0, &s->sysregmem);
492
493
494
495 memory_region_init_alias(&s->gic_iomem_alias, "nvic-gic", &s->gic.iomem,
496 0x100, 0xc00);
497 memory_region_add_subregion_overlap(&s->container, 0x100,
498 &s->gic_iomem_alias, 1);
499
500
501
502 memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->container);
503 s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
504 return 0;
505}
506
507static void armv7m_nvic_instance_init(Object *obj)
508{
509
510
511
512
513
514
515 GICState *s = ARM_GIC_COMMON(obj);
516
517
518
519
520 s->num_irq = 64;
521}
522
523static void armv7m_nvic_class_init(ObjectClass *klass, void *data)
524{
525 NVICClass *nc = NVIC_CLASS(klass);
526 DeviceClass *dc = DEVICE_CLASS(klass);
527 SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
528
529 nc->parent_reset = dc->reset;
530 nc->parent_init = sdc->init;
531 sdc->init = armv7m_nvic_init;
532 dc->vmsd = &vmstate_nvic;
533 dc->reset = armv7m_nvic_reset;
534}
535
536static TypeInfo armv7m_nvic_info = {
537 .name = TYPE_NVIC,
538 .parent = TYPE_ARM_GIC_COMMON,
539 .instance_init = armv7m_nvic_instance_init,
540 .instance_size = sizeof(nvic_state),
541 .class_init = armv7m_nvic_class_init,
542 .class_size = sizeof(NVICClass),
543};
544
545static void armv7m_nvic_register_types(void)
546{
547 type_register_static(&armv7m_nvic_info);
548}
549
550type_init(armv7m_nvic_register_types)
551