target/arm: GICv5 cpuif: Implement PPI pending status registers
The GICv5 PPI pending status is handled by two registers, one of which is write-1-to-set and one of which is write-1-to-clear. The pending state is read-only for PPIs where the handling mode is Edge. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Message-id: 20260327111700.795099-39-peter.maydell@linaro.org
Peter Maydell committed
Mar 27, 2026 at 11:16 UTC
585dad9e79e1d64075e99448ee34adbeeeeea056
2 files changed
+45
target/arm/cpu.h
+1
@@ -605,6 +605,7 @@ typedef struct CPUArchState {
605
/* Most PPI registers have 1 bit per PPI, so 64 PPIs to a register */
606
uint64_t ppi_active[GICV5_NUM_PPIS / 64];
607
uint64_t ppi_hm[GICV5_NUM_PPIS / 64];
608
+ uint64_t ppi_pend[GICV5_NUM_PPIS / 64];
609
} gicv5_cpuif;
610
611
struct {
target/arm/tcg/gicv5-cpuif.c
+44
@@ -199,6 +199,26 @@ static void gic_ppi_sactive_write(CPUARMState *env, const ARMCPRegInfo *ri,
199
raw_write(env, ri, old | value);
200
}
201
202
+static void gic_ppi_cpend_write(CPUARMState *env, const ARMCPRegInfo *ri,
203
+ uint64_t value)
204
+{
205
+ uint64_t old = raw_read(env, ri);
206
+ /* If ICC_PPI_HMR_EL1[n].HM is 1, PEND bits are RO */
207
+ uint64_t hm = env->gicv5_cpuif.ppi_hm[ri->opc2 & 1];
208
+ value &= ~hm;
209
+ raw_write(env, ri, old & ~value);
210
+}
211
+
212
+static void gic_ppi_spend_write(CPUARMState *env, const ARMCPRegInfo *ri,
213
+ uint64_t value)
214
+{
215
+ uint64_t old = raw_read(env, ri);
216
+ /* If ICC_PPI_HMR_EL1[n].HM is 1, PEND bits are RO */
217
+ uint64_t hm = env->gicv5_cpuif.ppi_hm[ri->opc2 & 1];
218
+ value &= ~hm;
219
+ raw_write(env, ri, old | value);
220
+}
221
+
222
static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
223
/*
224
* Barrier: wait until the effects of a cpuif system register
@@ -314,6 +334,30 @@ static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
334
.fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_hm[1]),
335
.resetvalue = PPI_HMR1_RESET,
336
},
337
+ { .name = "ICC_PPI_CPENDR0_EL1", .state = ARM_CP_STATE_AA64,
338
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 4,
339
+ .access = PL1_RW, .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW,
340
+ .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_pend[0]),
341
+ .writefn = gic_ppi_cpend_write,
342
+ },
343
+ { .name = "ICC_PPI_CPENDR1_EL1", .state = ARM_CP_STATE_AA64,
344
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 5,
345
+ .access = PL1_RW, .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW,
346
+ .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_pend[1]),
347
+ .writefn = gic_ppi_cpend_write,
348
+ },
349
+ { .name = "ICC_PPI_SPENDR0_EL1", .state = ARM_CP_STATE_AA64,
350
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 6,
351
+ .access = PL1_RW, .type = ARM_CP_IO | ARM_CP_NO_RAW,
352
+ .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_pend[0]),
353
+ .writefn = gic_ppi_spend_write,
354
+ },
355
+ { .name = "ICC_PPI_SPENDR0_EL1", .state = ARM_CP_STATE_AA64,
356
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 7,
357
+ .access = PL1_RW, .type = ARM_CP_IO | ARM_CP_NO_RAW,
358
+ .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_pend[1]),
359
+ .writefn = gic_ppi_spend_write,
360
+ },
361
};
362
363
void define_gicv5_cpuif_regs(ARMCPU *cpu)