Hi Zenghui, On Tue, 31 Mar 2020 11:12:45 +0800 Zenghui Yu <yuzenghui@xxxxxxxxxx> wrote: > When LPI support is enabled at redistributor level, VGIC will potentially > load the correspond LPI penging table and sync it into the pending_latch. > To avoid keeping the 'consumed' pending bits lying around in guest memory > (though they're not used), let's clear them after synchronization. > > The similar work had been done in vgic_v3_lpi_sync_pending_status(). > > Signed-off-by: Zenghui Yu <yuzenghui@xxxxxxxxxx> > --- > virt/kvm/arm/vgic/vgic-its.c | 23 +++++++++++++++++------ > 1 file changed, 17 insertions(+), 6 deletions(-) > > diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c > index d53d34a33e35..905760bfa404 100644 > --- a/virt/kvm/arm/vgic/vgic-its.c > +++ b/virt/kvm/arm/vgic/vgic-its.c > @@ -435,6 +435,7 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu) > > for (i = 0; i < nr_irqs; i++) { > int byte_offset, bit_nr; > + bool status; > > byte_offset = intids[i] / BITS_PER_BYTE; > bit_nr = intids[i] % BITS_PER_BYTE; > @@ -447,22 +448,32 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu) > ret = kvm_read_guest_lock(vcpu->kvm, > pendbase + byte_offset, > &pendmask, 1); > - if (ret) { > - kfree(intids); > - return ret; > - } > + if (ret) > + goto out; > last_byte_offset = byte_offset; > } > > + status = pendmask & (1 << bit_nr); > + > irq = vgic_get_irq(vcpu->kvm, NULL, intids[i]); > raw_spin_lock_irqsave(&irq->irq_lock, flags); > - irq->pending_latch = pendmask & (1U << bit_nr); > + irq->pending_latch = status; > vgic_queue_irq_unlock(vcpu->kvm, irq, flags); > vgic_put_irq(vcpu->kvm, irq); > + > + if (status) { > + /* clear consumed data */ > + pendmask &= ~(1 << bit_nr); > + ret = kvm_write_guest_lock(vcpu->kvm, > + pendbase + byte_offset, > + &pendmask, 1); > + if (ret) > + goto out; > + } > } > > +out: > kfree(intids); > - > return ret; > } > I've been thinking about this, and I wonder why we don't simply clear the whole pending table instead of carefully wiping it one bit at a time. My reasoning is that if a LPI isn't mapped, then it cannot be made pending the first place. And I think there is a similar issue in vgic_v3_lpi_sync_pending_status(). Why sync something back from the pending table when the LPI wasn't mapped yet? This seems pretty bizarre, as the GITS_TRANSLATER spec says that the write to this register is ignored when: "- The EventID is mapped to an Interrupt Translation Table and the EventID is within the range specified by MAPD on page 5-107, but the EventID is unmapped." (with the added bonus in the form of a type: the first instance of "EventID" here should obviously be "DeviceID"). What do you think? M. -- Jazz is not dead. It just smells funny... _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/mailman/listinfo/kvmarm