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 <[email protected]> --- target/arm/cpu.h | 5 +++++ target/arm/tcg/gicv5-cpuif.c | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index a32c5f3ab1..dd4dc12feb 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -257,6 +257,9 @@ typedef enum ARMFPStatusFlavour { } ARMFPStatusFlavour; #define FPST_COUNT 10 +/* Architecturally there are 128 PPIs in a GICv5 */ +#define GICV5_NUM_PPIS 128 + typedef struct CPUArchState { /* Regs for current mode. */ uint32_t regs[16]; @@ -600,6 +603,8 @@ typedef struct CPUArchState { struct { /* GICv5 CPU interface data */ uint64_t icc_icsr_el1; + /* Most PPI registers have 1 bit per PPI, so 64 PPIs to a register */ + uint64_t ppi_active[GICV5_NUM_PPIS / 64]; } gicv5_cpuif; struct { diff --git a/target/arm/tcg/gicv5-cpuif.c b/target/arm/tcg/gicv5-cpuif.c index 36d1c196a8..0132b13853 100644 --- a/target/arm/tcg/gicv5-cpuif.c +++ b/target/arm/tcg/gicv5-cpuif.c @@ -175,6 +175,20 @@ static void gic_cdhm_write(CPUARMState *env, const ARMCPRegInfo *ri, gicv5_set_handling(gic, id, hm, domain, type, virtual); } +static void gic_ppi_cactive_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + uint64_t old = raw_read(env, ri); + raw_write(env, ri, old & ~value); +} + +static void gic_ppi_sactive_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + uint64_t old = raw_read(env, ri); + raw_write(env, ri, old | value); +} + static const ARMCPRegInfo gicv5_cpuif_reginfo[] = { /* * Barrier: wait until the effects of a cpuif system register @@ -254,6 +268,30 @@ static const ARMCPRegInfo gicv5_cpuif_reginfo[] = { */ .resetfn = arm_cp_reset_ignore, }, + { .name = "ICC_PPI_CACTIVER0_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 0, + .access = PL1_RW, .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW, + .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_active[0]), + .writefn = gic_ppi_cactive_write, + }, + { .name = "ICC_PPI_CACTIVER1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 1, + .access = PL1_RW, .type = ARM_CP_ALIAS | ARM_CP_IO | ARM_CP_NO_RAW, + .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_active[1]), + .writefn = gic_ppi_cactive_write, + }, + { .name = "ICC_PPI_SACTIVER0_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 2, + .access = PL1_RW, .type = ARM_CP_IO | ARM_CP_NO_RAW, + .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_active[0]), + .writefn = gic_ppi_sactive_write, + }, + { .name = "ICC_PPI_SACTIVER1_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 13, .opc2 = 3, + .access = PL1_RW, .type = ARM_CP_IO | ARM_CP_NO_RAW, + .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.ppi_active[1]), + .writefn = gic_ppi_sactive_write, + }, }; void define_gicv5_cpuif_regs(ARMCPU *cpu) -- 2.43.0
