aboutsummaryrefslogtreecommitdiff
path: root/hw/intc
diff options
context:
space:
mode:
Diffstat (limited to 'hw/intc')
-rw-r--r--hw/intc/arm_gicv3_its.c28
-rw-r--r--hw/intc/gicv3_internal.h19
2 files changed, 21 insertions, 26 deletions
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index b94775fd37..48eaf20a6c 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -173,14 +173,12 @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
{
AddressSpace *as = &s->gicv3->dma_as;
MemTxResult res = MEMTX_OK;
+ hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
- address_space_stq_le(as, dte->ittaddr + (eventid * (sizeof(uint64_t) +
- sizeof(uint32_t))), ite.itel, MEMTXATTRS_UNSPECIFIED,
- &res);
+ address_space_stq_le(as, iteaddr, ite.itel, MEMTXATTRS_UNSPECIFIED, &res);
if (res == MEMTX_OK) {
- address_space_stl_le(as, dte->ittaddr + (eventid * (sizeof(uint64_t) +
- sizeof(uint32_t))) + sizeof(uint32_t), ite.iteh,
+ address_space_stl_le(as, iteaddr + 8, ite.iteh,
MEMTXATTRS_UNSPECIFIED, &res);
}
if (res != MEMTX_OK) {
@@ -196,16 +194,12 @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
AddressSpace *as = &s->gicv3->dma_as;
bool status = false;
IteEntry ite = {};
+ hwaddr iteaddr = dte->ittaddr + eventid * ITS_ITT_ENTRY_SIZE;
- ite.itel = address_space_ldq_le(as, dte->ittaddr +
- (eventid * (sizeof(uint64_t) +
- sizeof(uint32_t))), MEMTXATTRS_UNSPECIFIED,
- res);
+ ite.itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, res);
if (*res == MEMTX_OK) {
- ite.iteh = address_space_ldl_le(as, dte->ittaddr +
- (eventid * (sizeof(uint64_t) +
- sizeof(uint32_t))) + sizeof(uint32_t),
+ ite.iteh = address_space_ldl_le(as, iteaddr + 8,
MEMTXATTRS_UNSPECIFIED, res);
if (*res == MEMTX_OK) {
@@ -213,7 +207,7 @@ static bool get_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
int inttype = FIELD_EX64(ite.itel, ITE_L, INTTYPE);
if (inttype == ITE_INTTYPE_PHYSICAL) {
*pIntid = FIELD_EX64(ite.itel, ITE_L, INTID);
- *icid = FIELD_EX32(ite.iteh, ITE_H, ICID);
+ *icid = FIELD_EX64(ite.itel, ITE_L, ICID);
status = true;
}
}
@@ -412,8 +406,8 @@ static ItsCmdResult process_mapti(GICv3ITSState *s, const uint64_t *cmdpkt,
ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, true);
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, pIntid);
- ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
- ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, icid);
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, icid);
+ ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
}
@@ -688,8 +682,8 @@ static ItsCmdResult process_movi(GICv3ITSState *s, const uint64_t *cmdpkt)
ite.itel = FIELD_DP64(ite.itel, ITE_L, VALID, 1);
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTTYPE, ITE_INTTYPE_PHYSICAL);
ite.itel = FIELD_DP64(ite.itel, ITE_L, INTID, intid);
- ite.itel = FIELD_DP64(ite.itel, ITE_L, DOORBELL, INTID_SPURIOUS);
- ite.iteh = FIELD_DP32(ite.iteh, ITE_H, ICID, new_icid);
+ ite.itel = FIELD_DP64(ite.itel, ITE_L, ICID, new_icid);
+ ite.iteh = FIELD_DP32(ite.iteh, ITE_H, DOORBELL, INTID_SPURIOUS);
return update_ite(s, eventid, &dte, ite) ? CMD_CONTINUE : CMD_STALL;
}
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 60c8617e4e..2bf1baef04 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -370,22 +370,23 @@ FIELD(MOVI_2, ICID, 0, 16)
* 12 bytes Interrupt translation Table Entry size
* as per Table 5.3 in GICv3 spec
* ITE Lower 8 Bytes
- * Bits: | 49 ... 26 | 25 ... 2 | 1 | 0 |
- * Values: | Doorbell | IntNum | IntType | Valid |
+ * Bits: | 63 ... 48 | 47 ... 32 | 31 ... 26 | 25 ... 2 | 1 | 0 |
+ * Values: | vPEID | ICID | unused | IntNum | IntType | Valid |
* ITE Higher 4 Bytes
- * Bits: | 31 ... 16 | 15 ...0 |
- * Values: | vPEID | ICID |
- * (When Doorbell is unused, as it always is in GICv3, it is 1023)
+ * Bits: | 31 ... 25 | 24 ... 0 |
+ * Values: | unused | Doorbell |
+ * (When Doorbell is unused, as it always is for INTYPE_PHYSICAL,
+ * the value of that field in memory cannot be relied upon -- older
+ * versions of QEMU did not correctly write to that memory.)
*/
#define ITS_ITT_ENTRY_SIZE 0xC
FIELD(ITE_L, VALID, 0, 1)
FIELD(ITE_L, INTTYPE, 1, 1)
FIELD(ITE_L, INTID, 2, 24)
-FIELD(ITE_L, DOORBELL, 26, 24)
-
-FIELD(ITE_H, ICID, 0, 16)
-FIELD(ITE_H, VPEID, 16, 16)
+FIELD(ITE_L, ICID, 32, 16)
+FIELD(ITE_L, VPEID, 48, 16)
+FIELD(ITE_H, DOORBELL, 0, 24)
/* Possible values for ITE_L INTTYPE */
#define ITE_INTTYPE_VIRTUAL 0