Implement the GIC CDDI system instruction, which deactivates the
specified interrupt.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
target/arm/tcg/gicv5-cpuif.c | 49 ++++++++++++++++++++++++++++++++++++
target/arm/tcg/trace-events | 1 +
2 files changed, 50 insertions(+)
diff --git a/target/arm/tcg/gicv5-cpuif.c b/target/arm/tcg/gicv5-cpuif.c
index 0974637c92..94590bd765 100644
--- a/target/arm/tcg/gicv5-cpuif.c
+++ b/target/arm/tcg/gicv5-cpuif.c
@@ -17,6 +17,9 @@ FIELD(GIC_CDPRI, ID, 0, 24)
FIELD(GIC_CDPRI, TYPE, 29, 3)
FIELD(GIC_CDPRI, PRIORITY, 35, 5)
+FIELD(GIC_CDDI, ID, 0, 24)
+FIELD(GIC_CDDI, TYPE, 29, 3)
+
FIELD(GIC_CDDIS, ID, 0, 24)
FIELD(GIC_CDDIS, TYPE, 29, 3)
@@ -570,6 +573,47 @@ static void gic_cdeoi_write(CPUARMState *env, const ARMCPRegInfo *ri,
*apr &= *apr - 1;
}
+static void gic_cddi_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /*
+ * Clear the Active state of the specified interrupt in the
+ * current interrupt domain.
+ */
+ GICv5Common *gic = gicv5_get_gic(env);
+ GICv5Domain domain = gicv5_current_phys_domain(env);
+ GICv5IntType type = FIELD_EX64(value, GIC_CDDI, TYPE);
+ uint32_t id = FIELD_EX64(value, GIC_CDDI, ID);
+ bool virtual = false;
+
+ trace_gicv5_cddi(domain, value);
+
+ switch (type) {
+ case GICV5_PPI:
+ {
+ uint32_t ppireg, ppibit;
+
+ if (id >= GICV5_NUM_PPIS) {
+ break;
+ }
+
+ ppireg = id / 64;
+ ppibit = 1 << (id % 64);
+
+ env->gicv5_cpuif.ppi_active[ppireg] &= ~ppibit;
+ gic_recalc_ppi_hppi(env);
+ break;
+ }
+ case GICV5_LPI:
+ case GICV5_SPI:
+ /* Tell the IRS to deactivate this interrupt */
+ gicv5_deactivate(gic, id, domain, type, virtual);
+ break;
+ default:
+ break;
+ }
+}
+
static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
/*
* Barrier: wait until the effects of a cpuif system register
@@ -627,6 +671,11 @@ static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
.access = PL1_W, .type = ARM_CP_IO | ARM_CP_NO_RAW,
.writefn = gic_cdeoi_write,
},
+ { .name = "GIC_CDDI", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 12, .crm = 2, .opc2 = 0,
+ .access = PL1_W, .type = ARM_CP_IO | ARM_CP_NO_RAW,
+ .writefn = gic_cddi_write,
+ },
{ .name = "GIC_CDHM", .state = ARM_CP_STATE_AA64,
.opc0 = 1, .opc1 = 0, .crn = 12, .crm = 2, .opc2 = 1,
.access = PL1_W, .type = ARM_CP_IO | ARM_CP_NO_RAW,
diff --git a/target/arm/tcg/trace-events b/target/arm/tcg/trace-events
index fcb3106a96..c60ce6834e 100644
--- a/target/arm/tcg/trace-events
+++ b/target/arm/tcg/trace-events
@@ -6,3 +6,4 @@ gicv5_recalc_ppi_hppi(int domain, uint32_t id, uint8_t prio) "domain %d new PPI
gicv5_gicr_cdia_fail(int domain, const char *reason) "domain %d CDIA attempt failed: %s"
gicv5_gicr_cdia(int domain, uint32_t id) "domain %d CDIA acknowledge of interrupt 0x%x"
gicv5_cdeoi(int domain) "domain %d CDEOI performing priority drop"
+gicv5_cddi(int domain, uint32_t id) "domain %d CDDI deactivating interrupt ID 0x%x"
--
2.43.0