@samitouri / QOSamiQemu / commits / 4ea9fa2637

target/arm: GICv5 cpuif: Implement GICv5 PPI active set/clear registers

In the GICv5 PPI state and control lives in the CPU interface; this is different from the GICv3 where this was all in the redistributor. Implement the access system registers for the PPI active state; this is a pair of registers, one of which has "write 1 to clear" behaviour and the other of which has "write 1 to set". In both cases, reads return the current state. We start here by implementing the accessors for the underlying state; we don't yet attempt to do anything (e.g. recalculating the highest priority pending PPI) when the state changes. That will come in subsequent commits. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Message-id: 20260327111700.795099-37-peter.maydell@linaro.org

Peter Maydell committed Mar 27, 2026 at 11:16 UTC 4ea9fa263716f4a1ddbcfc1d731a27dfde6b9e0b
2 files changed +43
target/arm/cpu.h
+5
@@ -256,6 +256,9 @@ typedef enum ARMFPStatusFlavour {
256 } ARMFPStatusFlavour;
257 #define FPST_COUNT 10
258
259 +/* Architecturally there are 128 PPIs in a GICv5 */
260 +#define GICV5_NUM_PPIS 128
261 +
262 typedef struct CPUArchState {
263 /* Regs for current mode. */
264 uint32_t regs[16];
@@ -599,6 +602,8 @@ typedef struct CPUArchState {
602 struct {
603 /* GICv5 CPU interface data */
604 uint64_t icc_icsr_el1;
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 } gicv5_cpuif;
608
609 struct {
target/arm/tcg/gicv5-cpuif.c
+38
@@ -175,6 +175,20 @@ static void gic_cdhm_write(CPUARMState *env, const ARMCPRegInfo *ri,
175 gicv5_set_handling(gic, id, hm, domain, type, virtual);
176 }
177
178 +static void gic_ppi_cactive_write(CPUARMState *env, const ARMCPRegInfo *ri,
179 + uint64_t value)
180 +{
181 + uint64_t old = raw_read(env, ri);
182 + raw_write(env, ri, old & ~value);
183 +}
184 +
185 +static void gic_ppi_sactive_write(CPUARMState *env, const ARMCPRegInfo *ri,
186 + uint64_t value)
187 +{
188 + uint64_t old = raw_read(env, ri);
189 + raw_write(env, ri, old | value);
190 +}
191 +
192 static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
193 /*
194 * Barrier: wait until the effects of a cpuif system register
@@ -254,6 +268,30 @@ static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
268 */
269 .resetfn = arm_cp_reset_ignore,
270 },
271 + { .name = "ICC_PPI_CACTIVER0_EL1", .state = ARM_CP_STATE_AA64,
272 + .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 0,
273 + .access = PL1_RW, .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW,
274 + .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_active[0]),
275 + .writefn = gic_ppi_cactive_write,
276 + },
277 + { .name = "ICC_PPI_CACTIVER1_EL1", .state = ARM_CP_STATE_AA64,
278 + .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 1,
279 + .access = PL1_RW, .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW,
280 + .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_active[1]),
281 + .writefn = gic_ppi_cactive_write,
282 + },
283 + { .name = "ICC_PPI_SACTIVER0_EL1", .state = ARM_CP_STATE_AA64,
284 + .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 2,
285 + .access = PL1_RW, .type = ARM_CP_IO | ARM_CP_NO_RAW,
286 + .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_active[0]),
287 + .writefn = gic_ppi_sactive_write,
288 + },
289 + { .name = "ICC_PPI_SACTIVER1_EL1", .state = ARM_CP_STATE_AA64,
290 + .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 3,
291 + .access = PL1_RW, .type = ARM_CP_IO | ARM_CP_NO_RAW,
292 + .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_active[1]),
293 + .writefn = gic_ppi_sactive_write,
294 + },
295 };
296
297 void define_gicv5_cpuif_regs(ARMCPU *cpu)