FIELD(ICSR, PRIORITY, 11, 5)
FIELD(ICSR, IAFFID, 32, 16)
+static GICv5SPIState *spi_for_selr(GICv5Common *cs, GICv5Domain domain)
+{
+ /*
+ * If the IRS_SPI_SELR value specifies an SPI that can be managed in
+ * this domain, return a pointer to its GICv5SPIState; otherwise
+ * return NULL.
+ */
+ uint32_t id = FIELD_EX32(cs->irs_spi_selr[domain], IRS_SPI_SELR, ID);
+ GICv5SPIState *spi = gicv5_raw_spi_state(cs, id);
+
+ if (spi && (domain == GICV5_ID_EL3 || domain == spi->domain)) {
+ return spi;
+ }
+ return NULL;
+}
+
static MemTxAttrs irs_txattrs(GICv5Common *cs, GICv5Domain domain)
{
/*
case A_IRS_IST_CFGR:
*data = cs->irs_ist_cfgr[domain];
return true;
+
+ case A_IRS_SPI_STATUSR:
+ /*
+ * QEMU writes to IRS_SPI_{CFGR,DOMAINR,SELR,VMR} take effect
+ * instantaneously, so the guest can never see the IDLE bit as 0.
+ */
+ v = FIELD_DP32(v, IRS_SPI_STATUSR, V,
+ spi_for_selr(cs, domain) != NULL);
+ v = FIELD_DP32(v, IRS_SPI_STATUSR, IDLE, 1);
+ *data = v;
+ return true;
+
+ case A_IRS_SPI_CFGR:
+ {
+ GICv5SPIState *spi = spi_for_selr(cs, domain);
+
+ if (spi) {
+ v = FIELD_DP32(v, IRS_SPI_CFGR, TM, spi->tm);
+ }
+ *data = v;
+ return true;
+ }
+ case A_IRS_SPI_DOMAINR:
+ if (domain == GICV5_ID_EL3) {
+ /* This is RAZ/WI except for the EL3 domain */
+ GICv5SPIState *spi = spi_for_selr(cs, domain);
+ if (spi) {
+ v = FIELD_DP32(v, IRS_SPI_DOMAINR, DOMAIN, spi->domain);
+ }
+ }
+ *data = v;
+ return true;
}
return false;
case A_IRS_MAP_L2_ISTR:
irs_map_l2_istr_write(s, domain, data);
return true;
+ case A_IRS_SPI_SELR:
+ cs->irs_spi_selr[domain] = data;
+ return true;
+ case A_IRS_SPI_CFGR:
+ {
+ GICv5SPIState *spi = spi_for_selr(cs, domain);
+ if (spi) {
+ spi->tm = FIELD_EX32(data, IRS_SPI_CFGR, TM);
+ }
+ return true;
+ }
+ case A_IRS_SPI_DOMAINR:
+ if (domain == GICV5_ID_EL3) {
+ /* this is RAZ/WI except for the EL3 domain */
+ GICv5SPIState *spi = spi_for_selr(cs, domain);
+ if (spi) {
+ spi->domain = FIELD_EX32(data, IRS_SPI_DOMAINR, DOMAIN);
+ }
+ }
+ return true;
}
return false;