diff --git a/hw/intc/arm_gicv5_common.c b/hw/intc/arm_gicv5_common.c index 180fe338a4..b155486af6 100644 --- a/hw/intc/arm_gicv5_common.c +++ b/hw/intc/arm_gicv5_common.c @@ -173,9 +173,10 @@ static void gicv5_common_realize(DeviceState *dev, Error **errp) } for (int i = 0; i < cs->num_cpus; i++) { - if (!gicv5_set_gicv5state(cs->cpus[i], cs)) { + if (!gicv5_set_gicv5state(cs->cpus[i], cs, cs->cpu_iaffids[i])) { error_setg(errp, - "CPU %d does not implement GICv5 CPU interface", i); + "CPU %d (IAFFID 0x%x) does not implement GICv5 CPU interface", + i, cs->cpu_iaffids[i]); return; } } diff --git a/include/hw/intc/arm_gicv5_stream.h b/include/hw/intc/arm_gicv5_stream.h index 670423fdad..136b6339ee 100644 --- a/include/hw/intc/arm_gicv5_stream.h +++ b/include/hw/intc/arm_gicv5_stream.h @@ -20,6 +20,7 @@ typedef struct GICv5Common GICv5Common; * gicv5_set_gicv5state * @cpu: CPU object to tell about its IRS * @cs: the GIC IRS it is connected to + * @iaffid: the IAFFID of this CPU * * Set the CPU object's GICv5 pointer to point to this GIC IRS. The * IRS must call this when it is realized, for each CPU it is @@ -28,7 +29,7 @@ typedef struct GICv5Common GICv5Common; * Returns true on success, false if the CPU doesn't implement the * GICv5 CPU interface. */ -bool gicv5_set_gicv5state(ARMCPU *cpu, GICv5Common *cs); +bool gicv5_set_gicv5state(ARMCPU *cpu, GICv5Common *cs, uint32_t iaffid); /* * The architected Stream Protocol is asynchronous; commands can be diff --git a/target/arm/cpu.c b/target/arm/cpu.c index de9ba141bd..29346609e4 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1159,16 +1159,17 @@ static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags) } #ifndef CONFIG_USER_ONLY -bool gicv5_set_gicv5state(ARMCPU *cpu, GICv5Common *cs) +bool gicv5_set_gicv5state(ARMCPU *cpu, GICv5Common *cs, uint32_t iaffid) { /* * Set this CPU's gicv5state pointer to point to the GIC that we are - * connected to. + * connected to, and record our IAFFID. */ if (!cpu_isar_feature(aa64_gcie, cpu)) { return false; } cpu->env.gicv5state = cs; + cpu->env.gicv5_iaffid = iaffid; return true; } #endif diff --git a/target/arm/cpu.h b/target/arm/cpu.h index aa89b457b9..c7c410bed7 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -818,6 +818,8 @@ typedef struct CPUArchState { void *gicv3state; /* Similarly, for a GICv5Common */ void *gicv5state; + /* For GICv5, this CPU's IAFFID */ + uint64_t gicv5_iaffid; #else /* CONFIG_USER_ONLY */ /* For usermode syscall translation. */ bool eabi; diff --git a/target/arm/tcg/gicv5-cpuif.c b/target/arm/tcg/gicv5-cpuif.c index 8cf09791c1..005e2fa8d2 100644 --- a/target/arm/tcg/gicv5-cpuif.c +++ b/target/arm/tcg/gicv5-cpuif.c @@ -226,6 +226,17 @@ static const ARMCPRegInfo gicv5_cpuif_reginfo[] = { .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.icc_icsr_el1), .resetvalue = 0, }, + { .name = "ICC_IAFFIDR_EL1", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 10, .opc2 = 5, + .access = PL1_R, .type = ARM_CP_NO_RAW, + /* ICC_IAFFIDR_EL1 holds the IAFFID only, in its low bits */ + .fieldoffset = offsetof(CPUARMState, gicv5_iaffid), + /* + * The field is a constant value set in gicv5_set_gicv5state(), + * so don't allow it to be overwritten by reset. + */ + .resetfn = arm_cp_reset_ignore, + }, }; void define_gicv5_cpuif_regs(ARMCPU *cpu)