376
};
377
}
378
379
+/* Data we need to pass through to lpi_cache_get_hppi() */
380
+typedef struct GetHPPIUserData {
381
+ GICv5PendingIrq *best;
382
+ uint32_t iaffid;
383
+} GetHPPIUserData;
384
+
385
+static void lpi_cache_get_hppi(gpointer key, gpointer value, gpointer user_data)
386
+{
387
+ uint64_t id = GPOINTER_TO_INT(key);
388
+ uint64_t l2_iste = *(uint64_t *)value;
389
+ uint32_t prio, iaffid;
390
+ GetHPPIUserData *ud = user_data;
391
+
392
+ if ((l2_iste & (R_L2_ISTE_PENDING_MASK | R_L2_ISTE_ACTIVE_MASK | R_L2_ISTE_ENABLE_MASK))
393
+ != (R_L2_ISTE_PENDING_MASK | R_L2_ISTE_ENABLE_MASK)) {
394
+ return;
395
+ }
396
+ prio = FIELD_EX32(l2_iste, L2_ISTE, PRIORITY);
397
+ iaffid = FIELD_EX32(l2_iste, L2_ISTE, IAFFID);
398
+ if (iaffid == ud->iaffid && prio < ud->best->prio) {
399
+ id = FIELD_DP32(id, INTID, TYPE, GICV5_LPI);
400
+ ud->best->intid = id;
401
+ ud->best->prio = prio;
402
+ }
403
+}
404
+
405
+static int irs_cpuidx_from_iaffid(GICv5Common *cs, uint32_t iaffid)
406
+{
407
+ for (int i = 0; i < cs->num_cpus; i++) {
408
+ if (cs->cpu_iaffids[i] == iaffid) {
409
+ return i;
410
+ }
411
+ }
412
+ return -1;
413
+}
414
+
415
+static void irs_recalc_hppi(GICv5 *s, GICv5Domain domain, uint32_t iaffid)
416
+{
417
+ /*
418
+ * Recalculate the highest priority pending interrupt for the
419
+ * specified domain and cpuif. HPPI candidates must be pending,
420
+ * inactive and enabled.
421
+ */
422
+ GICv5Common *cs = ARM_GICV5_COMMON(s);
423
+ int cpuidx = irs_cpuidx_from_iaffid(cs, iaffid);
424
+ ARMCPU *cpu = cpuidx >= 0 ? cs->cpus[cpuidx] : NULL;
425
+ GICv5PendingIrq best;
426
+
427
+ best.intid = 0;
428
+ best.prio = PRIO_IDLE;
429
+
430
+ if (!cpu) {
431
+ /* Nothing happens for iaffids targeting nonexistent CPUs */
432
+ trace_gicv5_irs_recalc_hppi_fail(domain_name[domain], iaffid,
433
+ "IAFFID doesn't match any CPU");
434
+ return;
435
+ }
436
+
437
+ if (!FIELD_EX32(cs->irs_cr0[domain], IRS_CR0, IRSEN)) {
438
+ /* When the IRS is disabled we don't forward HPPIs */
439
+ trace_gicv5_irs_recalc_hppi_fail(domain_name[domain], iaffid,
440
+ "IRS_CR0.IRSEN is zero");
441
+ return;
442
+ }
443
+
444
+ if (s->phys_lpi_config[domain].valid) {
445
+ GetHPPIUserData ud;
446
+
447
+ ud.best = &best;
448
+ ud.iaffid = iaffid;
449
+ g_hash_table_foreach(s->phys_lpi_config[domain].lpi_cache,
450
+ lpi_cache_get_hppi, &ud);
451
+ }
452
+
453
+ /*
454
+ * OPT: consider also caching the SPI interrupt information,
455
+ * similarly to how we handle LPIs, if iterating through the whole
456
+ * SPI array every time is too expensive.
457
+ */
458
+ for (int i = 0; i < cs->spi_irs_range; i++) {
459
+ GICv5SPIState *spi = &cs->spi[i];
460
+
461
+ if (spi->active || !spi->pending || !spi->enabled) {
462
+ continue;
463
+ }
464
+ if (spi->domain != domain || spi->iaffid != iaffid) {
465
+ continue;
466
+ }
467
+ if (spi->priority < best.prio) {
468
+ uint32_t intid = 0;
469
+ intid = FIELD_DP32(intid, INTID, ID, i);
470
+ intid = FIELD_DP32(intid, INTID, TYPE, GICV5_SPI);
471
+ best.intid = intid;
472
+ best.prio = spi->priority;
473
+ }
474
+ }
475
+
476
+ trace_gicv5_irs_recalc_hppi(domain_name[domain], iaffid,
477
+ best.intid, best.prio);
478
+
479
+ s->hppi[domain][cpuidx] = best;
480
+ /*
481
+ * Now present the HPPI to the cpuif. In the real hardware stream
482
+ * protocol, the connection between IRS and cpuif is asynchronous,
483
+ * and so both ends track their idea of the current HPPI, with a
484
+ * back-and-forth sequence so they stay in sync and more
485
+ * interaction when the cpuif resets. For QEMU, we are strictly
486
+ * synchronous and the cpuif asking the IRS for data is a cheap
487
+ * function call, so we simplify this:
488
+ * - the IRS knows what the current HPPI is
489
+ * - s->hppi[][] is a cache we can recalculate
490
+ * - the IRS merely tells the cpuif "something changed", and
491
+ * the cpuif asks for the current HPPI when it needs it
492
+ * - the cpuif does not cache the HPPI on its end
493
+ */
494
+ gicv5_forward_interrupt(cpu, domain);
495
+}
496
+
497
+static void irs_recalc_hppi_all_cpus(GICv5 *s, GICv5Domain domain)
498
+{
499
+ /*
500
+ * Recalculate the HPPI for every CPU for this domain. This is
501
+ * not as efficient as it could be because we will scan through
502
+ * the LPI cached hash table and the SPI array for each CPU rather
503
+ * than doing a single combined scan, but we only need to do this
504
+ * very rarely, when the guest enables or disables the IST, so we
505
+ * implement this the simple way.
506
+ */
507
+ GICv5Common *cs = ARM_GICV5_COMMON(s);
508
+ for (int i = 0; i < cs->num_cpus; i++) {
509
+ irs_recalc_hppi(s, domain, cs->cpu_iaffids[i]);
510
+ }
511
+}
512
+
513
+static void irs_recall_hppis(GICv5 *s, GICv5Domain domain)
514
+{
515
+ /*
516
+ * The IRS was just disabled -- we must recall any pending HPPIs
517
+ * we have sent to the CPU interfaces. For us this means that we
518
+ * clear our cached HPPI data and tell the cpuif that it has
519
+ * changed.
520
+ */
521
+ GICv5Common *cs = ARM_GICV5_COMMON(s);
522
+
523
+ for (int i = 0; i < cs->num_cpus; i++) {
524
+ s->hppi[domain][i].intid = 0;
525
+ s->hppi[domain][i].prio = PRIO_IDLE;
526
+ gicv5_forward_interrupt(cs->cpus[i], domain);
527
+ }
528
+}
529
+
530
static hwaddr l1_iste_addr(GICv5Common *cs, const GICv5ISTConfig *cfg,
531
uint32_t id)
532
{
726
GICv5Domain domain, GICv5IntType type, bool virtual)
727
{
728
GICv5 *s = ARM_GICV5(cs);
729
+ uint32_t iaffid;
730
731
trace_gicv5_set_priority(domain_name[domain], inttype_name(type), virtual,
732
id, priority);
750
return;
751
}
752
*l2_iste_p = FIELD_DP32(*l2_iste_p, L2_ISTE, PRIORITY, priority);
753
+ iaffid = FIELD_EX32(*l2_iste_p, L2_ISTE, IAFFID);
754
put_l2_iste(cs, cfg, &h);
755
break;
756
}
765
}
766
767
spi->priority = priority;
768
+ iaffid = spi->iaffid;
769
break;
770
}
771
default:
773
"priority of bad interrupt type %d\n", type);
774
return;
775
}
776
+
777
+ irs_recalc_hppi(s, domain, iaffid);
778
}
779
780
void gicv5_set_enabled(GICv5Common *cs, uint32_t id, bool enabled,
781
GICv5Domain domain, GICv5IntType type, bool virtual)
782
{
783
GICv5 *s = ARM_GICV5(cs);
784
+ uint32_t iaffid;
785
786
trace_gicv5_set_enabled(domain_name[domain], inttype_name(type), virtual,
787
id, enabled);
802
return;
803
}
804
*l2_iste_p = FIELD_DP32(*l2_iste_p, L2_ISTE, ENABLE, enabled);
805
+ iaffid = FIELD_EX32(*l2_iste_p, L2_ISTE, IAFFID);
806
put_l2_iste(cs, cfg, &h);
807
break;
808
}
817
}
818
819
spi->enabled = true;
820
+ iaffid = spi->iaffid;
821
break;
822
}
823
default:
825
"enable state of bad interrupt type %d\n", type);
826
return;
827
}
828
+
829
+ irs_recalc_hppi(s, domain, iaffid);
830
}
831
832
void gicv5_set_pending(GICv5Common *cs, uint32_t id, bool pending,
833
GICv5Domain domain, GICv5IntType type, bool virtual)
834
{
835
GICv5 *s = ARM_GICV5(cs);
836
+ uint32_t iaffid;
837
838
trace_gicv5_set_pending(domain_name[domain], inttype_name(type), virtual,
839
id, pending);
854
return;
855
}
856
*l2_iste_p = FIELD_DP32(*l2_iste_p, L2_ISTE, PENDING, pending);
857
+ iaffid = FIELD_EX32(*l2_iste_p, L2_ISTE, IAFFID);
858
put_l2_iste(cs, cfg, &h);
859
break;
860
}
869
}
870
871
spi->pending = true;
872
+ iaffid = spi->iaffid;
873
break;
874
}
875
default:
877
"pending state of bad interrupt type %d\n", type);
878
return;
879
}
880
+
881
+ irs_recalc_hppi(s, domain, iaffid);
882
}
883
884
void gicv5_set_handling(GICv5Common *cs, uint32_t id,
933
GICv5IntType type, bool virtual)
934
{
935
GICv5 *s = ARM_GICV5(cs);
936
+ uint32_t old_iaffid;
937
938
trace_gicv5_set_target(domain_name[domain], inttype_name(type), virtual,
939
id, iaffid, irm);
967
* L2_ISTE.IRM is RES0. We never read it, and we can skip
968
* explicitly writing it to zero here.
969
*/
970
+ old_iaffid = FIELD_EX32(*l2_iste_p, L2_ISTE, IAFFID);
971
*l2_iste_p = FIELD_DP32(*l2_iste_p, L2_ISTE, IAFFID, iaffid);
972
put_l2_iste(cs, cfg, &h);
973
break;
982
return;
983
}
984
985
+ old_iaffid = spi->iaffid;
986
spi->iaffid = iaffid;
987
break;
988
}
991
"target of bad interrupt type %d\n", type);
992
return;
993
}
994
+
995
+ irs_recalc_hppi(s, domain, old_iaffid);
996
+ irs_recalc_hppi(s, domain, iaffid);
997
}
998
999
static uint64_t l2_iste_to_icsr(GICv5Common *cs, const GICv5ISTConfig *cfg,
1114
if (res != MEMTX_OK) {
1115
goto txfail;
1116
}
1117
+ /*
1118
+ * It's CONSTRAINED UNPREDICTABLE to make an L2 IST valid when
1119
+ * some of its entries have Pending already set, so we don't need
1120
+ * to go through looking for Pending bits and pulling them into
1121
+ * the cache, and we don't need to recalc our HPPI.
1122
+ */
1123
return;
1124
1125
txfail:
1177
IRS_IST_BASER, VALID, valid);
1178
s->phys_lpi_config[domain].valid = false;
1179
trace_gicv5_ist_invalid(domain_name[domain]);
1180
+ irs_recalc_hppi_all_cpus(s, domain);
1181
return;
1182
}
1183
cs->irs_ist_baser[domain] = value;
1247
cfg->valid = true;
1248
trace_gicv5_ist_valid(domain_name[domain], cfg->base, cfg->id_bits,
1249
cfg->l2_idx_bits, cfg->istsz, cfg->structure);
1250
+ irs_recalc_hppi_all_cpus(s, domain);
1251
}
1252
}
1253
1403
case A_IRS_CR0:
1404
/* Enabling is instantaneous for us so IDLE is always 1 */
1405
*data = cs->irs_cr0[domain] | R_IRS_CR0_IDLE_MASK;
1406
+ if (FIELD_EX32(cs->irs_cr0[domain], IRS_CR0, IRSEN)) {
1407
+ irs_recalc_hppi_all_cpus(s, domain);
1408
+ } else {
1409
+ irs_recall_hppis(s, domain);
1410
+ }
1411
return true;
1412
case A_IRS_CR1:
1413
*data = cs->irs_cr1[domain];
1496
} else if (spi->level) {
1497
spi->pending = false;
1498
}
1499
+ irs_recalc_hppi(s, spi->domain, spi->iaffid);
1500
}
1501
}
1502
return true;
1506
/* this is RAZ/WI except for the EL3 domain */
1507
GICv5SPIState *spi = spi_for_selr(cs, domain);
1508
if (spi) {
1509
+ GICv5Domain old_domain = spi->domain;
1510
spi->domain = FIELD_EX32(data, IRS_SPI_DOMAINR, DOMAIN);
1511
+ if (spi->domain != old_domain) {
1512
+ irs_recalc_hppi(s, old_domain, spi->iaffid);
1513
+ irs_recalc_hppi(s, spi->domain, spi->iaffid);
1514
+ }
1515
}
1516
}
1517
return true;
1522
1523
if (spi) {
1524
spi_sample(spi);
1525
+ irs_recalc_hppi(s, spi->domain, spi->iaffid);
1526
}
1527
trace_gicv5_spi_state(id, spi->level, spi->pending, spi->active);
1528
return true;
1691
{
1692
/* These irqs are all SPIs; the INTID is irq + s->spi_base */
1693
GICv5Common *cs = ARM_GICV5_COMMON(opaque);
1694
+ GICv5 *s = ARM_GICV5(cs);
1695
uint32_t spi_id = irq + cs->spi_base;
1696
GICv5SPIState *spi = gicv5_raw_spi_state(cs, spi_id);
1697
1704
spi->level = level;
1705
spi_sample(spi);
1706
trace_gicv5_spi_state(spi_id, spi->level, spi->pending, spi->active);
1707
+
1708
+ irs_recalc_hppi(s, spi->domain, spi->iaffid);
1709
}
1710
1711
static void gicv5_reset_hold(Object *obj, ResetType type)
1786
1787
static void gicv5_realize(DeviceState *dev, Error **errp)
1788
{
1789
+ GICv5 *s = ARM_GICV5(dev);
1790
GICv5Common *cs = ARM_GICV5_COMMON(dev);
1791
GICv5Class *gc = ARM_GICV5_GET_CLASS(dev);
1792
Error *migration_blocker = NULL;
1814
1815
gicv5_set_idregs(cs);
1816
gicv5_common_init_irqs_and_mmio(cs, gicv5_set_spi, config_frame_ops);
1817
+
1818
+ for (int i = 0; i < NUM_GICV5_DOMAINS; i++) {
1819
+ if (gicv5_domain_implemented(cs, i)) {
1820
+ s->hppi[i] = g_new0(GICv5PendingIrq, cs->num_cpus);
1821
+ }
1822
+ }
1823
}
1824
1825
static void gicv5_init(Object *obj)