1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "qapi/error.h"
23#include "qemu/module.h"
24#include "gic_internal.h"
25#include "hw/arm/linux-boot-if.h"
26#include "hw/qdev-properties.h"
27#include "migration/vmstate.h"
28
29#include "hw/fdt_generic_util.h"
30#include "hw/fdt_generic_devices.h"
31
32static int gic_pre_save(void *opaque)
33{
34 GICState *s = (GICState *)opaque;
35 ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
36
37 if (c->pre_save) {
38 c->pre_save(s);
39 }
40
41 return 0;
42}
43
44static int gic_post_load(void *opaque, int version_id)
45{
46 GICState *s = (GICState *)opaque;
47 ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s);
48
49 if (c->post_load) {
50 c->post_load(s);
51 }
52 return 0;
53}
54
55static bool gic_virt_state_needed(void *opaque)
56{
57 GICState *s = (GICState *)opaque;
58
59 return s->virt_extn;
60}
61
62static const VMStateDescription vmstate_gic_irq_state = {
63 .name = "arm_gic_irq_state",
64 .version_id = 1,
65 .minimum_version_id = 1,
66 .fields = (VMStateField[]) {
67 VMSTATE_UINT8(enabled, gic_irq_state),
68 VMSTATE_UINT8(pending, gic_irq_state),
69 VMSTATE_UINT8(active, gic_irq_state),
70 VMSTATE_UINT8(level, gic_irq_state),
71 VMSTATE_BOOL(model, gic_irq_state),
72 VMSTATE_BOOL(edge_trigger, gic_irq_state),
73 VMSTATE_UINT8(group, gic_irq_state),
74 VMSTATE_END_OF_LIST()
75 }
76};
77
78static const VMStateDescription vmstate_gic_virt_state = {
79 .name = "arm_gic_virt_state",
80 .version_id = 1,
81 .minimum_version_id = 1,
82 .needed = gic_virt_state_needed,
83 .fields = (VMStateField[]) {
84
85 VMSTATE_UINT32_ARRAY(h_hcr, GICState, GIC_NCPU),
86 VMSTATE_UINT32_ARRAY(h_misr, GICState, GIC_NCPU),
87 VMSTATE_UINT32_2DARRAY(h_lr, GICState, GIC_MAX_LR, GIC_NCPU),
88 VMSTATE_UINT32_ARRAY(h_apr, GICState, GIC_NCPU),
89
90
91 VMSTATE_UINT32_SUB_ARRAY(cpu_ctlr, GICState, GIC_NCPU, GIC_NCPU),
92 VMSTATE_UINT16_SUB_ARRAY(priority_mask, GICState, GIC_NCPU, GIC_NCPU),
93 VMSTATE_UINT16_SUB_ARRAY(running_priority, GICState, GIC_NCPU, GIC_NCPU),
94 VMSTATE_UINT16_SUB_ARRAY(current_pending, GICState, GIC_NCPU, GIC_NCPU),
95 VMSTATE_UINT8_SUB_ARRAY(bpr, GICState, GIC_NCPU, GIC_NCPU),
96 VMSTATE_UINT8_SUB_ARRAY(abpr, GICState, GIC_NCPU, GIC_NCPU),
97
98 VMSTATE_END_OF_LIST()
99 }
100};
101
102static const VMStateDescription vmstate_gic = {
103 .name = "arm_gic",
104 .version_id = 12,
105 .minimum_version_id = 12,
106 .pre_save = gic_pre_save,
107 .post_load = gic_post_load,
108 .fields = (VMStateField[]) {
109 VMSTATE_UINT32(ctlr, GICState),
110 VMSTATE_UINT32_SUB_ARRAY(cpu_ctlr, GICState, 0, GIC_NCPU),
111 VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1,
112 vmstate_gic_irq_state, gic_irq_state),
113 VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ),
114 VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, GIC_NCPU),
115 VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL),
116 VMSTATE_UINT8_2DARRAY(sgi_pending, GICState, GIC_NR_SGIS, GIC_NCPU),
117 VMSTATE_UINT16_SUB_ARRAY(priority_mask, GICState, 0, GIC_NCPU),
118 VMSTATE_UINT16_SUB_ARRAY(running_priority, GICState, 0, GIC_NCPU),
119 VMSTATE_UINT16_SUB_ARRAY(current_pending, GICState, 0, GIC_NCPU),
120 VMSTATE_UINT8_SUB_ARRAY(bpr, GICState, 0, GIC_NCPU),
121 VMSTATE_UINT8_SUB_ARRAY(abpr, GICState, 0, GIC_NCPU),
122 VMSTATE_UINT32_2DARRAY(apr, GICState, GIC_NR_APRS, GIC_NCPU),
123 VMSTATE_UINT32_2DARRAY(nsapr, GICState, GIC_NR_APRS, GIC_NCPU),
124 VMSTATE_END_OF_LIST()
125 },
126 .subsections = (const VMStateDescription * []) {
127 &vmstate_gic_virt_state,
128 NULL
129 }
130};
131
132void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
133 const MemoryRegionOps *ops,
134 const MemoryRegionOps *virt_ops)
135{
136 SysBusDevice *sbd = SYS_BUS_DEVICE(s);
137 int i = s->num_irq - GIC_INTERNAL;
138
139
140
141
142
143
144
145
146 i += (GIC_INTERNAL * s->num_cpu);
147 qdev_init_gpio_in(DEVICE(s), handler, i);
148
149 for (i = 0; i < s->num_cpu; i++) {
150 sysbus_init_irq(sbd, &s->parent_irq[i]);
151 }
152 for (i = 0; i < s->num_cpu; i++) {
153 sysbus_init_irq(sbd, &s->parent_fiq[i]);
154 }
155 for (i = 0; i < s->num_cpu; i++) {
156 sysbus_init_irq(sbd, &s->parent_virq[i]);
157 }
158 for (i = 0; i < s->num_cpu; i++) {
159 sysbus_init_irq(sbd, &s->parent_vfiq[i]);
160 }
161 if (s->virt_extn) {
162 for (i = 0; i < s->num_cpu; i++) {
163 sysbus_init_irq(sbd, &s->maintenance_irq[i]);
164 }
165 }
166
167
168 qdev_init_gpio_out_named(DEVICE(s), s->parent_irq, "irq", GIC_NCPU);
169 qdev_init_gpio_out_named(DEVICE(s), s->parent_virq, "virq", GIC_NCPU);
170 qdev_init_gpio_out_named(DEVICE(s), s->parent_fiq, "fiq", GIC_NCPU);
171 qdev_init_gpio_out_named(DEVICE(s), s->parent_vfiq, "vfiq", GIC_NCPU);
172 qdev_init_gpio_out_named(DEVICE(s), s->maintenance_irq, "maint",
173 s->num_cpu);
174
175
176 memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
177 sysbus_init_mmio(sbd, &s->iomem);
178
179
180
181
182 memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
183 s, "gic_cpu", s->revision == 2 ? s->map_stride * 2 : 0x100);
184 sysbus_init_mmio(sbd, &s->cpuiomem[0]);
185
186 if (s->virt_extn) {
187 memory_region_init_io(&s->vifaceiomem[0], OBJECT(s), virt_ops,
188 s, "gic_viface", 0x1000);
189 sysbus_init_mmio(sbd, &s->vifaceiomem[0]);
190
191 memory_region_init_io(&s->vcpuiomem, OBJECT(s),
192 virt_ops ? &virt_ops[1] : NULL,
193 s, "gic_vcpu", s->map_stride * 2);
194 sysbus_init_mmio(sbd, &s->vcpuiomem);
195 }
196}
197
198static void arm_gic_common_realize(DeviceState *dev, Error **errp)
199{
200 GICState *s = ARM_GIC_COMMON(dev);
201 int num_irq = s->num_irq;
202
203 if (!s->num_cpu) {
204 s->num_cpu = fdt_generic_num_cpus;
205 }
206
207 if (s->num_cpu > GIC_NCPU) {
208 error_setg(errp, "requested %u CPUs exceeds GIC maximum %d",
209 s->num_cpu, GIC_NCPU);
210 return;
211 }
212 if (s->num_irq > GIC_MAXIRQ) {
213 error_setg(errp,
214 "requested %u interrupt lines exceeds GIC maximum %d",
215 num_irq, GIC_MAXIRQ);
216 return;
217 }
218
219
220
221
222 if (s->num_irq < 32 || (s->num_irq % 32)) {
223 error_setg(errp,
224 "%d interrupt lines unsupported: not divisible by 32",
225 num_irq);
226 return;
227 }
228
229 if (s->security_extn &&
230 (s->revision == REV_11MPCORE)) {
231 error_setg(errp, "this GIC revision does not implement "
232 "the security extensions");
233 return;
234 }
235
236
237 if (s->virt_extn && s->revision != 2) {
238 s->virt_extn = false;
239 }
240
241 if (s->virt_extn) {
242 if (s->revision != 2) {
243 error_setg(errp, "GIC virtualization extensions are only "
244 "supported by revision 2");
245 return;
246 }
247
248
249
250
251
252 s->num_lrs = 4;
253 }
254}
255
256static inline void arm_gic_common_reset_irq_state(GICState *s, int first_cpu,
257 int resetprio)
258{
259 int i, j;
260
261 for (i = first_cpu; i < first_cpu + s->num_cpu; i++) {
262 if (s->revision == REV_11MPCORE) {
263 s->priority_mask[i] = 0xf0;
264 } else {
265 s->priority_mask[i] = resetprio;
266 }
267 s->current_pending[i] = 1023;
268 s->running_priority[i] = 0x100;
269 s->cpu_ctlr[i] = 0;
270 s->bpr[i] = gic_is_vcpu(i) ? GIC_VIRT_MIN_BPR : GIC_MIN_BPR;
271 s->abpr[i] = gic_is_vcpu(i) ? GIC_VIRT_MIN_ABPR : GIC_MIN_ABPR;
272
273 if (!gic_is_vcpu(i)) {
274 for (j = 0; j < GIC_INTERNAL; j++) {
275 s->priority1[j][i] = resetprio;
276 }
277 for (j = 0; j < GIC_NR_SGIS; j++) {
278 s->sgi_pending[j][i] = 0;
279 }
280 }
281 }
282}
283
284static void arm_gic_common_reset(DeviceState *dev)
285{
286 GICState *s = ARM_GIC_COMMON(dev);
287 int i, j;
288 int resetprio;
289
290
291
292
293
294
295
296
297 if (s->security_extn && s->irq_reset_nonsecure) {
298 resetprio = 0x80;
299 } else {
300 resetprio = 0;
301 }
302
303 memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
304 arm_gic_common_reset_irq_state(s, 0, resetprio);
305
306 if (s->virt_extn) {
307
308
309
310 arm_gic_common_reset_irq_state(s, GIC_NCPU, 0);
311 }
312
313 for (i = 0; i < GIC_NR_SGIS; i++) {
314 GIC_DIST_SET_ENABLED(i, ALL_CPU_MASK);
315 GIC_DIST_SET_EDGE_TRIGGER(i);
316 }
317
318 for (i = 0; i < ARRAY_SIZE(s->priority2); i++) {
319 s->priority2[i] = resetprio;
320 }
321
322 for (i = 0; i < GIC_MAXIRQ; i++) {
323
324 if (s->num_cpu == 1) {
325 s->irq_target[i] = 1;
326 } else {
327 s->irq_target[i] = 0;
328 }
329 }
330 if (s->security_extn && s->irq_reset_nonsecure) {
331 for (i = 0; i < GIC_MAXIRQ; i++) {
332 GIC_DIST_SET_GROUP(i, ALL_CPU_MASK);
333 }
334 }
335
336 if (s->virt_extn) {
337 for (i = 0; i < s->num_lrs; i++) {
338 for (j = 0; j < s->num_cpu; j++) {
339 s->h_lr[i][j] = 0;
340 }
341 }
342
343 for (i = 0; i < s->num_cpu; i++) {
344 s->h_hcr[i] = 0;
345 s->h_misr[i] = 0;
346 }
347 }
348
349 s->ctlr = 0;
350}
351
352static int arm_gic_common_fdt_get_irq(FDTGenericIntc *obj, qemu_irq *irqs,
353 uint32_t *cells, int ncells, int max,
354 Error **errp)
355{
356 GICState *gs = ARM_GIC_COMMON(obj);
357 int cpu = 0;
358 uint32_t idx;
359
360 if (ncells != 3) {
361 error_setg(errp, "ARM GIC requires 3 interrupt cells, %d cells given",
362 ncells);
363 return 0;
364 }
365 idx = cells[1];
366
367 switch (cells[0]) {
368 case 0:
369 if (idx >= gs->num_irq) {
370 error_setg(errp, "ARM GIC SPI has maximum index of %" PRId32 ", "
371 "index %" PRId32 " given", gs->num_irq - 1, idx);
372 return 0;
373 }
374 (*irqs) = qdev_get_gpio_in(DEVICE(obj), cells[1]);
375 return 1;
376 case 1:
377 if (idx >= 16) {
378 error_setg(errp, "ARM GIC PPI has maximum index of 15, "
379 "index %" PRId32 " given", idx);
380 return 0;
381 }
382 for (cpu = 0; cpu < max && cpu < gs->num_cpu; cpu++) {
383 if (cells[2] & 1 << (cpu + 8)) {
384 *irqs = qdev_get_gpio_in(DEVICE(obj),
385 gs->num_irq - 16 + idx + cpu * 32);
386 }
387 irqs++;
388 }
389 return cpu;
390 default:
391 error_setg(errp, "Invalid cell 0 value in interrupt binding: %d",
392 cells[0]);
393 return 0;
394 }
395}
396
397static void arm_gic_common_fdt_set_props(Object *obj, Error **errp)
398{
399 object_property_set_bool(obj, true, "has-security-extensions", errp);
400 object_property_set_bool(obj, true, "has-virtualization-extensions", errp);
401 object_property_set_int(obj, 0, "num-cpu", errp);
402 object_property_set_int(obj, 96, "num-irq", errp);
403}
404
405static void arm_gic_common_linux_init(ARMLinuxBootIf *obj,
406 bool secure_boot)
407{
408 GICState *s = ARM_GIC_COMMON(obj);
409
410 if (s->security_extn && !secure_boot) {
411
412
413
414
415
416
417
418 s->irq_reset_nonsecure = true;
419 }
420}
421
422static Property arm_gic_common_properties[] = {
423 DEFINE_PROP_UINT32("num-cpu", GICState, num_cpu, 1),
424 DEFINE_PROP_UINT32("num-irq", GICState, num_irq, 32),
425
426
427
428 DEFINE_PROP_UINT32("revision", GICState, revision, 1),
429
430 DEFINE_PROP_UINT32("map-stride", GICState, map_stride, 0x1000),
431 DEFINE_PROP_UINT32("int-id", GICState, c_iidr, 0),
432
433 DEFINE_PROP_BOOL("has-security-extensions", GICState, security_extn, 0),
434
435 DEFINE_PROP_BOOL("has-virtualization-extensions", GICState, virt_extn, 0),
436 DEFINE_PROP_UINT32("num-priority-bits", GICState, n_prio_bits, 8),
437 DEFINE_PROP_END_OF_LIST(),
438};
439
440static void arm_gic_common_class_init(ObjectClass *klass, void *data)
441{
442 DeviceClass *dc = DEVICE_CLASS(klass);
443 ARMLinuxBootIfClass *albifc = ARM_LINUX_BOOT_IF_CLASS(klass);
444 FDTGenericIntcClass *fgic = FDT_GENERIC_INTC_CLASS(klass);
445 FDTGenericPropsClass *fprops = FDT_GENERIC_PROPS_CLASS(klass);
446
447 dc->reset = arm_gic_common_reset;
448 dc->realize = arm_gic_common_realize;
449 device_class_set_props(dc, arm_gic_common_properties);
450 dc->vmsd = &vmstate_gic;
451 fgic->get_irq = arm_gic_common_fdt_get_irq;
452 albifc->arm_linux_init = arm_gic_common_linux_init;
453 fprops->set_props = arm_gic_common_fdt_set_props;
454}
455
456static const TypeInfo arm_gic_common_type = {
457 .name = TYPE_ARM_GIC_COMMON,
458 .parent = TYPE_SYS_BUS_DEVICE,
459 .instance_size = sizeof(GICState),
460 .class_size = sizeof(ARMGICCommonClass),
461 .class_init = arm_gic_common_class_init,
462 .abstract = true,
463 .interfaces = (InterfaceInfo []) {
464 { TYPE_ARM_LINUX_BOOT_IF },
465 { TYPE_FDT_GENERIC_INTC },
466 { TYPE_FDT_GENERIC_GPIO },
467 { TYPE_FDT_GENERIC_PROPS },
468 { },
469 },
470};
471
472static void register_types(void)
473{
474 type_register_static(&arm_gic_common_type);
475}
476
477type_init(register_types)
478