@@ -161,16 +161,22 @@ static MemTxResult get_cte(GICv3ITSState *s, uint16_t icid, CTEntry *cte)
if (entry_addr == -1) {
/* No L2 table entry, i.e. no valid CTE, or a memory error */
cte->valid = false;
- return res;
+ goto out;
}
cteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
if (res != MEMTX_OK) {
- return res;
+ goto out;
}
cte->valid = FIELD_EX64(cteval, CTE, VALID);
cte->rdbase = FIELD_EX64(cteval, CTE, RDBASE);
- return MEMTX_OK;
+out:
+ if (res != MEMTX_OK) {
+ trace_gicv3_its_cte_read_fault(icid);
+ } else {
+ trace_gicv3_its_cte_read(icid, cte->valid, cte->rdbase);
+ }
+ return res;
}
/*
@@ -187,6 +193,10 @@ static bool update_ite(GICv3ITSState *s, uint32_t eventid, const DTEntry *dte,
uint64_t itel = 0;
uint32_t iteh = 0;
+ trace_gicv3_its_ite_write(dte->ittaddr, eventid, ite->valid,
+ ite->inttype, ite->intid, ite->icid,
+ ite->vpeid, ite->doorbell);
+
if (ite->valid) {
itel = FIELD_DP64(itel, ITE_L, VALID, 1);
itel = FIELD_DP64(itel, ITE_L, INTTYPE, ite->inttype);
@@ -221,11 +231,13 @@ static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid,
itel = address_space_ldq_le(as, iteaddr, MEMTXATTRS_UNSPECIFIED, &res);
if (res != MEMTX_OK) {
+ trace_gicv3_its_ite_read_fault(dte->ittaddr, eventid);
return res;
}
iteh = address_space_ldl_le(as, iteaddr + 8, MEMTXATTRS_UNSPECIFIED, &res);
if (res != MEMTX_OK) {
+ trace_gicv3_its_ite_read_fault(dte->ittaddr, eventid);
return res;
}
@@ -235,6 +247,9 @@ static MemTxResult get_ite(GICv3ITSState *s, uint32_t eventid,
ite->icid = FIELD_EX64(itel, ITE_L, ICID);
ite->vpeid = FIELD_EX64(itel, ITE_L, VPEID);
ite->doorbell = FIELD_EX64(iteh, ITE_H, DOORBELL);
+ trace_gicv3_its_ite_read(dte->ittaddr, eventid, ite->valid,
+ ite->inttype, ite->intid, ite->icid,
+ ite->vpeid, ite->doorbell);
return MEMTX_OK;
}
@@ -254,17 +269,23 @@ static MemTxResult get_dte(GICv3ITSState *s, uint32_t devid, DTEntry *dte)
if (entry_addr == -1) {
/* No L2 table entry, i.e. no valid DTE, or a memory error */
dte->valid = false;
- return res;
+ goto out;
}
dteval = address_space_ldq_le(as, entry_addr, MEMTXATTRS_UNSPECIFIED, &res);
if (res != MEMTX_OK) {
- return res;
+ goto out;
}
dte->valid = FIELD_EX64(dteval, DTE, VALID);
dte->size = FIELD_EX64(dteval, DTE, SIZE);
/* DTE word field stores bits [51:8] of the ITT address */
dte->ittaddr = FIELD_EX64(dteval, DTE, ITTADDR) << ITTADDR_SHIFT;
- return MEMTX_OK;
+out:
+ if (res != MEMTX_OK) {
+ trace_gicv3_its_dte_read_fault(devid);
+ } else {
+ trace_gicv3_its_dte_read(devid, dte->valid, dte->size, dte->ittaddr);
+ }
+ return res;
}
/*
@@ -465,6 +486,8 @@ static bool update_cte(GICv3ITSState *s, uint16_t icid, const CTEntry *cte)
uint64_t cteval = 0;
MemTxResult res = MEMTX_OK;
+ trace_gicv3_its_cte_write(icid, cte->valid, cte->rdbase);
+
if (cte->valid) {
/* add mapping entry to collection table */
cteval = FIELD_DP64(cteval, CTE, VALID, 1);
@@ -524,6 +547,8 @@ static bool update_dte(GICv3ITSState *s, uint32_t devid, const DTEntry *dte)
uint64_t dteval = 0;
MemTxResult res = MEMTX_OK;
+ trace_gicv3_its_dte_write(devid, dte->valid, dte->size, dte->ittaddr);
+
if (dte->valid) {
/* add mapping entry to device table */
dteval = FIELD_DP64(dteval, DTE, VALID, 1);
@@ -188,6 +188,15 @@ gicv3_its_cmd_inv(void) "GICv3 ITS: command INV or INVALL"
gicv3_its_cmd_movall(uint64_t rd1, uint64_t rd2) "GICv3 ITS: command MOVALL RDbase1 0x%" PRIx64 " RDbase2 0x%" PRIx64
gicv3_its_cmd_movi(uint32_t devid, uint32_t eventid, uint32_t icid) "GICv3 ITS: command MOVI DeviceID 0x%x EventID 0x%x ICID 0x%x"
gicv3_its_cmd_unknown(unsigned cmd) "GICv3 ITS: unknown command 0x%x"
+gicv3_its_cte_read(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table read for ICID 0x%x: valid %d RDBase 0x%x"
+gicv3_its_cte_write(uint32_t icid, int valid, uint32_t rdbase) "GICv3 ITS: Collection Table write for ICID 0x%x: valid %d RDBase 0x%x"
+gicv3_its_cte_read_fault(uint32_t icid) "GICv3 ITS: Collection Table read for ICID 0x%x: faulted"
+gicv3_its_ite_read(uint64_t ittaddr, uint32_t eventid, int valid, int inttype, uint32_t intid, uint32_t icid, uint32_t vpeid, uint32_t doorbell) "GICv3 ITS: Interrupt Table read for ITTaddr 0x%" PRIx64 " EventID 0x%x: valid %d inttype %d intid 0x%x ICID 0x%x vPEID 0x%x doorbell 0x%x"
+gicv3_its_ite_read_fault(uint64_t ittaddr, uint32_t eventid) "GICv3 ITS: Interrupt Table read for ITTaddr 0x%" PRIx64 " EventID 0x%x: faulted"
+gicv3_its_ite_write(uint64_t ittaddr, uint32_t eventid, int valid, int inttype, uint32_t intid, uint32_t icid, uint32_t vpeid, uint32_t doorbell) "GICv3 ITS: Interrupt Table write for ITTaddr 0x%" PRIx64 " EventID 0x%x: valid %d inttype %d intid 0x%x ICID 0x%x vPEID 0x%x doorbell 0x%x"
+gicv3_its_dte_read(uint32_t devid, int valid, uint32_t size, uint64_t ittaddr) "GICv3 ITS: Device Table read for DeviceID 0x%x: valid %d size 0x%x ITTaddr 0x%" PRIx64
+gicv3_its_dte_write(uint32_t devid, int valid, uint32_t size, uint64_t ittaddr) "GICv3 ITS: Device Table write for DeviceID 0x%x: valid %d size 0x%x ITTaddr 0x%" PRIx64
+gicv3_its_dte_read_fault(uint32_t devid) "GICv3 ITS: Device Table read for DeviceID 0x%x: faulted"
# armv7m_nvic.c
nvic_recompute_state(int vectpending, int vectpending_prio, int exception_prio) "NVIC state recomputed: vectpending %d vectpending_prio %d exception_prio %d"
For debugging guest use of the ITS, it can be helpful to trace when the ITS reads and writes the in-memory tables. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> --- hw/intc/arm_gicv3_its.c | 37 +++++++++++++++++++++++++++++++------ hw/intc/trace-events | 9 +++++++++ 2 files changed, 40 insertions(+), 6 deletions(-)