@samitouri / QOSamiQemu / commits / 127a41fc00

target/arm: GICv5 cpuif: Implement GIC CDRCFG and ICC_ICSR_EL1

Implement the GIC CDRCFG system instruction, which asks the IRS for the configuration of an interrupt, and the system register ICC_ICSR_EL1 which is where the answer is placed for the guest to read it. We mark ICC_ICSR_EL1 as ARM_CP_NO_RAW, because we do not want to have this migrated as part of the generic "system register" migration arrays. Instead we will do migration via a GICv5 cpuif vmstate section. This is necessary because some of the cpuif registers are banked by interrupt domain and so need special handling to migrate the data in all the banks; it's also how we handle the gicv3 cpuif registers. (We expect that KVM also will expose the cpuif registers via GIC-specific ioctls rather than as generic sysregs.) We'll mark all the GICv5 sysregs as NO_RAW. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Message-id: 20260327111700.795099-27-peter.maydell@linaro.org

Peter Maydell committed Mar 27, 2026 at 11:16 UTC 127a41fc00229a4d40305fa245219e3eabce695c
2 files changed +32
target/arm/cpu.h
+5
@@ -596,6 +596,11 @@ typedef struct CPUArchState {
596 uint64_t vmecid_a_el2;
597 } cp15;
598
599 + struct {
600 + /* GICv5 CPU interface data */
601 + uint64_t icc_icsr_el1;
602 + } gicv5_cpuif;
603 +
604 struct {
605 /* M profile has up to 4 stack pointers:
606 * a Main Stack Pointer and a Process Stack Pointer for each
target/arm/tcg/gicv5-cpuif.c
+27
@@ -35,6 +35,9 @@ FIELD(GIC_CDHM, ID, 0, 24)
35 FIELD(GIC_CDHM, TYPE, 29, 3)
36 FIELD(GIC_CDHM, HM, 32, 1)
37
38 +FIELD(GIC_CDRCFG, ID, 0, 24)
39 +FIELD(GIC_CDRCFG, TYPE, 29, 3)
40 +
41 static GICv5Common *gicv5_get_gic(CPUARMState *env)
42 {
43 return env->gicv5state;
@@ -134,6 +137,19 @@ static void gic_cdpend_write(CPUARMState *env, const ARMCPRegInfo *ri,
137 gicv5_set_pending(gic, id, pending, domain, type, virtual);
138 }
139
140 +static void gic_cdrcfg_write(CPUARMState *env, const ARMCPRegInfo *ri,
141 + uint64_t value)
142 +{
143 + GICv5Common *gic = gicv5_get_gic(env);
144 + GICv5IntType type = FIELD_EX64(value, GIC_CDRCFG, TYPE);
145 + uint32_t id = FIELD_EX64(value, GIC_CDRCFG, ID);
146 + bool virtual = false;
147 + GICv5Domain domain = gicv5_current_phys_domain(env);
148 +
149 + env->gicv5_cpuif.icc_icsr_el1 =
150 + gicv5_request_config(gic, id, domain, type, virtual);
151 +}
152 +
153 static void gic_cdhm_write(CPUARMState *env, const ARMCPRegInfo *ri,
154 uint64_t value)
155 {
@@ -194,11 +210,22 @@ static const ARMCPRegInfo gicv5_cpuif_reginfo[] = {
210 .access = PL1_W, .type = ARM_CP_IO | ARM_CP_NO_RAW,
211 .writefn = gic_cdpend_write,
212 },
213 + { .name = "GIC_CDRCFG", .state = ARM_CP_STATE_AA64,
214 + .opc0 = 1, .opc1 = 0, .crn = 12, .crm = 1, .opc2 = 5,
215 + .access = PL1_W, .type = ARM_CP_IO | ARM_CP_NO_RAW,
216 + .writefn = gic_cdrcfg_write,
217 + },
218 { .name = "GIC_CDHM", .state = ARM_CP_STATE_AA64,
219 .opc0 = 1, .opc1 = 0, .crn = 12, .crm = 2, .opc2 = 1,
220 .access = PL1_W, .type = ARM_CP_IO | ARM_CP_NO_RAW,
221 .writefn = gic_cdhm_write,
222 },
223 + { .name = "ICC_ICSR_EL1", .state = ARM_CP_STATE_AA64,
224 + .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 10, .opc2 = 4,
225 + .access = PL1_RW, .type = ARM_CP_NO_RAW,
226 + .fieldoffset = offsetof(CPUARMState, gicv5_cpuif.icc_icsr_el1),
227 + .resetvalue = 0,
228 + },
229 };
230
231 void define_gicv5_cpuif_regs(ARMCPU *cpu)