When a vCPU reset happens, we should also
reset the state of the GIC CPU interface.

Otherwise, reboots might not work as expected
during some circumstances.

Signed-off-by: Mohamed Mediouni <[email protected]>
---
 hw/intc/arm_gicv3_hvf.c | 93 ++++++++++++++++++++++++-----------------
 1 file changed, 54 insertions(+), 39 deletions(-)

diff --git a/hw/intc/arm_gicv3_hvf.c b/hw/intc/arm_gicv3_hvf.c
index 4876446189..ad6e09b4c9 100644
--- a/hw/intc/arm_gicv3_hvf.c
+++ b/hw/intc/arm_gicv3_hvf.c
@@ -257,50 +257,14 @@ static void hvf_gicv3_put_cpu_el2(CPUState *cpu_state, 
run_on_cpu_data arg)
     }
 }
 
-static void hvf_gicv3_put_cpu(CPUState *cpu_state, run_on_cpu_data arg)
+static void hvf_gicv3_put_cpuif(CPUState *cpu_state, run_on_cpu_data arg)
 {
-    uint32_t reg;
     uint64_t reg64;
-    int i, num_pri_bits;
-
+    int num_pri_bits;
     /* Redistributor state */
     GICv3CPUState *c = arg.host_ptr;
     hv_vcpu_t vcpu = c->cpu->accel->fd;
 
-    reg = c->gicr_waker;
-    hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_IGROUPR0, 
reg);
-
-    reg = c->gicr_igroupr0;
-    hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_IGROUPR0, 
reg);
-
-    reg = ~0;
-    hv_gic_set_redistributor_reg(vcpu, 
HV_GIC_REDISTRIBUTOR_REG_GICR_ICENABLER0, reg);
-    reg = c->gicr_ienabler0;
-    hv_gic_set_redistributor_reg(vcpu, 
HV_GIC_REDISTRIBUTOR_REG_GICR_ISENABLER0, reg);
-
-    /* Restore config before pending so we treat level/edge correctly */
-    reg = half_shuffle32(c->edge_trigger >> 16) << 1;
-    hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ICFGR1, 
reg);
-
-    reg = ~0;
-    hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ICPENDR0, 
reg);
-    reg = c->gicr_ipendr0;
-    hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ISPENDR0, 
reg);
-
-    reg = ~0;
-    hv_gic_set_redistributor_reg(vcpu, 
HV_GIC_REDISTRIBUTOR_REG_GICR_ICACTIVER0, reg);
-    reg = c->gicr_iactiver0;
-    hv_gic_set_redistributor_reg(vcpu, 
HV_GIC_REDISTRIBUTOR_REG_GICR_ISACTIVER0, reg);
-
-    for (i = 0; i < GIC_INTERNAL; i += 4) {
-        reg = c->gicr_ipriorityr[i] |
-            (c->gicr_ipriorityr[i + 1] << 8) |
-            (c->gicr_ipriorityr[i + 2] << 16) |
-            (c->gicr_ipriorityr[i + 3] << 24);
-        hv_gic_set_redistributor_reg(vcpu,
-            HV_GIC_REDISTRIBUTOR_REG_GICR_IPRIORITYR0 + i, reg);
-    }
-
     /* CPU interface state */
     hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_SRE_EL1, c->icc_sre_el1);
 
@@ -320,7 +284,7 @@ static void hvf_gicv3_put_cpu(CPUState *cpu_state, 
run_on_cpu_data arg)
 
     switch (num_pri_bits) {
     case 7:
-           reg64 = c->icc_apr[GICV3_G0][3];
+        reg64 = c->icc_apr[GICV3_G0][3];
         hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP0R0_EL1 + 3, reg64);
         reg64 = c->icc_apr[GICV3_G0][2];
         hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP0R0_EL1 + 2, reg64);
@@ -349,6 +313,53 @@ static void hvf_gicv3_put_cpu(CPUState *cpu_state, 
run_on_cpu_data arg)
         reg64 = c->icc_apr[GICV3_G1NS][0];
         hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP1R0_EL1, reg64);
     }
+}
+
+static void hvf_gicv3_put_cpu(CPUState *cpu_state, run_on_cpu_data arg)
+{
+    uint32_t reg;
+    int i;
+
+    /* Redistributor state */
+    GICv3CPUState *c = arg.host_ptr;
+    hv_vcpu_t vcpu = c->cpu->accel->fd;
+
+    reg = c->gicr_waker;
+    hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_IGROUPR0, 
reg);
+
+    reg = c->gicr_igroupr0;
+    hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_IGROUPR0, 
reg);
+
+    reg = ~0;
+    hv_gic_set_redistributor_reg(vcpu, 
HV_GIC_REDISTRIBUTOR_REG_GICR_ICENABLER0, reg);
+    reg = c->gicr_ienabler0;
+    hv_gic_set_redistributor_reg(vcpu, 
HV_GIC_REDISTRIBUTOR_REG_GICR_ISENABLER0, reg);
+
+    /* Restore config before pending so we treat level/edge correctly */
+    reg = half_shuffle32(c->edge_trigger >> 16) << 1;
+    hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ICFGR1, 
reg);
+
+    reg = ~0;
+    hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ICPENDR0, 
reg);
+    reg = c->gicr_ipendr0;
+    hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ISPENDR0, 
reg);
+
+    reg = ~0;
+    hv_gic_set_redistributor_reg(vcpu, 
HV_GIC_REDISTRIBUTOR_REG_GICR_ICACTIVER0, reg);
+    reg = c->gicr_iactiver0;
+    hv_gic_set_redistributor_reg(vcpu, 
HV_GIC_REDISTRIBUTOR_REG_GICR_ISACTIVER0, reg);
+
+    for (i = 0; i < GIC_INTERNAL; i += 4) {
+        reg = c->gicr_ipriorityr[i] |
+            (c->gicr_ipriorityr[i + 1] << 8) |
+            (c->gicr_ipriorityr[i + 2] << 16) |
+            (c->gicr_ipriorityr[i + 3] << 24);
+        hv_gic_set_redistributor_reg(vcpu,
+            HV_GIC_REDISTRIBUTOR_REG_GICR_IPRIORITYR0 + i, reg);
+    }
+
+    /* CPU interface state */
+    hvf_gicv3_put_cpuif(cpu_state, arg);
 
     /* Registers beyond this point are with nested virt only */
     if (c->gic->maint_irq) {
@@ -629,6 +640,7 @@ static void hvf_gicv3_set_irq(void *opaque, int irq, int 
level)
 static void hvf_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)
 {
     GICv3CPUState *c;
+    run_on_cpu_data data;
 
     c = env->gicv3state;
     c->icc_pmr_el1 = 0;
@@ -649,6 +661,9 @@ static void hvf_gicv3_icc_reset(CPUARMState *env, const 
ARMCPRegInfo *ri)
     c->icc_sre_el1 = 0x7;
     memset(c->icc_apr, 0, sizeof(c->icc_apr));
     memset(c->icc_igrpen, 0, sizeof(c->icc_igrpen));
+
+    data.host_ptr = env->gicv3state;
+    run_on_cpu(env_cpu(env), hvf_gicv3_put_cpu, data);
 }
 
 static void hvf_gicv3_reset_hold(Object *obj, ResetType type)
-- 
2.54.0 (Apple Git-157)


Reply via email to