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)
