Hi, On 05/31/2018 05:15 AM, Shannon Zhao wrote: > While for_each_dist_irq_reg loop starts from GIC_INTERNAL, it forgot to > offset the date array and index. This will overlap the GICR registers > value and leave the last GIC_INTERNAL irq's registers out of update. > > Fixes: 367b9f527becdd20ddf116e17a3c0c2bbc486920 > Cc: qemu-sta...@nongnu.org > Reviewed-by: Peter Maydell <peter.mayd...@linaro.org> Reviewed-by: Eric Auger <eric.au...@redhat.com>
Thanks Eric > Signed-off-by: Shannon Zhao <zhaoshengl...@huawei.com> > --- > hw/intc/arm_gicv3_kvm.c | 18 ++++++++++++++++-- > 1 file changed, 16 insertions(+), 2 deletions(-) > > diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c > index 3536795..147e691 100644 > --- a/hw/intc/arm_gicv3_kvm.c > +++ b/hw/intc/arm_gicv3_kvm.c > @@ -135,7 +135,14 @@ static void kvm_dist_get_priority(GICv3State *s, > uint32_t offset, uint8_t *bmp) > uint32_t reg, *field; > int irq; > > - field = (uint32_t *)bmp; > + /* For the KVM GICv3, affinity routing is always enabled, and the first 8 > + * GICD_IPRIORITYR<n> registers are always RAZ/WI. The corresponding > + * functionality is replaced by GICR_IPRIORITYR<n>. It doesn't need to > + * sync them. So it needs to skip the field of GIC_INTERNAL irqs in bmp > and > + * offset. > + */ > + field = (uint32_t *)(bmp + GIC_INTERNAL); > + offset += (GIC_INTERNAL * 8) / 8; > for_each_dist_irq_reg(irq, s->num_irq, 8) { > kvm_gicd_access(s, offset, ®, false); > *field = reg; > @@ -149,7 +156,14 @@ static void kvm_dist_put_priority(GICv3State *s, > uint32_t offset, uint8_t *bmp) > uint32_t reg, *field; > int irq; > > - field = (uint32_t *)bmp; > + /* For the KVM GICv3, affinity routing is always enabled, and the first 8 > + * GICD_IPRIORITYR<n> registers are always RAZ/WI. The corresponding > + * functionality is replaced by GICR_IPRIORITYR<n>. It doesn't need to > + * sync them. So it needs to skip the field of GIC_INTERNAL irqs in bmp > and > + * offset. > + */ > + field = (uint32_t *)(bmp + GIC_INTERNAL); > + offset += (GIC_INTERNAL * 8) / 8; > for_each_dist_irq_reg(irq, s->num_irq, 8) { > reg = *field; > kvm_gicd_access(s, offset, ®, true); >