Implement the GIC CDEOI instruction, which performs a "priority
drop", clearing the highest set bit in the APR register.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com>
---
target/arm/tcg/gicv5-cpuif.c | 21 +++++++++++++++++++++
target/arm/tcg/trace-events | 1 +
2 files changed, 22 insertions(+)
diff --git a/target/arm/tcg/gicv5-cpuif.c b/target/arm/tcg/gicv5-cpuif.c
index 09870e0b09..0974637c92 100644
--- a/target/arm/tcg/gicv5-cpuif.c
+++ b/target/arm/tcg/gicv5-cpuif.c
@@ -554,6 +554,22 @@ static uint64_t gicr_cdia_read(CPUARMState *env, const ARMCPRegInfo *ri)
return hppi.intid | R_GICR_CDIA_VALID_MASK;
}
+static void gic_cdeoi_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ /*
+ * Perform Priority Drop in the current interrupt domain.
+ * This is just clearing the lowest set bit in the APR.
+ */
+ GICv5Domain domain = gicv5_current_phys_domain(env);
+ uint64_t *apr = &env->gicv5_cpuif.icc_apr[domain];
+
+ trace_gicv5_cdeoi(domain);
+
+ /* clear lowest bit, doing nothing if already zero */
+ *apr &= *apr - 1;
+}
+
static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
/*
* Barrier: wait until the effects of a cpuif system register
@@ -606,6 +622,11 @@ static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
.access = PL1_W, .type = ARM_CP_IO | ARM_CP_NO_RAW,
.writefn = gic_cdrcfg_write,
},
+ { .name = "GIC_CDEOI", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 12, .crm = 1, .opc2 = 7,
+ .access = PL1_W, .type = ARM_CP_IO | ARM_CP_NO_RAW,
+ .writefn = gic_cdeoi_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 13e15cfcfc..fcb3106a96 100644
--- a/target/arm/tcg/trace-events
+++ b/target/arm/tcg/trace-events
@@ -5,3 +5,4 @@
gicv5_recalc_ppi_hppi(int domain, uint32_t id, uint8_t prio) "domain %d new PPI HPPI id 0x%x prio %u"
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"
--
2.43.0