@samitouri / QOSamiQemu / commits / 2ad2689070

hw/intc/arm_gicv5: Implement IRS_MAP_L2_ISTR

The IRS register IRS_MAP_L2_ISTR is used by software to tell the IRS that it has updated the address in an L1 IST entry to point to an L2 IST. The sequence of events here is: * software writes to L1_ISTE.L2_ADDR for some L1 ISTE which is not valid (i.e. where L1_ISTE.VALID is 0); it leaves VALID at 0 * software writes to IRS_MAP_L2_ISTR with some INTID that is inside the range for this L1 ISTE * the IRS sets IRS_IST_STATUSR.IDLE to 0 * the IRS takes note of this information * the IRS writes to the L1_ISTE to set VALID=1 * the IRS sets IRS_IST_STATUSR.IDLE to 1 to indicate that the update is complete For QEMU, we're strictly synchronous, so (as with IRS_IST_BASER updates) we don't need to model the IDLE transitions and can have IRS_IST_STATUSR always return IDLE=1. We also don't currently cache anything for ISTE lookups, so we don't need to invalidate or update anything when software makes the L2 valid. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Message-id: 20260327111700.795099-21-peter.maydell@linaro.org

Peter Maydell committed Mar 27, 2026 at 11:16 UTC 2ad2689070c29dbfa07b0a81ecce9f889b7bcee1
1 file changed +40
hw/intc/arm_gicv5.c
+40
@@ -497,6 +497,43 @@ void gicv5_set_priority(GICv5Common *cs, uint32_t id, uint8_t priority,
497 }
498 }
499
500 +static void irs_map_l2_istr_write(GICv5 *s, GICv5Domain domain, uint64_t value)
501 +{
502 + GICv5Common *cs = ARM_GICV5_COMMON(s);
503 + GICv5ISTConfig *cfg = &s->phys_lpi_config[domain];
504 + uint32_t intid = FIELD_EX32(value, IRS_MAP_L2_ISTR, ID);
505 + hwaddr l1_addr;
506 + uint64_t l1_iste;
507 + MemTxResult res;
508 +
509 + if (!FIELD_EX64(cs->irs_ist_baser[domain], IRS_IST_BASER, VALID) ||
510 + !cfg->structure) {
511 + /* WI if no IST set up or it is not 2-level */
512 + return;
513 + }
514 +
515 + /* Find the relevant L1 ISTE and set its VALID bit */
516 + l1_addr = l1_iste_addr(cs, cfg, intid);
517 +
518 + l1_iste = address_space_ldq_le(&cs->dma_as, l1_addr, cfg->txattrs, &res);
519 + if (res != MEMTX_OK) {
520 + goto txfail;
521 + }
522 +
523 + l1_iste = FIELD_DP64(l1_iste, L1_ISTE, VALID, 1);
524 +
525 + address_space_stq_le(&cs->dma_as, l1_addr, l1_iste, cfg->txattrs, &res);
526 + if (res != MEMTX_OK) {
527 + goto txfail;
528 + }
529 + return;
530 +
531 +txfail:
532 + /* Reportable with EC=0x0 if sw error reporting implemented */
533 + qemu_log_mask(LOG_GUEST_ERROR, "L1 ISTE update failed for ID 0x%x at "
534 + "physical address 0x" HWADDR_FMT_plx "\n", intid, l1_addr);
535 +}
536 +
537 static void irs_ist_baser_write(GICv5 *s, GICv5Domain domain, uint64_t value)
538 {
539 GICv5Common *cs = ARM_GICV5_COMMON(s);
@@ -683,6 +720,9 @@ static bool config_writel(GICv5 *s, GICv5Domain domain, hwaddr offset,
720 cs->irs_ist_cfgr[domain] = data;
721 }
722 return true;
723 + case A_IRS_MAP_L2_ISTR:
724 + irs_map_l2_istr_write(s, domain, data);
725 + return true;
726 }
727
728 return false;