1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include "qemu/osdep.h"
23#include "qapi/error.h"
24#include "qemu/module.h"
25#include "cpu.h"
26#include "hw/sysbus.h"
27#include "migration/blocker.h"
28#include "sysemu/kvm.h"
29#include "kvm_arm.h"
30#include "gic_internal.h"
31#include "vgic_common.h"
32#include "qom/object.h"
33
34#define TYPE_KVM_ARM_GIC "kvm-arm-gic"
35typedef struct KVMARMGICClass KVMARMGICClass;
36
37DECLARE_OBJ_CHECKERS(GICState, KVMARMGICClass,
38 KVM_ARM_GIC, TYPE_KVM_ARM_GIC)
39
40struct KVMARMGICClass {
41 ARMGICCommonClass parent_class;
42 DeviceRealize parent_realize;
43 void (*parent_reset)(DeviceState *dev);
44};
45
46void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
47{
48
49
50
51
52
53
54
55
56
57 int irqtype, cpu;
58
59 if (irq < (num_irq - GIC_INTERNAL)) {
60
61
62
63
64 irqtype = KVM_ARM_IRQ_TYPE_SPI;
65 cpu = 0;
66 irq += GIC_INTERNAL;
67 } else {
68
69 irqtype = KVM_ARM_IRQ_TYPE_PPI;
70 irq -= (num_irq - GIC_INTERNAL);
71 cpu = irq / GIC_INTERNAL;
72 irq %= GIC_INTERNAL;
73 }
74 kvm_arm_set_irq(cpu, irqtype, irq, !!level);
75}
76
77static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level)
78{
79 GICState *s = (GICState *)opaque;
80
81 kvm_arm_gic_set_irq(s->num_irq, irq, level);
82}
83
84static bool kvm_arm_gic_can_save_restore(GICState *s)
85{
86 return s->dev_fd >= 0;
87}
88
89#define KVM_VGIC_ATTR(offset, cpu) \
90 ((((uint64_t)(cpu) << KVM_DEV_ARM_VGIC_CPUID_SHIFT) & \
91 KVM_DEV_ARM_VGIC_CPUID_MASK) | \
92 (((uint64_t)(offset) << KVM_DEV_ARM_VGIC_OFFSET_SHIFT) & \
93 KVM_DEV_ARM_VGIC_OFFSET_MASK))
94
95static void kvm_gicd_access(GICState *s, int offset, int cpu,
96 uint32_t *val, bool write)
97{
98 kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_DIST_REGS,
99 KVM_VGIC_ATTR(offset, cpu), val, write, &error_abort);
100}
101
102static void kvm_gicc_access(GICState *s, int offset, int cpu,
103 uint32_t *val, bool write)
104{
105 kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CPU_REGS,
106 KVM_VGIC_ATTR(offset, cpu), val, write, &error_abort);
107}
108
109#define for_each_irq_reg(_ctr, _max_irq, _field_width) \
110 for (_ctr = 0; _ctr < ((_max_irq) / (32 / (_field_width))); _ctr++)
111
112
113
114
115
116typedef void (*vgic_translate_fn)(GICState *s, int irq, int cpu,
117 uint32_t *field, bool to_kernel);
118
119
120
121
122static void translate_clear(GICState *s, int irq, int cpu,
123 uint32_t *field, bool to_kernel)
124{
125 if (to_kernel) {
126 *field = ~0;
127 } else {
128
129 abort();
130 }
131}
132
133static void translate_group(GICState *s, int irq, int cpu,
134 uint32_t *field, bool to_kernel)
135{
136 int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
137
138 if (to_kernel) {
139 *field = GIC_DIST_TEST_GROUP(irq, cm);
140 } else {
141 if (*field & 1) {
142 GIC_DIST_SET_GROUP(irq, cm);
143 }
144 }
145}
146
147static void translate_enabled(GICState *s, int irq, int cpu,
148 uint32_t *field, bool to_kernel)
149{
150 int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
151
152 if (to_kernel) {
153 *field = GIC_DIST_TEST_ENABLED(irq, cm);
154 } else {
155 if (*field & 1) {
156 GIC_DIST_SET_ENABLED(irq, cm);
157 }
158 }
159}
160
161static void translate_pending(GICState *s, int irq, int cpu,
162 uint32_t *field, bool to_kernel)
163{
164 int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
165
166 if (to_kernel) {
167 *field = gic_test_pending(s, irq, cm);
168 } else {
169 if (*field & 1) {
170 GIC_DIST_SET_PENDING(irq, cm);
171
172 }
173 }
174}
175
176static void translate_active(GICState *s, int irq, int cpu,
177 uint32_t *field, bool to_kernel)
178{
179 int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
180
181 if (to_kernel) {
182 *field = GIC_DIST_TEST_ACTIVE(irq, cm);
183 } else {
184 if (*field & 1) {
185 GIC_DIST_SET_ACTIVE(irq, cm);
186 }
187 }
188}
189
190static void translate_trigger(GICState *s, int irq, int cpu,
191 uint32_t *field, bool to_kernel)
192{
193 if (to_kernel) {
194 *field = (GIC_DIST_TEST_EDGE_TRIGGER(irq)) ? 0x2 : 0x0;
195 } else {
196 if (*field & 0x2) {
197 GIC_DIST_SET_EDGE_TRIGGER(irq);
198 }
199 }
200}
201
202static void translate_priority(GICState *s, int irq, int cpu,
203 uint32_t *field, bool to_kernel)
204{
205 if (to_kernel) {
206 *field = GIC_DIST_GET_PRIORITY(irq, cpu) & 0xff;
207 } else {
208 gic_dist_set_priority(s, cpu, irq,
209 *field & 0xff, MEMTXATTRS_UNSPECIFIED);
210 }
211}
212
213static void translate_targets(GICState *s, int irq, int cpu,
214 uint32_t *field, bool to_kernel)
215{
216 if (to_kernel) {
217 *field = s->irq_target[irq] & 0xff;
218 } else {
219 s->irq_target[irq] = *field & 0xff;
220 }
221}
222
223static void translate_sgisource(GICState *s, int irq, int cpu,
224 uint32_t *field, bool to_kernel)
225{
226 if (to_kernel) {
227 *field = s->sgi_pending[irq][cpu] & 0xff;
228 } else {
229 s->sgi_pending[irq][cpu] = *field & 0xff;
230 }
231}
232
233
234static void kvm_dist_get(GICState *s, uint32_t offset, int width,
235 int maxirq, vgic_translate_fn translate_fn)
236{
237 uint32_t reg;
238 int i;
239 int j;
240 int irq;
241 int cpu;
242 int regsz = 32 / width;
243 uint32_t field;
244
245 for_each_irq_reg(i, maxirq, width) {
246 irq = i * regsz;
247 cpu = 0;
248 while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
249 kvm_gicd_access(s, offset, cpu, ®, false);
250 for (j = 0; j < regsz; j++) {
251 field = extract32(reg, j * width, width);
252 translate_fn(s, irq + j, cpu, &field, false);
253 }
254
255 cpu++;
256 }
257 offset += 4;
258 }
259}
260
261
262static void kvm_dist_put(GICState *s, uint32_t offset, int width,
263 int maxirq, vgic_translate_fn translate_fn)
264{
265 uint32_t reg;
266 int i;
267 int j;
268 int irq;
269 int cpu;
270 int regsz = 32 / width;
271 uint32_t field;
272
273 for_each_irq_reg(i, maxirq, width) {
274 irq = i * regsz;
275 cpu = 0;
276 while ((cpu < s->num_cpu && irq < GIC_INTERNAL) || cpu == 0) {
277 reg = 0;
278 for (j = 0; j < regsz; j++) {
279 translate_fn(s, irq + j, cpu, &field, true);
280 reg = deposit32(reg, j * width, width, field);
281 }
282 kvm_gicd_access(s, offset, cpu, ®, true);
283
284 cpu++;
285 }
286 offset += 4;
287 }
288}
289
290static void kvm_arm_gic_put(GICState *s)
291{
292 uint32_t reg;
293 int i;
294 int cpu;
295 int num_cpu;
296 int num_irq;
297
298
299
300
301
302
303
304
305
306
307 reg = s->ctlr;
308 kvm_gicd_access(s, 0x0, 0, ®, true);
309
310
311 kvm_gicd_access(s, 0x4, 0, ®, false);
312 num_irq = ((reg & 0x1f) + 1) * 32;
313 num_cpu = ((reg & 0xe0) >> 5) + 1;
314
315 if (num_irq < s->num_irq) {
316 fprintf(stderr, "Restoring %u IRQs, but kernel supports max %d\n",
317 s->num_irq, num_irq);
318 abort();
319 } else if (num_cpu != s->num_cpu) {
320 fprintf(stderr, "Restoring %u CPU interfaces, kernel only has %d\n",
321 s->num_cpu, num_cpu);
322
323 abort();
324 }
325
326
327
328
329 kvm_dist_put(s, 0x180, 1, s->num_irq, translate_clear);
330 kvm_dist_put(s, 0x100, 1, s->num_irq, translate_enabled);
331
332
333 kvm_dist_put(s, 0x80, 1, s->num_irq, translate_group);
334
335
336
337
338 kvm_dist_put(s, 0x800, 8, s->num_irq, translate_targets);
339
340
341
342
343 kvm_dist_put(s, 0xc00, 2, s->num_irq, translate_trigger);
344
345
346 kvm_dist_put(s, 0x280, 1, s->num_irq, translate_clear);
347 kvm_dist_put(s, 0x200, 1, s->num_irq, translate_pending);
348
349
350 kvm_dist_put(s, 0x380, 1, s->num_irq, translate_clear);
351 kvm_dist_put(s, 0x300, 1, s->num_irq, translate_active);
352
353
354
355 kvm_dist_put(s, 0x400, 8, s->num_irq, translate_priority);
356
357
358 kvm_dist_put(s, 0xf10, 8, GIC_NR_SGIS, translate_clear);
359 kvm_dist_put(s, 0xf20, 8, GIC_NR_SGIS, translate_sgisource);
360
361
362
363
364
365
366 for (cpu = 0; cpu < s->num_cpu; cpu++) {
367
368 reg = s->cpu_ctlr[cpu];
369 kvm_gicc_access(s, 0x00, cpu, ®, true);
370
371
372 reg = (s->priority_mask[cpu] & 0xff);
373 kvm_gicc_access(s, 0x04, cpu, ®, true);
374
375
376 reg = (s->bpr[cpu] & 0x7);
377 kvm_gicc_access(s, 0x08, cpu, ®, true);
378
379
380 reg = (s->abpr[cpu] & 0x7);
381 kvm_gicc_access(s, 0x1c, cpu, ®, true);
382
383
384 for (i = 0; i < 4; i++) {
385 reg = s->apr[i][cpu];
386 kvm_gicc_access(s, 0xd0 + i * 4, cpu, ®, true);
387 }
388 }
389}
390
391static void kvm_arm_gic_get(GICState *s)
392{
393 uint32_t reg;
394 int i;
395 int cpu;
396
397
398
399
400
401
402 kvm_gicd_access(s, 0x0, 0, ®, false);
403 s->ctlr = reg;
404
405
406 kvm_gicd_access(s, 0x4, 0, ®, false);
407 s->num_irq = ((reg & 0x1f) + 1) * 32;
408 s->num_cpu = ((reg & 0xe0) >> 5) + 1;
409
410 if (s->num_irq > GIC_MAXIRQ) {
411 fprintf(stderr, "Too many IRQs reported from the kernel: %d\n",
412 s->num_irq);
413 abort();
414 }
415
416
417 kvm_gicd_access(s, 0x8, 0, ®, false);
418
419
420 for (i = 0; i < s->num_irq; i++) {
421 memset(&s->irq_state[i], 0, sizeof(s->irq_state[0]));
422 }
423
424
425 kvm_dist_get(s, 0x80, 1, s->num_irq, translate_group);
426
427
428 kvm_dist_get(s, 0x100, 1, s->num_irq, translate_enabled);
429
430
431 kvm_dist_get(s, 0x200, 1, s->num_irq, translate_pending);
432
433
434 kvm_dist_get(s, 0x300, 1, s->num_irq, translate_active);
435
436
437 kvm_dist_get(s, 0xc00, 2, s->num_irq, translate_trigger);
438
439
440 kvm_dist_get(s, 0x400, 8, s->num_irq, translate_priority);
441
442
443 kvm_dist_get(s, 0x800, 8, s->num_irq, translate_targets);
444
445
446 kvm_dist_get(s, 0xf10, 8, GIC_NR_SGIS, translate_sgisource);
447
448
449
450
451
452
453 for (cpu = 0; cpu < s->num_cpu; cpu++) {
454
455 kvm_gicc_access(s, 0x00, cpu, ®, false);
456 s->cpu_ctlr[cpu] = reg;
457
458
459 kvm_gicc_access(s, 0x04, cpu, ®, false);
460 s->priority_mask[cpu] = (reg & 0xff);
461
462
463 kvm_gicc_access(s, 0x08, cpu, ®, false);
464 s->bpr[cpu] = (reg & 0x7);
465
466
467 kvm_gicc_access(s, 0x1c, cpu, ®, false);
468 s->abpr[cpu] = (reg & 0x7);
469
470
471 for (i = 0; i < 4; i++) {
472 kvm_gicc_access(s, 0xd0 + i * 4, cpu, ®, false);
473 s->apr[i][cpu] = reg;
474 }
475 }
476}
477
478static void kvm_arm_gic_reset(DeviceState *dev)
479{
480 GICState *s = ARM_GIC_COMMON(dev);
481 KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
482
483 kgc->parent_reset(dev);
484
485 if (kvm_arm_gic_can_save_restore(s)) {
486 kvm_arm_gic_put(s);
487 }
488}
489
490static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
491{
492 int i;
493 GICState *s = KVM_ARM_GIC(dev);
494 KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
495 Error *local_err = NULL;
496 int ret;
497
498 kgc->parent_realize(dev, &local_err);
499 if (local_err) {
500 error_propagate(errp, local_err);
501 return;
502 }
503
504 if (s->security_extn) {
505 error_setg(errp, "the in-kernel VGIC does not implement the "
506 "security extensions");
507 return;
508 }
509
510 if (s->virt_extn) {
511 error_setg(errp, "the in-kernel VGIC does not implement the "
512 "virtualization extensions");
513 return;
514 }
515
516 if (!kvm_arm_gic_can_save_restore(s)) {
517 error_setg(&s->migration_blocker, "This operating system kernel does "
518 "not support vGICv2 migration");
519 if (migrate_add_blocker(s->migration_blocker, errp) < 0) {
520 error_free(s->migration_blocker);
521 return;
522 }
523 }
524
525 gic_init_irqs_and_mmio(s, kvm_arm_gicv2_set_irq, NULL, NULL);
526
527 for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
528 qemu_irq irq = qdev_get_gpio_in(dev, i);
529 kvm_irqchip_set_qemuirq_gsi(kvm_state, irq, i);
530 }
531
532
533 s->dev_fd = -1;
534 ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false);
535 if (ret >= 0) {
536 s->dev_fd = ret;
537
538
539 if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0)) {
540 uint32_t numirqs = s->num_irq;
541 kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0,
542 &numirqs, true, &error_abort);
543 }
544
545 if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
546 KVM_DEV_ARM_VGIC_CTRL_INIT)) {
547 kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
548 KVM_DEV_ARM_VGIC_CTRL_INIT, NULL, true,
549 &error_abort);
550 }
551 } else if (kvm_check_extension(kvm_state, KVM_CAP_DEVICE_CTRL)) {
552 error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
553 error_append_hint(errp,
554 "Perhaps the host CPU does not support GICv2?\n");
555 } else if (ret != -ENODEV && ret != -ENOTSUP) {
556
557
558
559
560
561 error_setg_errno(errp, -ret, "error creating in-kernel VGIC");
562 return;
563 }
564
565
566 kvm_arm_register_device(&s->iomem,
567 (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
568 | KVM_VGIC_V2_ADDR_TYPE_DIST,
569 KVM_DEV_ARM_VGIC_GRP_ADDR,
570 KVM_VGIC_V2_ADDR_TYPE_DIST,
571 s->dev_fd, 0);
572
573
574
575
576 kvm_arm_register_device(&s->cpuiomem[0],
577 (KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
578 | KVM_VGIC_V2_ADDR_TYPE_CPU,
579 KVM_DEV_ARM_VGIC_GRP_ADDR,
580 KVM_VGIC_V2_ADDR_TYPE_CPU,
581 s->dev_fd, 0);
582
583 if (kvm_has_gsi_routing()) {
584
585 for (i = 0; i < s->num_irq - GIC_INTERNAL; ++i) {
586 kvm_irqchip_add_irq_route(kvm_state, i, 0, i);
587 }
588
589 kvm_gsi_routing_allowed = true;
590
591 kvm_irqchip_commit_routes(kvm_state);
592 }
593}
594
595static void kvm_arm_gic_class_init(ObjectClass *klass, void *data)
596{
597 DeviceClass *dc = DEVICE_CLASS(klass);
598 ARMGICCommonClass *agcc = ARM_GIC_COMMON_CLASS(klass);
599 KVMARMGICClass *kgc = KVM_ARM_GIC_CLASS(klass);
600
601 agcc->pre_save = kvm_arm_gic_get;
602 agcc->post_load = kvm_arm_gic_put;
603 device_class_set_parent_realize(dc, kvm_arm_gic_realize,
604 &kgc->parent_realize);
605 device_class_set_parent_reset(dc, kvm_arm_gic_reset, &kgc->parent_reset);
606}
607
608static const TypeInfo kvm_arm_gic_info = {
609 .name = TYPE_KVM_ARM_GIC,
610 .parent = TYPE_ARM_GIC_COMMON,
611 .instance_size = sizeof(GICState),
612 .class_init = kvm_arm_gic_class_init,
613 .class_size = sizeof(KVMARMGICClass),
614};
615
616static void kvm_arm_gic_register_types(void)
617{
618 type_register_static(&kvm_arm_gic_info);
619}
620
621type_init(kvm_arm_gic_register_types)
622