Implement the GIC CDEOI instruction, which performs a "priority drop", clearing the highest set bit in the APR register.
Signed-off-by: Peter Maydell <[email protected]> --- 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 d32263a5b7..c830938bdc 100644 --- a/target/arm/tcg/gicv5-cpuif.c +++ b/target/arm/tcg/gicv5-cpuif.c @@ -556,6 +556,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 @@ -608,6 +624,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
